diff options
author | Eric Moore <eric.moore@lsi.com> | 2007-01-29 11:47:47 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-02-02 22:10:55 -0500 |
commit | cd2c61911dfe0d87cb872571739d5838cc233747 (patch) | |
tree | b6daf2d0d3208cc767ccc4482ad71f70f6c16d08 /drivers/message | |
parent | 2ecce492290bf0d5eedc76cf0f4bf45f8c3f42bc (diff) |
[SCSI] fusion - error handling bug fix's
misc error handling bug fix's
- properly interpret iocstatus returned after task management request
- clear tmState after a failed doorbell
- cleanup mptscsih_taskmgmt_complete
Signed-off-by: Eric Moore <Eric.Moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/message')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 14 | ||||
-rw-r--r-- | drivers/message/fusion/mptctl.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 295 |
3 files changed, 153 insertions, 158 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index e7aec3478a30..fcbce1c31d04 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -916,7 +916,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) | |||
916 | int | 916 | int |
917 | mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) | 917 | mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) |
918 | { | 918 | { |
919 | int r = 0; | 919 | int r = 0; |
920 | u8 *req_as_bytes; | 920 | u8 *req_as_bytes; |
921 | int ii; | 921 | int ii; |
922 | 922 | ||
@@ -3219,6 +3219,9 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3219 | u32 diag1val = 0; | 3219 | u32 diag1val = 0; |
3220 | #endif | 3220 | #endif |
3221 | 3221 | ||
3222 | /* Clear any existing interrupts */ | ||
3223 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | ||
3224 | |||
3222 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { | 3225 | if (ioc->pcidev->device == MPI_MANUFACTPAGE_DEVID_SAS1078) { |
3223 | drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " | 3226 | drsprintk((MYIOC_s_WARN_FMT "%s: Doorbell=%p; 1078 reset " |
3224 | "address=%p\n", ioc->name, __FUNCTION__, | 3227 | "address=%p\n", ioc->name, __FUNCTION__, |
@@ -3238,7 +3241,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3238 | " count=%d\n", | 3241 | " count=%d\n", |
3239 | ioc->name, doorbell, count)); | 3242 | ioc->name, doorbell, count)); |
3240 | if (doorbell == MPI_IOC_STATE_READY) { | 3243 | if (doorbell == MPI_IOC_STATE_READY) { |
3241 | return 0; | 3244 | return 1; |
3242 | } | 3245 | } |
3243 | 3246 | ||
3244 | /* wait 1 sec */ | 3247 | /* wait 1 sec */ |
@@ -3250,9 +3253,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3250 | return -1; | 3253 | return -1; |
3251 | } | 3254 | } |
3252 | 3255 | ||
3253 | /* Clear any existing interrupts */ | ||
3254 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | ||
3255 | |||
3256 | /* Use "Diagnostic reset" method! (only thing available!) */ | 3256 | /* Use "Diagnostic reset" method! (only thing available!) */ |
3257 | diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); | 3257 | diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); |
3258 | 3258 | ||
@@ -3968,7 +3968,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) | |||
3968 | } | 3968 | } |
3969 | } else { | 3969 | } else { |
3970 | while (--cntdn) { | 3970 | while (--cntdn) { |
3971 | mdelay (1); | 3971 | udelay (1000); |
3972 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); | 3972 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); |
3973 | if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) | 3973 | if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS)) |
3974 | break; | 3974 | break; |
@@ -4020,7 +4020,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) | |||
4020 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); | 4020 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); |
4021 | if (intstat & MPI_HIS_DOORBELL_INTERRUPT) | 4021 | if (intstat & MPI_HIS_DOORBELL_INTERRUPT) |
4022 | break; | 4022 | break; |
4023 | mdelay(1); | 4023 | udelay (1000); |
4024 | count++; | 4024 | count++; |
4025 | } | 4025 | } |
4026 | } | 4026 | } |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 922d0c879f06..4779ff502e53 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
@@ -313,7 +313,7 @@ static void mptctl_timeout_expired (MPT_IOCTL *ioctl) | |||
313 | */ | 313 | */ |
314 | dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", | 314 | dctlprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", |
315 | ioctl->ioc->name)); | 315 | ioctl->ioc->name)); |
316 | mpt_HardResetHandler(ioctl->ioc, NO_SLEEP); | 316 | mpt_HardResetHandler(ioctl->ioc, CAN_SLEEP); |
317 | } | 317 | } |
318 | return; | 318 | return; |
319 | 319 | ||
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index f9e11c8db462..3bc9446ec42d 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -1536,7 +1536,7 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1536 | */ | 1536 | */ |
1537 | 1537 | ||
1538 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1538 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1539 | /* | 1539 | /** |
1540 | * mptscsih_TMHandler - Generic handler for SCSI Task Management. | 1540 | * mptscsih_TMHandler - Generic handler for SCSI Task Management. |
1541 | * Fall through to mpt_HardResetHandler if: not operational, too many | 1541 | * Fall through to mpt_HardResetHandler if: not operational, too many |
1542 | * failed TM requests or handshake failure. | 1542 | * failed TM requests or handshake failure. |
@@ -1552,28 +1552,17 @@ mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx) | |||
1552 | * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC | 1552 | * Remark: With old EH code, at most 1 SCSI TaskMgmt function per IOC |
1553 | * will be active. | 1553 | * will be active. |
1554 | * | 1554 | * |
1555 | * Returns 0 for SUCCESS or -1 if FAILED. | 1555 | * Returns 0 for SUCCESS, or FAILED. |
1556 | */ | 1556 | **/ |
1557 | int | 1557 | int |
1558 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | 1558 | mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) |
1559 | { | 1559 | { |
1560 | MPT_ADAPTER *ioc; | 1560 | MPT_ADAPTER *ioc; |
1561 | int rc = -1; | 1561 | int rc = -1; |
1562 | int doTask = 1; | ||
1563 | u32 ioc_raw_state; | 1562 | u32 ioc_raw_state; |
1564 | unsigned long flags; | 1563 | unsigned long flags; |
1565 | 1564 | ||
1566 | /* If FW is being reloaded currently, return success to | ||
1567 | * the calling function. | ||
1568 | */ | ||
1569 | if (hd == NULL) | ||
1570 | return 0; | ||
1571 | |||
1572 | ioc = hd->ioc; | 1565 | ioc = hd->ioc; |
1573 | if (ioc == NULL) { | ||
1574 | printk(KERN_ERR MYNAM " TMHandler" " NULL ioc!\n"); | ||
1575 | return FAILED; | ||
1576 | } | ||
1577 | dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); | 1566 | dtmprintk((MYIOC_s_INFO_FMT "TMHandler Entered!\n", ioc->name)); |
1578 | 1567 | ||
1579 | // SJR - CHECKME - Can we avoid this here? | 1568 | // SJR - CHECKME - Can we avoid this here? |
@@ -1586,8 +1575,10 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c | |||
1586 | spin_unlock_irqrestore(&ioc->diagLock, flags); | 1575 | spin_unlock_irqrestore(&ioc->diagLock, flags); |
1587 | 1576 | ||
1588 | /* Wait a fixed amount of time for the TM pending flag to be cleared. | 1577 | /* Wait a fixed amount of time for the TM pending flag to be cleared. |
1589 | * If we time out and not bus reset, then we return a FAILED status to the caller. | 1578 | * If we time out and not bus reset, then we return a FAILED status |
1590 | * The call to mptscsih_tm_pending_wait() will set the pending flag if we are | 1579 | * to the caller. |
1580 | * The call to mptscsih_tm_pending_wait() will set the pending flag | ||
1581 | * if we are | ||
1591 | * successful. Otherwise, reload the FW. | 1582 | * successful. Otherwise, reload the FW. |
1592 | */ | 1583 | */ |
1593 | if (mptscsih_tm_pending_wait(hd) == FAILED) { | 1584 | if (mptscsih_tm_pending_wait(hd) == FAILED) { |
@@ -1597,18 +1588,16 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c | |||
1597 | hd->ioc->name, hd->tmPending)); | 1588 | hd->ioc->name, hd->tmPending)); |
1598 | return FAILED; | 1589 | return FAILED; |
1599 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { | 1590 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { |
1600 | dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target reset: " | 1591 | dtmprintk((KERN_INFO MYNAM ": %s: TMHandler target " |
1601 | "Timed out waiting for last TM (%d) to complete! \n", | 1592 | "reset: Timed out waiting for last TM (%d) " |
1602 | hd->ioc->name, hd->tmPending)); | 1593 | "to complete! \n", hd->ioc->name, |
1594 | hd->tmPending)); | ||
1603 | return FAILED; | 1595 | return FAILED; |
1604 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { | 1596 | } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { |
1605 | dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " | 1597 | dtmprintk((KERN_INFO MYNAM ": %s: TMHandler bus reset: " |
1606 | "Timed out waiting for last TM (%d) to complete! \n", | 1598 | "Timed out waiting for last TM (%d) to complete! \n", |
1607 | hd->ioc->name, hd->tmPending)); | 1599 | hd->ioc->name, hd->tmPending)); |
1608 | if (hd->tmPending & (1 << MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS)) | 1600 | return FAILED; |
1609 | return FAILED; | ||
1610 | |||
1611 | doTask = 0; | ||
1612 | } | 1601 | } |
1613 | } else { | 1602 | } else { |
1614 | spin_lock_irqsave(&hd->ioc->FreeQlock, flags); | 1603 | spin_lock_irqsave(&hd->ioc->FreeQlock, flags); |
@@ -1616,47 +1605,40 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c | |||
1616 | spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); | 1605 | spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); |
1617 | } | 1606 | } |
1618 | 1607 | ||
1619 | /* Is operational? | ||
1620 | */ | ||
1621 | ioc_raw_state = mpt_GetIocState(hd->ioc, 0); | 1608 | ioc_raw_state = mpt_GetIocState(hd->ioc, 0); |
1622 | 1609 | ||
1623 | #ifdef MPT_DEBUG_RESET | ||
1624 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { | 1610 | if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { |
1625 | printk(MYIOC_s_WARN_FMT | 1611 | printk(MYIOC_s_WARN_FMT |
1626 | "TM Handler: IOC Not operational(0x%x)!\n", | 1612 | "TM Handler for type=%x: IOC Not operational (0x%x)!\n", |
1627 | hd->ioc->name, ioc_raw_state); | 1613 | ioc->name, type, ioc_raw_state); |
1628 | } | 1614 | printk(KERN_WARNING " Issuing HardReset!!\n"); |
1629 | #endif | 1615 | if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) |
1630 | 1616 | printk((KERN_WARNING "TMHandler: HardReset " | |
1631 | if (doTask && ((ioc_raw_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) | 1617 | "FAILED!!\n")); |
1632 | && !(ioc_raw_state & MPI_DOORBELL_ACTIVE)) { | 1618 | return FAILED; |
1633 | |||
1634 | /* Isse the Task Mgmt request. | ||
1635 | */ | ||
1636 | if (hd->hard_resets < -1) | ||
1637 | hd->hard_resets++; | ||
1638 | rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, ctx2abort, timeout); | ||
1639 | if (rc) { | ||
1640 | printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); | ||
1641 | } else { | ||
1642 | dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); | ||
1643 | } | ||
1644 | } | 1619 | } |
1645 | 1620 | ||
1646 | /* Only fall through to the HRH if this is a bus reset | 1621 | if (ioc_raw_state & MPI_DOORBELL_ACTIVE) { |
1647 | */ | 1622 | printk(MYIOC_s_WARN_FMT |
1648 | if ((type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) && (rc || | 1623 | "TM Handler for type=%x: ioc_state: " |
1649 | ioc->reload_fw || (ioc->alt_ioc && ioc->alt_ioc->reload_fw))) { | 1624 | "DOORBELL_ACTIVE (0x%x)!\n", |
1650 | dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", | 1625 | ioc->name, type, ioc_raw_state); |
1651 | hd->ioc->name)); | 1626 | return FAILED; |
1652 | rc = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); | ||
1653 | } | 1627 | } |
1654 | 1628 | ||
1655 | /* | 1629 | /* Isse the Task Mgmt request. |
1656 | * Check IOCStatus from TM reply message | ||
1657 | */ | 1630 | */ |
1658 | if (hd->tm_iocstatus != MPI_IOCSTATUS_SUCCESS) | 1631 | if (hd->hard_resets < -1) |
1659 | rc = FAILED; | 1632 | hd->hard_resets++; |
1633 | |||
1634 | rc = mptscsih_IssueTaskMgmt(hd, type, channel, id, lun, | ||
1635 | ctx2abort, timeout); | ||
1636 | if (rc) | ||
1637 | printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", | ||
1638 | hd->ioc->name); | ||
1639 | else | ||
1640 | dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", | ||
1641 | hd->ioc->name)); | ||
1660 | 1642 | ||
1661 | dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); | 1643 | dtmprintk((MYIOC_s_INFO_FMT "TMHandler rc = %d!\n", hd->ioc->name, rc)); |
1662 | 1644 | ||
@@ -1665,7 +1647,7 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c | |||
1665 | 1647 | ||
1666 | 1648 | ||
1667 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1649 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1668 | /* | 1650 | /** |
1669 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. | 1651 | * mptscsih_IssueTaskMgmt - Generic send Task Management function. |
1670 | * @hd: Pointer to MPT_SCSI_HOST structure | 1652 | * @hd: Pointer to MPT_SCSI_HOST structure |
1671 | * @type: Task Management type | 1653 | * @type: Task Management type |
@@ -1678,9 +1660,9 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c | |||
1678 | * | 1660 | * |
1679 | * Not all fields are meaningfull for all task types. | 1661 | * Not all fields are meaningfull for all task types. |
1680 | * | 1662 | * |
1681 | * Returns 0 for SUCCESS, -999 for "no msg frames", | 1663 | * Returns 0 for SUCCESS, or FAILED. |
1682 | * else other non-zero value returned. | 1664 | * |
1683 | */ | 1665 | **/ |
1684 | static int | 1666 | static int |
1685 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) | 1667 | mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout) |
1686 | { | 1668 | { |
@@ -1720,32 +1702,52 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i | |||
1720 | 1702 | ||
1721 | pScsiTm->TaskMsgContext = ctx2abort; | 1703 | pScsiTm->TaskMsgContext = ctx2abort; |
1722 | 1704 | ||
1723 | dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n", | 1705 | dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " |
1724 | hd->ioc->name, ctx2abort, type)); | 1706 | "type=%d\n", hd->ioc->name, ctx2abort, type)); |
1725 | 1707 | ||
1726 | DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); | 1708 | DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm); |
1727 | 1709 | ||
1728 | if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, | 1710 | if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, |
1729 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, | 1711 | sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { |
1730 | CAN_SLEEP)) != 0) { | 1712 | dfailprintk((MYIOC_s_ERR_FMT "send_handshake FAILED!" |
1731 | dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!" | 1713 | " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, |
1732 | " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, | 1714 | hd->ioc, mf, retval)); |
1733 | hd->ioc, mf)); | 1715 | goto fail_out; |
1734 | mpt_free_msg_frame(hd->ioc, mf); | ||
1735 | return retval; | ||
1736 | } | 1716 | } |
1737 | 1717 | ||
1738 | if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { | 1718 | if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { |
1739 | dfailprintk((MYIOC_s_ERR_FMT "_wait_for_completion FAILED!" | 1719 | dfailprintk((MYIOC_s_ERR_FMT "task management request TIMED OUT!" |
1740 | " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, | 1720 | " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, |
1741 | hd->ioc, mf)); | 1721 | hd->ioc, mf)); |
1742 | mpt_free_msg_frame(hd->ioc, mf); | ||
1743 | dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", | 1722 | dtmprintk((MYIOC_s_INFO_FMT "Calling HardReset! \n", |
1744 | hd->ioc->name)); | 1723 | hd->ioc->name)); |
1745 | retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); | 1724 | retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); |
1725 | dtmprintk((MYIOC_s_INFO_FMT "rc=%d \n", | ||
1726 | hd->ioc->name, retval)); | ||
1727 | goto fail_out; | ||
1746 | } | 1728 | } |
1747 | 1729 | ||
1730 | /* | ||
1731 | * Handle success case, see if theres a non-zero ioc_status. | ||
1732 | */ | ||
1733 | if (hd->tm_iocstatus == MPI_IOCSTATUS_SUCCESS || | ||
1734 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_TASK_TERMINATED || | ||
1735 | hd->tm_iocstatus == MPI_IOCSTATUS_SCSI_IOC_TERMINATED) | ||
1736 | retval = 0; | ||
1737 | else | ||
1738 | retval = FAILED; | ||
1739 | |||
1748 | return retval; | 1740 | return retval; |
1741 | |||
1742 | fail_out: | ||
1743 | |||
1744 | /* | ||
1745 | * Free task managment mf, and corresponding tm flags | ||
1746 | */ | ||
1747 | mpt_free_msg_frame(hd->ioc, mf); | ||
1748 | hd->tmPending = 0; | ||
1749 | hd->tmState = TM_STATE_NONE; | ||
1750 | return FAILED; | ||
1749 | } | 1751 | } |
1750 | 1752 | ||
1751 | static int | 1753 | static int |
@@ -1770,7 +1772,7 @@ mptscsih_get_tm_timeout(MPT_ADAPTER *ioc) | |||
1770 | * (linux scsi_host_template.eh_abort_handler routine) | 1772 | * (linux scsi_host_template.eh_abort_handler routine) |
1771 | * | 1773 | * |
1772 | * Returns SUCCESS or FAILED. | 1774 | * Returns SUCCESS or FAILED. |
1773 | */ | 1775 | **/ |
1774 | int | 1776 | int |
1775 | mptscsih_abort(struct scsi_cmnd * SCpnt) | 1777 | mptscsih_abort(struct scsi_cmnd * SCpnt) |
1776 | { | 1778 | { |
@@ -1806,9 +1808,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1806 | return SUCCESS; | 1808 | return SUCCESS; |
1807 | } | 1809 | } |
1808 | 1810 | ||
1809 | if (hd->resetPending) { | 1811 | if (hd->resetPending) |
1810 | return FAILED; | 1812 | return FAILED; |
1811 | } | ||
1812 | 1813 | ||
1813 | if (hd->timeouts < -1) | 1814 | if (hd->timeouts < -1) |
1814 | hd->timeouts++; | 1815 | hd->timeouts++; |
@@ -1835,9 +1836,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1835 | ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); | 1836 | ctx2abort, mptscsih_get_tm_timeout(hd->ioc)); |
1836 | 1837 | ||
1837 | if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && | 1838 | if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && |
1838 | SCpnt->serial_number == sn) { | 1839 | SCpnt->serial_number == sn) |
1839 | retval = FAILED; | 1840 | retval = FAILED; |
1840 | } | ||
1841 | 1841 | ||
1842 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", | 1842 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", |
1843 | hd->ioc->name, | 1843 | hd->ioc->name, |
@@ -1845,12 +1845,8 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1845 | 1845 | ||
1846 | if (retval == 0) | 1846 | if (retval == 0) |
1847 | return SUCCESS; | 1847 | return SUCCESS; |
1848 | 1848 | else | |
1849 | if(retval != FAILED ) { | 1849 | return FAILED; |
1850 | hd->tmPending = 0; | ||
1851 | hd->tmState = TM_STATE_NONE; | ||
1852 | } | ||
1853 | return FAILED; | ||
1854 | } | 1850 | } |
1855 | 1851 | ||
1856 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1852 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -1861,7 +1857,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1861 | * (linux scsi_host_template.eh_dev_reset_handler routine) | 1857 | * (linux scsi_host_template.eh_dev_reset_handler routine) |
1862 | * | 1858 | * |
1863 | * Returns SUCCESS or FAILED. | 1859 | * Returns SUCCESS or FAILED. |
1864 | */ | 1860 | **/ |
1865 | int | 1861 | int |
1866 | mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | 1862 | mptscsih_dev_reset(struct scsi_cmnd * SCpnt) |
1867 | { | 1863 | { |
@@ -1896,14 +1892,11 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1896 | 1892 | ||
1897 | if (retval == 0) | 1893 | if (retval == 0) |
1898 | return SUCCESS; | 1894 | return SUCCESS; |
1899 | 1895 | else | |
1900 | if(retval != FAILED ) { | 1896 | return FAILED; |
1901 | hd->tmPending = 0; | ||
1902 | hd->tmState = TM_STATE_NONE; | ||
1903 | } | ||
1904 | return FAILED; | ||
1905 | } | 1897 | } |
1906 | 1898 | ||
1899 | |||
1907 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1900 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1908 | /** | 1901 | /** |
1909 | * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant | 1902 | * mptscsih_bus_reset - Perform a SCSI BUS_RESET! new_eh variant |
@@ -1912,7 +1905,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1912 | * (linux scsi_host_template.eh_bus_reset_handler routine) | 1905 | * (linux scsi_host_template.eh_bus_reset_handler routine) |
1913 | * | 1906 | * |
1914 | * Returns SUCCESS or FAILED. | 1907 | * Returns SUCCESS or FAILED. |
1915 | */ | 1908 | **/ |
1916 | int | 1909 | int |
1917 | mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | 1910 | mptscsih_bus_reset(struct scsi_cmnd * SCpnt) |
1918 | { | 1911 | { |
@@ -1946,12 +1939,8 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | |||
1946 | 1939 | ||
1947 | if (retval == 0) | 1940 | if (retval == 0) |
1948 | return SUCCESS; | 1941 | return SUCCESS; |
1949 | 1942 | else | |
1950 | if(retval != FAILED ) { | 1943 | return FAILED; |
1951 | hd->tmPending = 0; | ||
1952 | hd->tmState = TM_STATE_NONE; | ||
1953 | } | ||
1954 | return FAILED; | ||
1955 | } | 1944 | } |
1956 | 1945 | ||
1957 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1946 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2034,7 +2023,6 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) | |||
2034 | /** | 2023 | /** |
2035 | * mptscsih_tm_wait_for_completion - wait for completion of TM task | 2024 | * mptscsih_tm_wait_for_completion - wait for completion of TM task |
2036 | * @hd: Pointer to MPT host structure. | 2025 | * @hd: Pointer to MPT host structure. |
2037 | * @timeout: timeout in seconds | ||
2038 | * | 2026 | * |
2039 | * Returns {SUCCESS,FAILED}. | 2027 | * Returns {SUCCESS,FAILED}. |
2040 | */ | 2028 | */ |
@@ -2108,7 +2096,7 @@ mptscsih_taskmgmt_response_code(MPT_ADAPTER *ioc, u8 response_code) | |||
2108 | * load/init time via the mpt_register() API call. | 2096 | * load/init time via the mpt_register() API call. |
2109 | * | 2097 | * |
2110 | * Returns 1 indicating alloc'd request frame ptr should be freed. | 2098 | * Returns 1 indicating alloc'd request frame ptr should be freed. |
2111 | */ | 2099 | **/ |
2112 | int | 2100 | int |
2113 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2101 | mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) |
2114 | { | 2102 | { |
@@ -2118,78 +2106,85 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m | |||
2118 | unsigned long flags; | 2106 | unsigned long flags; |
2119 | u16 iocstatus; | 2107 | u16 iocstatus; |
2120 | u8 tmType; | 2108 | u8 tmType; |
2109 | u32 termination_count; | ||
2121 | 2110 | ||
2122 | dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", | 2111 | dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n", |
2123 | ioc->name, mf, mr)); | 2112 | ioc->name, mf, mr)); |
2124 | if (ioc->sh) { | 2113 | if (!ioc->sh) { |
2125 | /* Depending on the thread, a timer is activated for | 2114 | dtmprintk((MYIOC_s_WARN_FMT |
2126 | * the TM request. Delete this timer on completion of TM. | 2115 | "TaskMgmt Complete: NULL Scsi Host Ptr\n", ioc->name)); |
2127 | * Decrement count of outstanding TM requests. | ||
2128 | */ | ||
2129 | hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; | ||
2130 | } else { | ||
2131 | dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n", | ||
2132 | ioc->name)); | ||
2133 | return 1; | 2116 | return 1; |
2134 | } | 2117 | } |
2135 | 2118 | ||
2136 | if (mr == NULL) { | 2119 | if (mr == NULL) { |
2137 | dtmprintk((MYIOC_s_WARN_FMT "ERROR! TaskMgmt Reply: NULL Request %p\n", | 2120 | dtmprintk((MYIOC_s_WARN_FMT |
2138 | ioc->name, mf)); | 2121 | "ERROR! TaskMgmt Reply: NULL Request %p\n", ioc->name, mf)); |
2139 | return 1; | 2122 | return 1; |
2140 | } else { | 2123 | } |
2141 | pScsiTmReply = (SCSITaskMgmtReply_t*)mr; | ||
2142 | pScsiTmReq = (SCSITaskMgmt_t*)mf; | ||
2143 | 2124 | ||
2144 | /* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */ | 2125 | hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; |
2145 | tmType = pScsiTmReq->TaskType; | 2126 | pScsiTmReply = (SCSITaskMgmtReply_t*)mr; |
2127 | pScsiTmReq = (SCSITaskMgmt_t*)mf; | ||
2128 | tmType = pScsiTmReq->TaskType; | ||
2129 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2130 | termination_count = le32_to_cpu(pScsiTmReply->TerminationCount); | ||
2131 | |||
2132 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && | ||
2133 | pScsiTmReply->ResponseCode) | ||
2134 | mptscsih_taskmgmt_response_code(ioc, | ||
2135 | pScsiTmReply->ResponseCode); | ||
2136 | DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); | ||
2137 | |||
2138 | #if defined(MPT_DEBUG_REPLY) || defined(MPT_DEBUG_TM) | ||
2139 | printk("%s: ha=%d [%d:%d:0] task_type=0x%02X " | ||
2140 | "iocstatus=0x%04X\n\tloginfo=0x%08X response_code=0x%02X " | ||
2141 | "term_cmnds=%d\n", __FUNCTION__, ioc->id, pScsiTmReply->Bus, | ||
2142 | pScsiTmReply->TargetID, pScsiTmReq->TaskType, | ||
2143 | le16_to_cpu(pScsiTmReply->IOCStatus), | ||
2144 | le32_to_cpu(pScsiTmReply->IOCLogInfo),pScsiTmReply->ResponseCode, | ||
2145 | le32_to_cpu(pScsiTmReply->TerminationCount)); | ||
2146 | #endif | ||
2147 | if (!iocstatus) { | ||
2148 | dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); | ||
2149 | hd->abortSCpnt = NULL; | ||
2150 | goto out; | ||
2151 | } | ||
2146 | 2152 | ||
2147 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05 && | 2153 | /* Error? (anything non-zero?) */ |
2148 | pScsiTmReply->ResponseCode) | ||
2149 | mptscsih_taskmgmt_response_code(ioc, | ||
2150 | pScsiTmReply->ResponseCode); | ||
2151 | 2154 | ||
2152 | dtmprintk((MYIOC_s_WARN_FMT " TaskType = %d, TerminationCount=%d\n", | 2155 | /* clear flags and continue. |
2153 | ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount))); | 2156 | */ |
2154 | DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply); | 2157 | switch (tmType) { |
2155 | 2158 | ||
2156 | iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK; | 2159 | case MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK: |
2157 | hd->tm_iocstatus = iocstatus; | 2160 | if (termination_count == 1) |
2158 | dtmprintk((MYIOC_s_WARN_FMT " SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n", | 2161 | iocstatus = MPI_IOCSTATUS_SCSI_TASK_TERMINATED; |
2159 | ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo))); | 2162 | hd->abortSCpnt = NULL; |
2160 | /* Error? (anything non-zero?) */ | 2163 | break; |
2161 | if (iocstatus) { | ||
2162 | 2164 | ||
2163 | /* clear flags and continue. | 2165 | case MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS: |
2164 | */ | ||
2165 | if (tmType == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) | ||
2166 | hd->abortSCpnt = NULL; | ||
2167 | 2166 | ||
2168 | /* If an internal command is present | 2167 | /* If an internal command is present |
2169 | * or the TM failed - reload the FW. | 2168 | * or the TM failed - reload the FW. |
2170 | * FC FW may respond FAILED to an ABORT | 2169 | * FC FW may respond FAILED to an ABORT |
2171 | */ | 2170 | */ |
2172 | if (tmType == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { | 2171 | if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || |
2173 | if ((hd->cmdPtr) || | 2172 | hd->cmdPtr) |
2174 | (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED)) { | 2173 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) |
2175 | if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { | 2174 | printk((KERN_WARNING " Firmware Reload FAILED!!\n")); |
2176 | printk((KERN_WARNING | 2175 | break; |
2177 | " Firmware Reload FAILED!!\n")); | ||
2178 | } | ||
2179 | } | ||
2180 | } | ||
2181 | } else { | ||
2182 | dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name)); | ||
2183 | |||
2184 | hd->abortSCpnt = NULL; | ||
2185 | 2176 | ||
2186 | } | 2177 | case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: |
2178 | default: | ||
2179 | break; | ||
2187 | } | 2180 | } |
2188 | 2181 | ||
2182 | out: | ||
2189 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 2183 | spin_lock_irqsave(&ioc->FreeQlock, flags); |
2190 | hd->tmPending = 0; | 2184 | hd->tmPending = 0; |
2191 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2192 | hd->tmState = TM_STATE_NONE; | 2185 | hd->tmState = TM_STATE_NONE; |
2186 | hd->tm_iocstatus = iocstatus; | ||
2187 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2193 | 2188 | ||
2194 | return 1; | 2189 | return 1; |
2195 | } | 2190 | } |