aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-06-14 22:52:38 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:27 -0400
commit915caaaf622172bd3451e7b76ba9cfcea80e87c7 (patch)
treeee336bd79be7cf81b6da86c278b45116a1b54f9f /drivers/scsi
parent235f7f25f4928f5075dbebdfb9ca2c5d90db882c (diff)
[SCSI] lpfc 8.2.7 : Change device reset behavior
Prior handler was only waiting for I/O on one lun to finish before returning completion. Now, wait for all LUNs on the target. Also performed some rudimentary cleanup while in this code. Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c201
1 files changed, 80 insertions, 121 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 0910a9ab76a..3926affaf72 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -849,14 +849,15 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
849 struct lpfc_iocbq *iocbq; 849 struct lpfc_iocbq *iocbq;
850 struct lpfc_iocbq *iocbqrsp; 850 struct lpfc_iocbq *iocbqrsp;
851 int ret; 851 int ret;
852 int status;
852 853
853 if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode)) 854 if (!rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode))
854 return FAILED; 855 return FAILED;
855 856
856 lpfc_cmd->rdata = rdata; 857 lpfc_cmd->rdata = rdata;
857 ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun, 858 status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun,
858 FCP_TARGET_RESET); 859 FCP_TARGET_RESET);
859 if (!ret) 860 if (!status)
860 return FAILED; 861 return FAILED;
861 862
862 iocbq = &lpfc_cmd->cur_iocbq; 863 iocbq = &lpfc_cmd->cur_iocbq;
@@ -869,12 +870,15 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_vport *vport,
869 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, 870 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
870 "0702 Issue Target Reset to TGT %d Data: x%x x%x\n", 871 "0702 Issue Target Reset to TGT %d Data: x%x x%x\n",
871 tgt_id, rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag); 872 tgt_id, rdata->pnode->nlp_rpi, rdata->pnode->nlp_flag);
872 ret = lpfc_sli_issue_iocb_wait(phba, 873 status = lpfc_sli_issue_iocb_wait(phba,
873 &phba->sli.ring[phba->sli.fcp_ring], 874 &phba->sli.ring[phba->sli.fcp_ring],
874 iocbq, iocbqrsp, lpfc_cmd->timeout); 875 iocbq, iocbqrsp, lpfc_cmd->timeout);
875 if (ret != IOCB_SUCCESS) { 876 if (status != IOCB_SUCCESS) {
876 if (ret == IOCB_TIMEDOUT) 877 if (status == IOCB_TIMEDOUT) {
877 iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; 878 iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
879 ret = TIMEOUT_ERROR;
880 } else
881 ret = FAILED;
878 lpfc_cmd->status = IOSTAT_DRIVER_REJECT; 882 lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
879 } else { 883 } else {
880 ret = SUCCESS; 884 ret = SUCCESS;
@@ -1142,121 +1146,96 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
1142 struct lpfc_iocbq *iocbq, *iocbqrsp; 1146 struct lpfc_iocbq *iocbq, *iocbqrsp;
1143 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 1147 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
1144 struct lpfc_nodelist *pnode = rdata->pnode; 1148 struct lpfc_nodelist *pnode = rdata->pnode;
1145 uint32_t cmd_result = 0, cmd_status = 0; 1149 unsigned long later;
1146 int ret = FAILED; 1150 int ret = SUCCESS;
1147 int iocb_status = IOCB_SUCCESS; 1151 int status;
1148 int cnt, loopcnt; 1152 int cnt;
1149 1153
1150 lpfc_block_error_handler(cmnd); 1154 lpfc_block_error_handler(cmnd);
1151 loopcnt = 0;
1152 /* 1155 /*
1153 * If target is not in a MAPPED state, delay the reset until 1156 * If target is not in a MAPPED state, delay the reset until
1154 * target is rediscovered or devloss timeout expires. 1157 * target is rediscovered or devloss timeout expires.
1155 */ 1158 */
1156 while (1) { 1159 later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
1160 while (time_after(later, jiffies)) {
1157 if (!pnode || !NLP_CHK_NODE_ACT(pnode)) 1161 if (!pnode || !NLP_CHK_NODE_ACT(pnode))
1158 goto out; 1162 return FAILED;
1159
1160 if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
1161 schedule_timeout_uninterruptible(msecs_to_jiffies(500));
1162 loopcnt++;
1163 rdata = cmnd->device->hostdata;
1164 if (!rdata ||
1165 (loopcnt > ((vport->cfg_devloss_tmo * 2) + 1))){
1166 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1167 "0721 LUN Reset rport "
1168 "failure: cnt x%x rdata x%p\n",
1169 loopcnt, rdata);
1170 goto out;
1171 }
1172 pnode = rdata->pnode;
1173 if (!pnode || !NLP_CHK_NODE_ACT(pnode))
1174 goto out;
1175 }
1176 if (pnode->nlp_state == NLP_STE_MAPPED_NODE) 1163 if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
1177 break; 1164 break;
1165 schedule_timeout_uninterruptible(msecs_to_jiffies(500));
1166 rdata = cmnd->device->hostdata;
1167 if (!rdata)
1168 break;
1169 pnode = rdata->pnode;
1170 }
1171 if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) {
1172 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1173 "0721 LUN Reset rport "
1174 "failure: msec x%x rdata x%p\n",
1175 jiffies_to_msecs(jiffies - later), rdata);
1176 return FAILED;
1178 } 1177 }
1179
1180 lpfc_cmd = lpfc_get_scsi_buf(phba); 1178 lpfc_cmd = lpfc_get_scsi_buf(phba);
1181 if (lpfc_cmd == NULL) 1179 if (lpfc_cmd == NULL)
1182 goto out; 1180 return FAILED;
1183
1184 lpfc_cmd->timeout = 60; 1181 lpfc_cmd->timeout = 60;
1185 lpfc_cmd->rdata = rdata; 1182 lpfc_cmd->rdata = rdata;
1186 1183
1187 ret = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, cmnd->device->lun, 1184 status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd,
1188 FCP_TARGET_RESET); 1185 cmnd->device->lun,
1189 if (!ret) 1186 FCP_TARGET_RESET);
1190 goto out_free_scsi_buf; 1187 if (!status) {
1191 1188 lpfc_release_scsi_buf(phba, lpfc_cmd);
1189 return FAILED;
1190 }
1192 iocbq = &lpfc_cmd->cur_iocbq; 1191 iocbq = &lpfc_cmd->cur_iocbq;
1193 1192
1194 /* get a buffer for this IOCB command response */ 1193 /* get a buffer for this IOCB command response */
1195 iocbqrsp = lpfc_sli_get_iocbq(phba); 1194 iocbqrsp = lpfc_sli_get_iocbq(phba);
1196 if (iocbqrsp == NULL) 1195 if (iocbqrsp == NULL) {
1197 goto out_free_scsi_buf; 1196 lpfc_release_scsi_buf(phba, lpfc_cmd);
1198 1197 return FAILED;
1198 }
1199 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, 1199 lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
1200 "0703 Issue target reset to TGT %d LUN %d " 1200 "0703 Issue target reset to TGT %d LUN %d "
1201 "rpi x%x nlp_flag x%x\n", cmnd->device->id, 1201 "rpi x%x nlp_flag x%x\n", cmnd->device->id,
1202 cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag); 1202 cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
1203 iocb_status = lpfc_sli_issue_iocb_wait(phba, 1203 status = lpfc_sli_issue_iocb_wait(phba,
1204 &phba->sli.ring[phba->sli.fcp_ring], 1204 &phba->sli.ring[phba->sli.fcp_ring],
1205 iocbq, iocbqrsp, lpfc_cmd->timeout); 1205 iocbq, iocbqrsp, lpfc_cmd->timeout);
1206 1206 if (status == IOCB_TIMEDOUT) {
1207 if (iocb_status == IOCB_TIMEDOUT)
1208 iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; 1207 iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
1209 1208 ret = TIMEOUT_ERROR;
1210 if (iocb_status == IOCB_SUCCESS) 1209 } else {
1211 ret = SUCCESS; 1210 if (status != IOCB_SUCCESS)
1212 else 1211 ret = FAILED;
1213 ret = iocb_status; 1212 lpfc_release_scsi_buf(phba, lpfc_cmd);
1214 1213 }
1215 cmd_result = iocbqrsp->iocb.un.ulpWord[4]; 1214 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1216 cmd_status = iocbqrsp->iocb.ulpStatus; 1215 "0713 SCSI layer issued device reset (%d, %d) "
1217 1216 "return x%x status x%x result x%x\n",
1217 cmnd->device->id, cmnd->device->lun, ret,
1218 iocbqrsp->iocb.ulpStatus,
1219 iocbqrsp->iocb.un.ulpWord[4]);
1218 lpfc_sli_release_iocbq(phba, iocbqrsp); 1220 lpfc_sli_release_iocbq(phba, iocbqrsp);
1219
1220 /*
1221 * All outstanding txcmplq I/Os should have been aborted by the device.
1222 * Unfortunately, some targets do not abide by this forcing the driver
1223 * to double check.
1224 */
1225 cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun, 1221 cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, cmnd->device->lun,
1226 LPFC_CTX_LUN); 1222 LPFC_CTX_TGT);
1227 if (cnt) 1223 if (cnt)
1228 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], 1224 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
1229 cmnd->device->id, cmnd->device->lun, 1225 cmnd->device->id, cmnd->device->lun,
1230 LPFC_CTX_LUN); 1226 LPFC_CTX_TGT);
1231 loopcnt = 0; 1227 later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
1232 while(cnt) { 1228 while (time_after(later, jiffies) && cnt) {
1233 schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); 1229 schedule_timeout_uninterruptible(msecs_to_jiffies(20));
1234
1235 if (++loopcnt
1236 > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
1237 break;
1238
1239 cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id, 1230 cnt = lpfc_sli_sum_iocb(vport, cmnd->device->id,
1240 cmnd->device->lun, LPFC_CTX_LUN); 1231 cmnd->device->lun, LPFC_CTX_TGT);
1241 } 1232 }
1242
1243 if (cnt) { 1233 if (cnt) {
1244 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 1234 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1245 "0719 device reset I/O flush failure: " 1235 "0719 device reset I/O flush failure: "
1246 "cnt x%x\n", cnt); 1236 "cnt x%x\n", cnt);
1247 ret = FAILED; 1237 ret = FAILED;
1248 } 1238 }
1249
1250out_free_scsi_buf:
1251 if (iocb_status != IOCB_TIMEDOUT) {
1252 lpfc_release_scsi_buf(phba, lpfc_cmd);
1253 }
1254 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1255 "0713 SCSI layer issued device reset (%d, %d) "
1256 "return x%x status x%x result x%x\n",
1257 cmnd->device->id, cmnd->device->lun, ret,
1258 cmd_status, cmd_result);
1259out:
1260 return ret; 1239 return ret;
1261} 1240}
1262 1241
@@ -1268,19 +1247,12 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
1268 struct lpfc_hba *phba = vport->phba; 1247 struct lpfc_hba *phba = vport->phba;
1269 struct lpfc_nodelist *ndlp = NULL; 1248 struct lpfc_nodelist *ndlp = NULL;
1270 int match; 1249 int match;
1271 int ret = FAILED, i, err_count = 0; 1250 int ret = SUCCESS, status, i;
1272 int cnt, loopcnt; 1251 int cnt;
1273 struct lpfc_scsi_buf * lpfc_cmd; 1252 struct lpfc_scsi_buf * lpfc_cmd;
1253 unsigned long later;
1274 1254
1275 lpfc_block_error_handler(cmnd); 1255 lpfc_block_error_handler(cmnd);
1276
1277 lpfc_cmd = lpfc_get_scsi_buf(phba);
1278 if (lpfc_cmd == NULL)
1279 goto out;
1280
1281 /* The lpfc_cmd storage is reused. Set all loop invariants. */
1282 lpfc_cmd->timeout = 60;
1283
1284 /* 1256 /*
1285 * Since the driver manages a single bus device, reset all 1257 * Since the driver manages a single bus device, reset all
1286 * targets known to the driver. Should any target reset 1258 * targets known to the driver. Should any target reset
@@ -1294,7 +1266,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
1294 if (!NLP_CHK_NODE_ACT(ndlp)) 1266 if (!NLP_CHK_NODE_ACT(ndlp))
1295 continue; 1267 continue;
1296 if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && 1268 if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
1297 i == ndlp->nlp_sid && 1269 ndlp->nlp_sid == i &&
1298 ndlp->rport) { 1270 ndlp->rport) {
1299 match = 1; 1271 match = 1;
1300 break; 1272 break;
@@ -1303,27 +1275,22 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
1303 spin_unlock_irq(shost->host_lock); 1275 spin_unlock_irq(shost->host_lock);
1304 if (!match) 1276 if (!match)
1305 continue; 1277 continue;
1306 1278 lpfc_cmd = lpfc_get_scsi_buf(phba);
1307 ret = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i, 1279 if (lpfc_cmd) {
1308 cmnd->device->lun, 1280 lpfc_cmd->timeout = 60;
1309 ndlp->rport->dd_data); 1281 status = lpfc_scsi_tgt_reset(lpfc_cmd, vport, i,
1310 if (ret != SUCCESS) { 1282 cmnd->device->lun,
1283 ndlp->rport->dd_data);
1284 if (status != TIMEOUT_ERROR)
1285 lpfc_release_scsi_buf(phba, lpfc_cmd);
1286 }
1287 if (!lpfc_cmd || status != SUCCESS) {
1311 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 1288 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1312 "0700 Bus Reset on target %d failed\n", 1289 "0700 Bus Reset on target %d failed\n",
1313 i); 1290 i);
1314 err_count++; 1291 ret = FAILED;
1315 break;
1316 } 1292 }
1317 } 1293 }
1318
1319 if (ret != IOCB_TIMEDOUT)
1320 lpfc_release_scsi_buf(phba, lpfc_cmd);
1321
1322 if (err_count == 0)
1323 ret = SUCCESS;
1324 else
1325 ret = FAILED;
1326
1327 /* 1294 /*
1328 * All outstanding txcmplq I/Os should have been aborted by 1295 * All outstanding txcmplq I/Os should have been aborted by
1329 * the targets. Unfortunately, some targets do not abide by 1296 * the targets. Unfortunately, some targets do not abide by
@@ -1333,27 +1300,19 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
1333 if (cnt) 1300 if (cnt)
1334 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], 1301 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
1335 0, 0, LPFC_CTX_HOST); 1302 0, 0, LPFC_CTX_HOST);
1336 loopcnt = 0; 1303 later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies;
1337 while(cnt) { 1304 while (time_after(later, jiffies) && cnt) {
1338 schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ); 1305 schedule_timeout_uninterruptible(msecs_to_jiffies(20));
1339
1340 if (++loopcnt
1341 > (2 * vport->cfg_devloss_tmo)/LPFC_RESET_WAIT)
1342 break;
1343
1344 cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST); 1306 cnt = lpfc_sli_sum_iocb(vport, 0, 0, LPFC_CTX_HOST);
1345 } 1307 }
1346
1347 if (cnt) { 1308 if (cnt) {
1348 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 1309 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1349 "0715 Bus Reset I/O flush failure: " 1310 "0715 Bus Reset I/O flush failure: "
1350 "cnt x%x left x%x\n", cnt, i); 1311 "cnt x%x left x%x\n", cnt, i);
1351 ret = FAILED; 1312 ret = FAILED;
1352 } 1313 }
1353
1354 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, 1314 lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
1355 "0714 SCSI layer issued Bus Reset Data: x%x\n", ret); 1315 "0714 SCSI layer issued Bus Reset Data: x%x\n", ret);
1356out:
1357 return ret; 1316 return ret;
1358} 1317}
1359 1318