aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi/ibmvscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvscsi.c')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c151
1 files changed, 96 insertions, 55 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 50120c8c164b..30819012898f 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -629,6 +629,16 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
629 list_del(&evt_struct->list); 629 list_del(&evt_struct->list);
630 del_timer(&evt_struct->timer); 630 del_timer(&evt_struct->timer);
631 631
632 /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY.
633 * Firmware will send a CRQ with a transport event (0xFF) to
634 * tell this client what has happened to the transport. This
635 * will be handled in ibmvscsi_handle_crq()
636 */
637 if (rc == H_CLOSED) {
638 dev_warn(hostdata->dev, "send warning. "
639 "Receive queue closed, will retry.\n");
640 goto send_busy;
641 }
632 dev_err(hostdata->dev, "send error %d\n", rc); 642 dev_err(hostdata->dev, "send error %d\n", rc);
633 atomic_inc(&hostdata->request_limit); 643 atomic_inc(&hostdata->request_limit);
634 goto send_error; 644 goto send_error;
@@ -976,58 +986,74 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
976 int rsp_rc; 986 int rsp_rc;
977 unsigned long flags; 987 unsigned long flags;
978 u16 lun = lun_from_dev(cmd->device); 988 u16 lun = lun_from_dev(cmd->device);
989 unsigned long wait_switch = 0;
979 990
980 /* First, find this command in our sent list so we can figure 991 /* First, find this command in our sent list so we can figure
981 * out the correct tag 992 * out the correct tag
982 */ 993 */
983 spin_lock_irqsave(hostdata->host->host_lock, flags); 994 spin_lock_irqsave(hostdata->host->host_lock, flags);
984 found_evt = NULL; 995 wait_switch = jiffies + (init_timeout * HZ);
985 list_for_each_entry(tmp_evt, &hostdata->sent, list) { 996 do {
986 if (tmp_evt->cmnd == cmd) { 997 found_evt = NULL;
987 found_evt = tmp_evt; 998 list_for_each_entry(tmp_evt, &hostdata->sent, list) {
988 break; 999 if (tmp_evt->cmnd == cmd) {
1000 found_evt = tmp_evt;
1001 break;
1002 }
989 } 1003 }
990 }
991 1004
992 if (!found_evt) { 1005 if (!found_evt) {
993 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1006 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
994 return SUCCESS; 1007 return SUCCESS;
995 } 1008 }
996 1009
997 evt = get_event_struct(&hostdata->pool); 1010 evt = get_event_struct(&hostdata->pool);
998 if (evt == NULL) { 1011 if (evt == NULL) {
999 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1012 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1000 sdev_printk(KERN_ERR, cmd->device, "failed to allocate abort event\n"); 1013 sdev_printk(KERN_ERR, cmd->device,
1001 return FAILED; 1014 "failed to allocate abort event\n");
1002 } 1015 return FAILED;
1016 }
1003 1017
1004 init_event_struct(evt, 1018 init_event_struct(evt,
1005 sync_completion, 1019 sync_completion,
1006 VIOSRP_SRP_FORMAT, 1020 VIOSRP_SRP_FORMAT,
1007 init_timeout); 1021 init_timeout);
1008 1022
1009 tsk_mgmt = &evt->iu.srp.tsk_mgmt; 1023 tsk_mgmt = &evt->iu.srp.tsk_mgmt;
1010 1024
1011 /* Set up an abort SRP command */ 1025 /* Set up an abort SRP command */
1012 memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1026 memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
1013 tsk_mgmt->opcode = SRP_TSK_MGMT; 1027 tsk_mgmt->opcode = SRP_TSK_MGMT;
1014 tsk_mgmt->lun = ((u64) lun) << 48; 1028 tsk_mgmt->lun = ((u64) lun) << 48;
1015 tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK; 1029 tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
1016 tsk_mgmt->task_tag = (u64) found_evt; 1030 tsk_mgmt->task_tag = (u64) found_evt;
1017 1031
1018 sdev_printk(KERN_INFO, cmd->device, "aborting command. lun 0x%lx, tag 0x%lx\n", 1032 evt->sync_srp = &srp_rsp;
1019 tsk_mgmt->lun, tsk_mgmt->task_tag); 1033
1020 1034 init_completion(&evt->comp);
1021 evt->sync_srp = &srp_rsp; 1035 rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
1022 init_completion(&evt->comp); 1036
1023 rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2); 1037 if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY)
1038 break;
1039
1040 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1041 msleep(10);
1042 spin_lock_irqsave(hostdata->host->host_lock, flags);
1043 } while (time_before(jiffies, wait_switch));
1044
1024 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1045 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1046
1025 if (rsp_rc != 0) { 1047 if (rsp_rc != 0) {
1026 sdev_printk(KERN_ERR, cmd->device, 1048 sdev_printk(KERN_ERR, cmd->device,
1027 "failed to send abort() event. rc=%d\n", rsp_rc); 1049 "failed to send abort() event. rc=%d\n", rsp_rc);
1028 return FAILED; 1050 return FAILED;
1029 } 1051 }
1030 1052
1053 sdev_printk(KERN_INFO, cmd->device,
1054 "aborting command. lun 0x%lx, tag 0x%lx\n",
1055 (((u64) lun) << 48), (u64) found_evt);
1056
1031 wait_for_completion(&evt->comp); 1057 wait_for_completion(&evt->comp);
1032 1058
1033 /* make sure we got a good response */ 1059 /* make sure we got a good response */
@@ -1099,41 +1125,56 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
1099 int rsp_rc; 1125 int rsp_rc;
1100 unsigned long flags; 1126 unsigned long flags;
1101 u16 lun = lun_from_dev(cmd->device); 1127 u16 lun = lun_from_dev(cmd->device);
1128 unsigned long wait_switch = 0;
1102 1129
1103 spin_lock_irqsave(hostdata->host->host_lock, flags); 1130 spin_lock_irqsave(hostdata->host->host_lock, flags);
1104 evt = get_event_struct(&hostdata->pool); 1131 wait_switch = jiffies + (init_timeout * HZ);
1105 if (evt == NULL) { 1132 do {
1106 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1133 evt = get_event_struct(&hostdata->pool);
1107 sdev_printk(KERN_ERR, cmd->device, "failed to allocate reset event\n"); 1134 if (evt == NULL) {
1108 return FAILED; 1135 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1109 } 1136 sdev_printk(KERN_ERR, cmd->device,
1137 "failed to allocate reset event\n");
1138 return FAILED;
1139 }
1110 1140
1111 init_event_struct(evt, 1141 init_event_struct(evt,
1112 sync_completion, 1142 sync_completion,
1113 VIOSRP_SRP_FORMAT, 1143 VIOSRP_SRP_FORMAT,
1114 init_timeout); 1144 init_timeout);
1115 1145
1116 tsk_mgmt = &evt->iu.srp.tsk_mgmt; 1146 tsk_mgmt = &evt->iu.srp.tsk_mgmt;
1117 1147
1118 /* Set up a lun reset SRP command */ 1148 /* Set up a lun reset SRP command */
1119 memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt)); 1149 memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
1120 tsk_mgmt->opcode = SRP_TSK_MGMT; 1150 tsk_mgmt->opcode = SRP_TSK_MGMT;
1121 tsk_mgmt->lun = ((u64) lun) << 48; 1151 tsk_mgmt->lun = ((u64) lun) << 48;
1122 tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET; 1152 tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
1123 1153
1124 sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n", 1154 evt->sync_srp = &srp_rsp;
1125 tsk_mgmt->lun); 1155
1156 init_completion(&evt->comp);
1157 rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
1158
1159 if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY)
1160 break;
1161
1162 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1163 msleep(10);
1164 spin_lock_irqsave(hostdata->host->host_lock, flags);
1165 } while (time_before(jiffies, wait_switch));
1126 1166
1127 evt->sync_srp = &srp_rsp;
1128 init_completion(&evt->comp);
1129 rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
1130 spin_unlock_irqrestore(hostdata->host->host_lock, flags); 1167 spin_unlock_irqrestore(hostdata->host->host_lock, flags);
1168
1131 if (rsp_rc != 0) { 1169 if (rsp_rc != 0) {
1132 sdev_printk(KERN_ERR, cmd->device, 1170 sdev_printk(KERN_ERR, cmd->device,
1133 "failed to send reset event. rc=%d\n", rsp_rc); 1171 "failed to send reset event. rc=%d\n", rsp_rc);
1134 return FAILED; 1172 return FAILED;
1135 } 1173 }
1136 1174
1175 sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
1176 (((u64) lun) << 48));
1177
1137 wait_for_completion(&evt->comp); 1178 wait_for_completion(&evt->comp);
1138 1179
1139 /* make sure we got a good response */ 1180 /* make sure we got a good response */