diff options
author | Kashyap, Desai <kashyap.desai@lsi.com> | 2009-05-29 07:14:06 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-09 18:27:49 -0400 |
commit | 37c60f374a855974c27bd30d5662a8fa5e933792 (patch) | |
tree | 98e1ee9a5f54152a7dfaf9f320a87fde791f544e /drivers/message/fusion/mptscsih.c | |
parent | f0f09d3b3f06900d64971625d6753dea0623ed45 (diff) |
[SCSI] mpt fusion: rewrite of all internal generated functions
Rewrite of all internal generated functions that issue commands to firmware,
porting them to be single threaded using the generic MPT_MGMT
struct. Implemented using completion Queue.
Signed-off-by: Kashyap Desai <kadesai@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/message/fusion/mptscsih.c')
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 514 |
1 files changed, 211 insertions, 303 deletions
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 8c08c73f194c..35173252e948 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -100,6 +100,8 @@ static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, | |||
100 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); | 100 | int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset); |
101 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); | 101 | int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); |
102 | 102 | ||
103 | static int mptscsih_get_completion_code(MPT_ADAPTER *ioc, | ||
104 | MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply); | ||
103 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); | 105 | int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); |
104 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 106 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
105 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); | 107 | static void mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice); |
@@ -2571,94 +2573,35 @@ int | |||
2571 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 2573 | mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
2572 | { | 2574 | { |
2573 | MPT_SCSI_HOST *hd; | 2575 | MPT_SCSI_HOST *hd; |
2574 | unsigned long flags; | ||
2575 | |||
2576 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2577 | ": IOC %s_reset routed to SCSI host driver!\n", | ||
2578 | ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | ||
2579 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | ||
2580 | 2576 | ||
2581 | /* If a FW reload request arrives after base installed but | ||
2582 | * before all scsi hosts have been attached, then an alt_ioc | ||
2583 | * may have a NULL sh pointer. | ||
2584 | */ | ||
2585 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) | 2577 | if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) |
2586 | return 0; | 2578 | return 0; |
2587 | else | ||
2588 | hd = shost_priv(ioc->sh); | ||
2589 | |||
2590 | if (reset_phase == MPT_IOC_SETUP_RESET) { | ||
2591 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); | ||
2592 | 2579 | ||
2593 | /* Clean Up: | 2580 | hd = shost_priv(ioc->sh); |
2594 | * 1. Set Hard Reset Pending Flag | 2581 | switch (reset_phase) { |
2595 | * All new commands go to doneQ | 2582 | case MPT_IOC_SETUP_RESET: |
2596 | */ | 2583 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2584 | "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__)); | ||
2597 | hd->resetPending = 1; | 2585 | hd->resetPending = 1; |
2598 | 2586 | break; | |
2599 | } else if (reset_phase == MPT_IOC_PRE_RESET) { | 2587 | case MPT_IOC_PRE_RESET: |
2600 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Diag Reset\n", ioc->name)); | 2588 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2601 | 2589 | "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__)); | |
2602 | /* 2. Flush running commands | ||
2603 | * Clean ScsiLookup (and associated memory) | ||
2604 | * AND clean mytaskQ | ||
2605 | */ | ||
2606 | |||
2607 | /* 2b. Reply to OS all known outstanding I/O commands. | ||
2608 | */ | ||
2609 | mptscsih_flush_running_cmds(hd); | ||
2610 | |||
2611 | /* 2c. If there was an internal command that | ||
2612 | * has not completed, configuration or io request, | ||
2613 | * free these resources. | ||
2614 | */ | ||
2615 | if (hd->cmdPtr) { | ||
2616 | del_timer(&hd->timer); | ||
2617 | mpt_free_msg_frame(ioc, hd->cmdPtr); | ||
2618 | } | ||
2619 | |||
2620 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Pre-Reset complete.\n", ioc->name)); | ||
2621 | |||
2622 | } else { | ||
2623 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Diag Reset\n", ioc->name)); | ||
2624 | |||
2625 | /* Once a FW reload begins, all new OS commands are | ||
2626 | * redirected to the doneQ w/ a reset status. | ||
2627 | * Init all control structures. | ||
2628 | */ | ||
2629 | |||
2630 | /* 2. Chain Buffer initialization | ||
2631 | */ | ||
2632 | |||
2633 | /* 4. Renegotiate to all devices, if SPI | ||
2634 | */ | ||
2635 | |||
2636 | /* 5. Enable new commands to be posted | ||
2637 | */ | ||
2638 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
2639 | hd->tmPending = 0; | ||
2640 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
2641 | hd->resetPending = 0; | 2590 | hd->resetPending = 0; |
2642 | hd->tmState = TM_STATE_NONE; | 2591 | mptscsih_flush_running_cmds(hd); |
2643 | 2592 | break; | |
2644 | /* 6. If there was an internal command, | 2593 | case MPT_IOC_POST_RESET: |
2645 | * wake this process up. | 2594 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2646 | */ | 2595 | "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__)); |
2647 | if (hd->cmdPtr) { | 2596 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING) { |
2648 | /* | 2597 | ioc->internal_cmds.status |= |
2649 | * Wake up the original calling thread | 2598 | MPT_MGMT_STATUS_DID_IOCRESET; |
2650 | */ | 2599 | complete(&ioc->internal_cmds.done); |
2651 | hd->pLocal = &hd->localReply; | ||
2652 | hd->pLocal->completion = MPT_SCANDV_DID_RESET; | ||
2653 | hd->scandv_wait_done = 1; | ||
2654 | wake_up(&hd->scandv_waitq); | ||
2655 | hd->cmdPtr = NULL; | ||
2656 | } | 2600 | } |
2657 | 2601 | break; | |
2658 | dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Post-Reset complete.\n", ioc->name)); | 2602 | default: |
2659 | 2603 | break; | |
2660 | } | 2604 | } |
2661 | |||
2662 | return 1; /* currently means nothing really */ | 2605 | return 1; /* currently means nothing really */ |
2663 | } | 2606 | } |
2664 | 2607 | ||
@@ -2669,8 +2612,9 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2669 | MPT_SCSI_HOST *hd; | 2612 | MPT_SCSI_HOST *hd; |
2670 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | 2613 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; |
2671 | 2614 | ||
2672 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2615 | devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2673 | ioc->name, event)); | 2616 | "MPT event (=%02Xh) routed to SCSI host driver!\n", |
2617 | ioc->name, event)); | ||
2674 | 2618 | ||
2675 | if (ioc->sh == NULL || | 2619 | if (ioc->sh == NULL || |
2676 | ((hd = shost_priv(ioc->sh)) == NULL)) | 2620 | ((hd = shost_priv(ioc->sh)) == NULL)) |
@@ -2711,8 +2655,9 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2711 | case MPI_EVENT_STATE_CHANGE: /* 02 */ | 2655 | case MPI_EVENT_STATE_CHANGE: /* 02 */ |
2712 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ | 2656 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ |
2713 | default: | 2657 | default: |
2714 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n", | 2658 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
2715 | ioc->name, event)); | 2659 | ": Ignoring event (=%02Xh)\n", |
2660 | ioc->name, event)); | ||
2716 | break; | 2661 | break; |
2717 | } | 2662 | } |
2718 | 2663 | ||
@@ -2745,153 +2690,44 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2745 | * Used ONLY for DV and other internal commands. | 2690 | * Used ONLY for DV and other internal commands. |
2746 | */ | 2691 | */ |
2747 | int | 2692 | int |
2748 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | 2693 | mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, |
2694 | MPT_FRAME_HDR *reply) | ||
2749 | { | 2695 | { |
2750 | MPT_SCSI_HOST *hd; | ||
2751 | SCSIIORequest_t *pReq; | 2696 | SCSIIORequest_t *pReq; |
2752 | int completionCode; | 2697 | SCSIIOReply_t *pReply; |
2698 | u8 cmd; | ||
2753 | u16 req_idx; | 2699 | u16 req_idx; |
2700 | u8 *sense_data; | ||
2701 | int sz; | ||
2754 | 2702 | ||
2755 | hd = shost_priv(ioc->sh); | 2703 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; |
2756 | 2704 | ioc->internal_cmds.completion_code = MPT_SCANDV_GOOD; | |
2757 | if ((mf == NULL) || | 2705 | if (!reply) |
2758 | (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { | 2706 | goto out; |
2759 | printk(MYIOC_s_ERR_FMT | ||
2760 | "ScanDvComplete, %s req frame ptr! (=%p)\n", | ||
2761 | ioc->name, mf?"BAD":"NULL", (void *) mf); | ||
2762 | goto wakeup; | ||
2763 | } | ||
2764 | |||
2765 | del_timer(&hd->timer); | ||
2766 | req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
2767 | mptscsih_set_scsi_lookup(ioc, req_idx, NULL); | ||
2768 | pReq = (SCSIIORequest_t *) mf; | ||
2769 | 2707 | ||
2770 | if (mf != hd->cmdPtr) { | 2708 | pReply = (SCSIIOReply_t *) reply; |
2771 | printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", | 2709 | pReq = (SCSIIORequest_t *) req; |
2772 | ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); | 2710 | ioc->internal_cmds.completion_code = |
2711 | mptscsih_get_completion_code(ioc, req, reply); | ||
2712 | ioc->internal_cmds.status |= MPT_MGMT_STATUS_RF_VALID; | ||
2713 | memcpy(ioc->internal_cmds.reply, reply, | ||
2714 | min(MPT_DEFAULT_FRAME_SIZE, 4 * reply->u.reply.MsgLength)); | ||
2715 | cmd = reply->u.hdr.Function; | ||
2716 | if (((cmd == MPI_FUNCTION_SCSI_IO_REQUEST) || | ||
2717 | (cmd == MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) && | ||
2718 | (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID)) { | ||
2719 | req_idx = le16_to_cpu(req->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
2720 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
2721 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
2722 | sz = min_t(int, pReq->SenseBufferLength, | ||
2723 | MPT_SENSE_BUFFER_ALLOC); | ||
2724 | memcpy(ioc->internal_cmds.sense, sense_data, sz); | ||
2773 | } | 2725 | } |
2774 | hd->cmdPtr = NULL; | 2726 | out: |
2775 | 2727 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_PENDING)) | |
2776 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", | 2728 | return 0; |
2777 | ioc->name, mf, mr, req_idx)); | 2729 | ioc->internal_cmds.status &= ~MPT_MGMT_STATUS_PENDING; |
2778 | 2730 | complete(&ioc->internal_cmds.done); | |
2779 | hd->pLocal = &hd->localReply; | ||
2780 | hd->pLocal->scsiStatus = 0; | ||
2781 | |||
2782 | /* If target struct exists, clear sense valid flag. | ||
2783 | */ | ||
2784 | if (mr == NULL) { | ||
2785 | completionCode = MPT_SCANDV_GOOD; | ||
2786 | } else { | ||
2787 | SCSIIOReply_t *pReply; | ||
2788 | u16 status; | ||
2789 | u8 scsi_status; | ||
2790 | |||
2791 | pReply = (SCSIIOReply_t *) mr; | ||
2792 | |||
2793 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2794 | scsi_status = pReply->SCSIStatus; | ||
2795 | |||
2796 | |||
2797 | switch(status) { | ||
2798 | |||
2799 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
2800 | completionCode = MPT_SCANDV_SELECTION_TIMEOUT; | ||
2801 | break; | ||
2802 | |||
2803 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
2804 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
2805 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
2806 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
2807 | completionCode = MPT_SCANDV_DID_RESET; | ||
2808 | break; | ||
2809 | |||
2810 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
2811 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
2812 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
2813 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
2814 | ConfigReply_t *pr = (ConfigReply_t *)mr; | ||
2815 | completionCode = MPT_SCANDV_GOOD; | ||
2816 | hd->pLocal->header.PageVersion = pr->Header.PageVersion; | ||
2817 | hd->pLocal->header.PageLength = pr->Header.PageLength; | ||
2818 | hd->pLocal->header.PageNumber = pr->Header.PageNumber; | ||
2819 | hd->pLocal->header.PageType = pr->Header.PageType; | ||
2820 | |||
2821 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
2822 | /* If the RAID Volume request is successful, | ||
2823 | * return GOOD, else indicate that | ||
2824 | * some type of error occurred. | ||
2825 | */ | ||
2826 | MpiRaidActionReply_t *pr = (MpiRaidActionReply_t *)mr; | ||
2827 | if (le16_to_cpu(pr->ActionStatus) == MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
2828 | completionCode = MPT_SCANDV_GOOD; | ||
2829 | else | ||
2830 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2831 | memcpy(hd->pLocal->sense, pr, sizeof(hd->pLocal->sense)); | ||
2832 | |||
2833 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { | ||
2834 | u8 *sense_data; | ||
2835 | int sz; | ||
2836 | |||
2837 | /* save sense data in global structure | ||
2838 | */ | ||
2839 | completionCode = MPT_SCANDV_SENSE; | ||
2840 | hd->pLocal->scsiStatus = scsi_status; | ||
2841 | sense_data = ((u8 *)ioc->sense_buf_pool + | ||
2842 | (req_idx * MPT_SENSE_BUFFER_ALLOC)); | ||
2843 | |||
2844 | sz = min_t(int, pReq->SenseBufferLength, | ||
2845 | SCSI_STD_SENSE_BYTES); | ||
2846 | memcpy(hd->pLocal->sense, sense_data, sz); | ||
2847 | |||
2848 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n", | ||
2849 | ioc->name, sense_data)); | ||
2850 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
2851 | if (pReq->CDB[0] == INQUIRY) | ||
2852 | completionCode = MPT_SCANDV_ISSUE_SENSE; | ||
2853 | else | ||
2854 | completionCode = MPT_SCANDV_DID_RESET; | ||
2855 | } | ||
2856 | else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
2857 | completionCode = MPT_SCANDV_DID_RESET; | ||
2858 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2859 | completionCode = MPT_SCANDV_DID_RESET; | ||
2860 | else { | ||
2861 | completionCode = MPT_SCANDV_GOOD; | ||
2862 | hd->pLocal->scsiStatus = scsi_status; | ||
2863 | } | ||
2864 | break; | ||
2865 | |||
2866 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
2867 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2868 | completionCode = MPT_SCANDV_DID_RESET; | ||
2869 | else | ||
2870 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2871 | break; | ||
2872 | |||
2873 | default: | ||
2874 | completionCode = MPT_SCANDV_SOME_ERROR; | ||
2875 | break; | ||
2876 | |||
2877 | } /* switch(status) */ | ||
2878 | |||
2879 | } /* end of address reply case */ | ||
2880 | |||
2881 | hd->pLocal->completion = completionCode; | ||
2882 | |||
2883 | /* MF and RF are freed in mpt_interrupt | ||
2884 | */ | ||
2885 | wakeup: | ||
2886 | /* Free Chain buffers (will never chain) in scan or dv */ | ||
2887 | //mptscsih_freeChainBuffers(ioc, req_idx); | ||
2888 | |||
2889 | /* | ||
2890 | * Wake up the original calling thread | ||
2891 | */ | ||
2892 | hd->scandv_wait_done = 1; | ||
2893 | wake_up(&hd->scandv_waitq); | ||
2894 | |||
2895 | return 1; | 2731 | return 1; |
2896 | } | 2732 | } |
2897 | 2733 | ||
@@ -2940,6 +2776,95 @@ mptscsih_timer_expired(unsigned long data) | |||
2940 | return; | 2776 | return; |
2941 | } | 2777 | } |
2942 | 2778 | ||
2779 | /** | ||
2780 | * mptscsih_get_completion_code - | ||
2781 | * @ioc: Pointer to MPT_ADAPTER structure | ||
2782 | * @reply: | ||
2783 | * @cmd: | ||
2784 | * | ||
2785 | **/ | ||
2786 | static int | ||
2787 | mptscsih_get_completion_code(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, | ||
2788 | MPT_FRAME_HDR *reply) | ||
2789 | { | ||
2790 | SCSIIOReply_t *pReply; | ||
2791 | MpiRaidActionReply_t *pr; | ||
2792 | u8 scsi_status; | ||
2793 | u16 status; | ||
2794 | int completion_code; | ||
2795 | |||
2796 | pReply = (SCSIIOReply_t *)reply; | ||
2797 | status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; | ||
2798 | scsi_status = pReply->SCSIStatus; | ||
2799 | |||
2800 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2801 | "IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh," | ||
2802 | "IOCLogInfo=%08xh\n", ioc->name, status, pReply->SCSIState, | ||
2803 | scsi_status, le32_to_cpu(pReply->IOCLogInfo))); | ||
2804 | |||
2805 | switch (status) { | ||
2806 | |||
2807 | case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ | ||
2808 | completion_code = MPT_SCANDV_SELECTION_TIMEOUT; | ||
2809 | break; | ||
2810 | |||
2811 | case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR: /* 0x0046 */ | ||
2812 | case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ | ||
2813 | case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: /* 0x004B */ | ||
2814 | case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */ | ||
2815 | completion_code = MPT_SCANDV_DID_RESET; | ||
2816 | break; | ||
2817 | |||
2818 | case MPI_IOCSTATUS_BUSY: | ||
2819 | case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: | ||
2820 | completion_code = MPT_SCANDV_BUSY; | ||
2821 | break; | ||
2822 | |||
2823 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | ||
2824 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | ||
2825 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | ||
2826 | if (pReply->Function == MPI_FUNCTION_CONFIG) { | ||
2827 | completion_code = MPT_SCANDV_GOOD; | ||
2828 | } else if (pReply->Function == MPI_FUNCTION_RAID_ACTION) { | ||
2829 | pr = (MpiRaidActionReply_t *)reply; | ||
2830 | if (le16_to_cpu(pr->ActionStatus) == | ||
2831 | MPI_RAID_ACTION_ASTATUS_SUCCESS) | ||
2832 | completion_code = MPT_SCANDV_GOOD; | ||
2833 | else | ||
2834 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2835 | } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) | ||
2836 | completion_code = MPT_SCANDV_SENSE; | ||
2837 | else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { | ||
2838 | if (req->u.scsireq.CDB[0] == INQUIRY) | ||
2839 | completion_code = MPT_SCANDV_ISSUE_SENSE; | ||
2840 | else | ||
2841 | completion_code = MPT_SCANDV_DID_RESET; | ||
2842 | } else if (pReply->SCSIState & MPI_SCSI_STATE_NO_SCSI_STATUS) | ||
2843 | completion_code = MPT_SCANDV_DID_RESET; | ||
2844 | else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2845 | completion_code = MPT_SCANDV_DID_RESET; | ||
2846 | else if (scsi_status == MPI_SCSI_STATUS_BUSY) | ||
2847 | completion_code = MPT_SCANDV_BUSY; | ||
2848 | else | ||
2849 | completion_code = MPT_SCANDV_GOOD; | ||
2850 | break; | ||
2851 | |||
2852 | case MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* 0x0047 */ | ||
2853 | if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED) | ||
2854 | completion_code = MPT_SCANDV_DID_RESET; | ||
2855 | else | ||
2856 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2857 | break; | ||
2858 | default: | ||
2859 | completion_code = MPT_SCANDV_SOME_ERROR; | ||
2860 | break; | ||
2861 | |||
2862 | } /* switch(status) */ | ||
2863 | |||
2864 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT | ||
2865 | " completionCode set to %08xh\n", ioc->name, completion_code)); | ||
2866 | return completion_code; | ||
2867 | } | ||
2943 | 2868 | ||
2944 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2869 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2945 | /** | 2870 | /** |
@@ -2966,22 +2891,17 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
2966 | { | 2891 | { |
2967 | MPT_FRAME_HDR *mf; | 2892 | MPT_FRAME_HDR *mf; |
2968 | SCSIIORequest_t *pScsiReq; | 2893 | SCSIIORequest_t *pScsiReq; |
2969 | SCSIIORequest_t ReqCopy; | ||
2970 | int my_idx, ii, dir; | 2894 | int my_idx, ii, dir; |
2971 | int rc, cmdTimeout; | 2895 | int timeout; |
2972 | int in_isr; | ||
2973 | char cmdLen; | 2896 | char cmdLen; |
2974 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 2897 | char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
2975 | char cmd = io->cmd; | 2898 | u8 cmd = io->cmd; |
2976 | MPT_ADAPTER *ioc = hd->ioc; | 2899 | MPT_ADAPTER *ioc = hd->ioc; |
2977 | 2900 | int ret = 0; | |
2978 | in_isr = in_interrupt(); | 2901 | unsigned long timeleft; |
2979 | if (in_isr) { | 2902 | unsigned long flags; |
2980 | dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", | ||
2981 | ioc->name)); | ||
2982 | return -EPERM; | ||
2983 | } | ||
2984 | 2903 | ||
2904 | mutex_lock(&ioc->internal_cmds.mutex); | ||
2985 | 2905 | ||
2986 | /* Set command specific information | 2906 | /* Set command specific information |
2987 | */ | 2907 | */ |
@@ -2991,13 +2911,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
2991 | dir = MPI_SCSIIO_CONTROL_READ; | 2911 | dir = MPI_SCSIIO_CONTROL_READ; |
2992 | CDB[0] = cmd; | 2912 | CDB[0] = cmd; |
2993 | CDB[4] = io->size; | 2913 | CDB[4] = io->size; |
2994 | cmdTimeout = 10; | 2914 | timeout = 10; |
2995 | break; | 2915 | break; |
2996 | 2916 | ||
2997 | case TEST_UNIT_READY: | 2917 | case TEST_UNIT_READY: |
2998 | cmdLen = 6; | 2918 | cmdLen = 6; |
2999 | dir = MPI_SCSIIO_CONTROL_READ; | 2919 | dir = MPI_SCSIIO_CONTROL_READ; |
3000 | cmdTimeout = 10; | 2920 | timeout = 10; |
3001 | break; | 2921 | break; |
3002 | 2922 | ||
3003 | case START_STOP: | 2923 | case START_STOP: |
@@ -3005,7 +2925,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3005 | dir = MPI_SCSIIO_CONTROL_READ; | 2925 | dir = MPI_SCSIIO_CONTROL_READ; |
3006 | CDB[0] = cmd; | 2926 | CDB[0] = cmd; |
3007 | CDB[4] = 1; /*Spin up the disk */ | 2927 | CDB[4] = 1; /*Spin up the disk */ |
3008 | cmdTimeout = 15; | 2928 | timeout = 15; |
3009 | break; | 2929 | break; |
3010 | 2930 | ||
3011 | case REQUEST_SENSE: | 2931 | case REQUEST_SENSE: |
@@ -3013,7 +2933,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3013 | CDB[0] = cmd; | 2933 | CDB[0] = cmd; |
3014 | CDB[4] = io->size; | 2934 | CDB[4] = io->size; |
3015 | dir = MPI_SCSIIO_CONTROL_READ; | 2935 | dir = MPI_SCSIIO_CONTROL_READ; |
3016 | cmdTimeout = 10; | 2936 | timeout = 10; |
3017 | break; | 2937 | break; |
3018 | 2938 | ||
3019 | case READ_BUFFER: | 2939 | case READ_BUFFER: |
@@ -3032,7 +2952,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3032 | CDB[6] = (io->size >> 16) & 0xFF; | 2952 | CDB[6] = (io->size >> 16) & 0xFF; |
3033 | CDB[7] = (io->size >> 8) & 0xFF; | 2953 | CDB[7] = (io->size >> 8) & 0xFF; |
3034 | CDB[8] = io->size & 0xFF; | 2954 | CDB[8] = io->size & 0xFF; |
3035 | cmdTimeout = 10; | 2955 | timeout = 10; |
3036 | break; | 2956 | break; |
3037 | 2957 | ||
3038 | case WRITE_BUFFER: | 2958 | case WRITE_BUFFER: |
@@ -3047,21 +2967,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3047 | CDB[6] = (io->size >> 16) & 0xFF; | 2967 | CDB[6] = (io->size >> 16) & 0xFF; |
3048 | CDB[7] = (io->size >> 8) & 0xFF; | 2968 | CDB[7] = (io->size >> 8) & 0xFF; |
3049 | CDB[8] = io->size & 0xFF; | 2969 | CDB[8] = io->size & 0xFF; |
3050 | cmdTimeout = 10; | 2970 | timeout = 10; |
3051 | break; | 2971 | break; |
3052 | 2972 | ||
3053 | case RESERVE: | 2973 | case RESERVE: |
3054 | cmdLen = 6; | 2974 | cmdLen = 6; |
3055 | dir = MPI_SCSIIO_CONTROL_READ; | 2975 | dir = MPI_SCSIIO_CONTROL_READ; |
3056 | CDB[0] = cmd; | 2976 | CDB[0] = cmd; |
3057 | cmdTimeout = 10; | 2977 | timeout = 10; |
3058 | break; | 2978 | break; |
3059 | 2979 | ||
3060 | case RELEASE: | 2980 | case RELEASE: |
3061 | cmdLen = 6; | 2981 | cmdLen = 6; |
3062 | dir = MPI_SCSIIO_CONTROL_READ; | 2982 | dir = MPI_SCSIIO_CONTROL_READ; |
3063 | CDB[0] = cmd; | 2983 | CDB[0] = cmd; |
3064 | cmdTimeout = 10; | 2984 | timeout = 10; |
3065 | break; | 2985 | break; |
3066 | 2986 | ||
3067 | case SYNCHRONIZE_CACHE: | 2987 | case SYNCHRONIZE_CACHE: |
@@ -3069,20 +2989,23 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3069 | dir = MPI_SCSIIO_CONTROL_READ; | 2989 | dir = MPI_SCSIIO_CONTROL_READ; |
3070 | CDB[0] = cmd; | 2990 | CDB[0] = cmd; |
3071 | // CDB[1] = 0x02; /* set immediate bit */ | 2991 | // CDB[1] = 0x02; /* set immediate bit */ |
3072 | cmdTimeout = 10; | 2992 | timeout = 10; |
3073 | break; | 2993 | break; |
3074 | 2994 | ||
3075 | default: | 2995 | default: |
3076 | /* Error Case */ | 2996 | /* Error Case */ |
3077 | return -EFAULT; | 2997 | ret = -EFAULT; |
2998 | goto out; | ||
3078 | } | 2999 | } |
3079 | 3000 | ||
3080 | /* Get and Populate a free Frame | 3001 | /* Get and Populate a free Frame |
3002 | * MsgContext set in mpt_get_msg_frame call | ||
3081 | */ | 3003 | */ |
3082 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { | 3004 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { |
3083 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n", | 3005 | dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s: No msg frames!\n", |
3084 | ioc->name)); | 3006 | ioc->name, __func__)); |
3085 | return -EBUSY; | 3007 | ret = MPT_SCANDV_BUSY; |
3008 | goto out; | ||
3086 | } | 3009 | } |
3087 | 3010 | ||
3088 | pScsiReq = (SCSIIORequest_t *) mf; | 3011 | pScsiReq = (SCSIIORequest_t *) mf; |
@@ -3120,74 +3043,58 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) | |||
3120 | 3043 | ||
3121 | if (cmd == REQUEST_SENSE) { | 3044 | if (cmd == REQUEST_SENSE) { |
3122 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); | 3045 | pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); |
3123 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", | 3046 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3124 | ioc->name, cmd)); | 3047 | "%s: Untagged! 0x%02x\n", ioc->name, __func__, cmd)); |
3125 | } | 3048 | } |
3126 | 3049 | ||
3127 | for (ii=0; ii < 16; ii++) | 3050 | for (ii = 0; ii < 16; ii++) |
3128 | pScsiReq->CDB[ii] = CDB[ii]; | 3051 | pScsiReq->CDB[ii] = CDB[ii]; |
3129 | 3052 | ||
3130 | pScsiReq->DataLength = cpu_to_le32(io->size); | 3053 | pScsiReq->DataLength = cpu_to_le32(io->size); |
3131 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma | 3054 | pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma |
3132 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); | 3055 | + (my_idx * MPT_SENSE_BUFFER_ALLOC)); |
3133 | 3056 | ||
3134 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", | 3057 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3135 | ioc->name, cmd, io->channel, io->id, io->lun)); | 3058 | "%s: Sending Command 0x%02x for fw_channel=%d fw_id=%d lun=%d\n", |
3059 | ioc->name, __func__, cmd, io->channel, io->id, io->lun)); | ||
3136 | 3060 | ||
3137 | if (dir == MPI_SCSIIO_CONTROL_READ) { | 3061 | if (dir == MPI_SCSIIO_CONTROL_READ) |
3138 | ioc->add_sge((char *) &pScsiReq->SGL, | 3062 | ioc->add_sge((char *) &pScsiReq->SGL, |
3139 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, | 3063 | MPT_SGE_FLAGS_SSIMPLE_READ | io->size, io->data_dma); |
3140 | io->data_dma); | 3064 | else |
3141 | } else { | ||
3142 | ioc->add_sge((char *) &pScsiReq->SGL, | 3065 | ioc->add_sge((char *) &pScsiReq->SGL, |
3143 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, | 3066 | MPT_SGE_FLAGS_SSIMPLE_WRITE | io->size, io->data_dma); |
3144 | io->data_dma); | ||
3145 | } | ||
3146 | |||
3147 | /* The ISR will free the request frame, but we need | ||
3148 | * the information to initialize the target. Duplicate. | ||
3149 | */ | ||
3150 | memcpy(&ReqCopy, pScsiReq, sizeof(SCSIIORequest_t)); | ||
3151 | |||
3152 | /* Issue this command after: | ||
3153 | * finish init | ||
3154 | * add timer | ||
3155 | * Wait until the reply has been received | ||
3156 | * ScsiScanDvCtx callback function will | ||
3157 | * set hd->pLocal; | ||
3158 | * set scandv_wait_done and call wake_up | ||
3159 | */ | ||
3160 | hd->pLocal = NULL; | ||
3161 | hd->timer.expires = jiffies + HZ*cmdTimeout; | ||
3162 | hd->scandv_wait_done = 0; | ||
3163 | 3067 | ||
3164 | /* Save cmd pointer, for resource free if timeout or | 3068 | INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) |
3165 | * FW reload occurs | ||
3166 | */ | ||
3167 | hd->cmdPtr = mf; | ||
3168 | |||
3169 | add_timer(&hd->timer); | ||
3170 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); | 3069 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); |
3171 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | 3070 | timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, |
3172 | 3071 | timeout*HZ); | |
3173 | if (hd->pLocal) { | 3072 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { |
3174 | rc = hd->pLocal->completion; | 3073 | ret = MPT_SCANDV_DID_RESET; |
3175 | hd->pLocal->skip = 0; | 3074 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT |
3176 | 3075 | "%s: TIMED OUT for cmd=0x%02x\n", ioc->name, __func__, | |
3177 | /* Always set fatal error codes in some cases. | 3076 | cmd)); |
3178 | */ | 3077 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) { |
3179 | if (rc == MPT_SCANDV_SELECTION_TIMEOUT) | 3078 | mpt_free_msg_frame(ioc, mf); |
3180 | rc = -ENXIO; | 3079 | goto out; |
3181 | else if (rc == MPT_SCANDV_SOME_ERROR) | 3080 | } |
3182 | rc = -rc; | 3081 | if (!timeleft) { |
3183 | } else { | 3082 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", |
3184 | rc = -EFAULT; | 3083 | ioc->name, __func__); |
3185 | /* This should never happen. */ | 3084 | mpt_HardResetHandler(ioc, CAN_SLEEP); |
3186 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", | 3085 | mpt_free_msg_frame(ioc, mf); |
3187 | ioc->name)); | 3086 | } |
3087 | goto out; | ||
3188 | } | 3088 | } |
3189 | 3089 | ||
3190 | return rc; | 3090 | ret = ioc->internal_cmds.completion_code; |
3091 | devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: success, rc=0x%02x\n", | ||
3092 | ioc->name, __func__, ret)); | ||
3093 | |||
3094 | out: | ||
3095 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
3096 | mutex_unlock(&ioc->internal_cmds.mutex); | ||
3097 | return ret; | ||
3191 | } | 3098 | } |
3192 | 3099 | ||
3193 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3100 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -3427,6 +3334,7 @@ struct device_attribute *mptscsih_host_attrs[] = { | |||
3427 | &dev_attr_debug_level, | 3334 | &dev_attr_debug_level, |
3428 | NULL, | 3335 | NULL, |
3429 | }; | 3336 | }; |
3337 | |||
3430 | EXPORT_SYMBOL(mptscsih_host_attrs); | 3338 | EXPORT_SYMBOL(mptscsih_host_attrs); |
3431 | 3339 | ||
3432 | EXPORT_SYMBOL(mptscsih_remove); | 3340 | EXPORT_SYMBOL(mptscsih_remove); |