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 | |
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')
-rw-r--r-- | drivers/message/fusion/mptbase.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptbase.h | 5 | ||||
-rw-r--r-- | drivers/message/fusion/mptfc.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptsas.c | 2 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.c | 514 | ||||
-rw-r--r-- | drivers/message/fusion/mptscsih.h | 1 | ||||
-rw-r--r-- | drivers/message/fusion/mptspi.c | 52 |
7 files changed, 248 insertions, 330 deletions
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index e63a6260b0a0..d8d5231f484e 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -1775,6 +1775,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1775 | spin_lock_init(&ioc->diagLock); | 1775 | spin_lock_init(&ioc->diagLock); |
1776 | spin_lock_init(&ioc->initializing_hba_lock); | 1776 | spin_lock_init(&ioc->initializing_hba_lock); |
1777 | 1777 | ||
1778 | mutex_init(&ioc->internal_cmds.mutex); | ||
1779 | init_completion(&ioc->internal_cmds.done); | ||
1778 | mutex_init(&ioc->mptbase_cmds.mutex); | 1780 | mutex_init(&ioc->mptbase_cmds.mutex); |
1779 | init_completion(&ioc->mptbase_cmds.done); | 1781 | init_completion(&ioc->mptbase_cmds.done); |
1780 | 1782 | ||
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 41273fff4b01..4d77256954f9 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -465,7 +465,9 @@ typedef struct _MPT_MGMT { | |||
465 | struct mutex mutex; | 465 | struct mutex mutex; |
466 | struct completion done; | 466 | struct completion done; |
467 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ | 467 | u8 reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */ |
468 | u8 sense[MPT_SENSE_BUFFER_ALLOC]; | ||
468 | u8 status; /* current command status */ | 469 | u8 status; /* current command status */ |
470 | int completion_code; | ||
469 | } MPT_MGMT; | 471 | } MPT_MGMT; |
470 | 472 | ||
471 | /* | 473 | /* |
@@ -709,6 +711,7 @@ typedef struct _MPT_ADAPTER | |||
709 | int sas_index; /* index refrencing */ | 711 | int sas_index; /* index refrencing */ |
710 | MPT_MGMT sas_mgmt; | 712 | MPT_MGMT sas_mgmt; |
711 | MPT_MGMT mptbase_cmds; /* for sending config pages */ | 713 | MPT_MGMT mptbase_cmds; /* for sending config pages */ |
714 | MPT_MGMT internal_cmds; | ||
712 | struct work_struct sas_persist_task; | 715 | struct work_struct sas_persist_task; |
713 | 716 | ||
714 | struct work_struct fc_setup_reset_work; | 717 | struct work_struct fc_setup_reset_work; |
@@ -863,8 +866,6 @@ typedef struct _MPT_SCSI_HOST { | |||
863 | unsigned long timeouts; /* cmd timeouts */ | 866 | unsigned long timeouts; /* cmd timeouts */ |
864 | ushort sel_timeout[MPT_MAX_FC_DEVICES]; | 867 | ushort sel_timeout[MPT_MAX_FC_DEVICES]; |
865 | char *info_kbuf; | 868 | char *info_kbuf; |
866 | wait_queue_head_t scandv_waitq; | ||
867 | int scandv_wait_done; | ||
868 | long last_queue_full; | 869 | long last_queue_full; |
869 | u16 tm_iocstatus; | 870 | u16 tm_iocstatus; |
870 | u16 spi_pending; | 871 | u16 spi_pending; |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index da16b47a3f32..d09387134145 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
@@ -1310,8 +1310,6 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1310 | hd->timer.data = (unsigned long) hd; | 1310 | hd->timer.data = (unsigned long) hd; |
1311 | hd->timer.function = mptscsih_timer_expired; | 1311 | hd->timer.function = mptscsih_timer_expired; |
1312 | 1312 | ||
1313 | init_waitqueue_head(&hd->scandv_waitq); | ||
1314 | hd->scandv_wait_done = 0; | ||
1315 | hd->last_queue_full = 0; | 1313 | hd->last_queue_full = 0; |
1316 | 1314 | ||
1317 | sh->transportt = mptfc_transport_template; | 1315 | sh->transportt = mptfc_transport_template; |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index dc23adf9a30f..16c4232c37de 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
@@ -3282,8 +3282,6 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
3282 | 3282 | ||
3283 | ioc->sas_data.ptClear = mpt_pt_clear; | 3283 | ioc->sas_data.ptClear = mpt_pt_clear; |
3284 | 3284 | ||
3285 | init_waitqueue_head(&hd->scandv_waitq); | ||
3286 | hd->scandv_wait_done = 0; | ||
3287 | hd->last_queue_full = 0; | 3285 | hd->last_queue_full = 0; |
3288 | INIT_LIST_HEAD(&hd->target_reset_list); | 3286 | INIT_LIST_HEAD(&hd->target_reset_list); |
3289 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | 3287 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); |
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); |
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 319aa3033371..0b103a2516ee 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
@@ -60,6 +60,7 @@ | |||
60 | #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) | 60 | #define MPT_SCANDV_SELECTION_TIMEOUT (0x00000008) |
61 | #define MPT_SCANDV_ISSUE_SENSE (0x00000010) | 61 | #define MPT_SCANDV_ISSUE_SENSE (0x00000010) |
62 | #define MPT_SCANDV_FALLBACK (0x00000020) | 62 | #define MPT_SCANDV_FALLBACK (0x00000020) |
63 | #define MPT_SCANDV_BUSY (0x00000040) | ||
63 | 64 | ||
64 | #define MPT_SCANDV_MAX_RETRIES (10) | 65 | #define MPT_SCANDV_MAX_RETRIES (10) |
65 | 66 | ||
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 643a3c6443af..8f46fdff7f77 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
@@ -614,19 +614,24 @@ static void mptspi_read_parameters(struct scsi_target *starget) | |||
614 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; | 614 | spi_width(starget) = (nego & MPI_SCSIDEVPAGE0_NP_WIDE) ? 1 : 0; |
615 | } | 615 | } |
616 | 616 | ||
617 | static int | 617 | int |
618 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) | 618 | mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) |
619 | { | 619 | { |
620 | MPT_ADAPTER *ioc = hd->ioc; | ||
620 | MpiRaidActionRequest_t *pReq; | 621 | MpiRaidActionRequest_t *pReq; |
621 | MPT_FRAME_HDR *mf; | 622 | MPT_FRAME_HDR *mf; |
622 | MPT_ADAPTER *ioc = hd->ioc; | 623 | int ret; |
624 | unsigned long timeleft; | ||
625 | |||
626 | mutex_lock(&ioc->internal_cmds.mutex); | ||
623 | 627 | ||
624 | /* Get and Populate a free Frame | 628 | /* Get and Populate a free Frame |
625 | */ | 629 | */ |
626 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { | 630 | if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { |
627 | ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", | 631 | dfailprintk(hd->ioc, printk(MYIOC_s_WARN_FMT |
628 | ioc->name)); | 632 | "%s: no msg frames!\n", ioc->name, __func__)); |
629 | return -EAGAIN; | 633 | ret = -EAGAIN; |
634 | goto out; | ||
630 | } | 635 | } |
631 | pReq = (MpiRaidActionRequest_t *)mf; | 636 | pReq = (MpiRaidActionRequest_t *)mf; |
632 | if (quiesce) | 637 | if (quiesce) |
@@ -649,23 +654,30 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) | |||
649 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", | 654 | ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", |
650 | ioc->name, pReq->Action, channel, id)); | 655 | ioc->name, pReq->Action, channel, id)); |
651 | 656 | ||
652 | hd->pLocal = NULL; | 657 | INITIALIZE_MGMT_STATUS(ioc->internal_cmds.status) |
653 | hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ | ||
654 | hd->scandv_wait_done = 0; | ||
655 | |||
656 | /* Save cmd pointer, for resource free if timeout or | ||
657 | * FW reload occurs | ||
658 | */ | ||
659 | hd->cmdPtr = mf; | ||
660 | |||
661 | add_timer(&hd->timer); | ||
662 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); | 658 | mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); |
663 | wait_event(hd->scandv_waitq, hd->scandv_wait_done); | 659 | timeleft = wait_for_completion_timeout(&ioc->internal_cmds.done, 10*HZ); |
660 | if (!(ioc->internal_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) { | ||
661 | ret = -ETIME; | ||
662 | dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: TIMED OUT!\n", | ||
663 | ioc->name, __func__)); | ||
664 | if (ioc->internal_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET) | ||
665 | goto out; | ||
666 | if (!timeleft) { | ||
667 | printk(MYIOC_s_WARN_FMT "Issuing Reset from %s!!\n", | ||
668 | ioc->name, __func__); | ||
669 | mpt_HardResetHandler(ioc, CAN_SLEEP); | ||
670 | mpt_free_msg_frame(ioc, mf); | ||
671 | } | ||
672 | goto out; | ||
673 | } | ||
664 | 674 | ||
665 | if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) | 675 | ret = ioc->internal_cmds.completion_code; |
666 | return -1; | ||
667 | 676 | ||
668 | return 0; | 677 | out: |
678 | CLEAR_MGMT_STATUS(ioc->internal_cmds.status) | ||
679 | mutex_unlock(&ioc->internal_cmds.mutex); | ||
680 | return ret; | ||
669 | } | 681 | } |
670 | 682 | ||
671 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, | 683 | static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, |
@@ -1491,8 +1503,6 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1491 | mpt_saf_te)); | 1503 | mpt_saf_te)); |
1492 | ioc->spi_data.noQas = 0; | 1504 | ioc->spi_data.noQas = 0; |
1493 | 1505 | ||
1494 | init_waitqueue_head(&hd->scandv_waitq); | ||
1495 | hd->scandv_wait_done = 0; | ||
1496 | hd->last_queue_full = 0; | 1506 | hd->last_queue_full = 0; |
1497 | hd->spi_pending = 0; | 1507 | hd->spi_pending = 0; |
1498 | 1508 | ||