aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-12-17 20:29:36 -0500
committerJames Bottomley <JBottomley@Parallels.com>2014-03-15 13:18:55 -0400
commit0976e1a650bdcdf235808e35c96eee70081c079d (patch)
tree1f8fd11826c0c5c3d562efd63e47266fd896a2af /drivers/scsi/lpfc
parent646a2dd7515177376cf12aeb60bd6d462d61c5b8 (diff)
[SCSI] lpfc 8.3.44: Fix Crash in lpfc_els_timeout_handler
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c101
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c56
2 files changed, 84 insertions, 73 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 110445f0c58d..647f4f3b3748 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -6223,19 +6223,17 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
6223 uint32_t els_command = 0; 6223 uint32_t els_command = 0;
6224 uint32_t timeout; 6224 uint32_t timeout;
6225 uint32_t remote_ID = 0xffffffff; 6225 uint32_t remote_ID = 0xffffffff;
6226 LIST_HEAD(txcmplq_completions);
6227 LIST_HEAD(abort_list); 6226 LIST_HEAD(abort_list);
6228 6227
6229 6228
6230 timeout = (uint32_t)(phba->fc_ratov << 1); 6229 timeout = (uint32_t)(phba->fc_ratov << 1);
6231 6230
6232 pring = &phba->sli.ring[LPFC_ELS_RING]; 6231 pring = &phba->sli.ring[LPFC_ELS_RING];
6233
6234 spin_lock_irq(&phba->hbalock); 6232 spin_lock_irq(&phba->hbalock);
6235 list_splice_init(&pring->txcmplq, &txcmplq_completions); 6233 if (phba->sli_rev == LPFC_SLI_REV4)
6236 spin_unlock_irq(&phba->hbalock); 6234 spin_lock(&pring->ring_lock);
6237 6235
6238 list_for_each_entry_safe(piocb, tmp_iocb, &txcmplq_completions, list) { 6236 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
6239 cmd = &piocb->iocb; 6237 cmd = &piocb->iocb;
6240 6238
6241 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || 6239 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
@@ -6274,8 +6272,8 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
6274 } 6272 }
6275 list_add_tail(&piocb->dlist, &abort_list); 6273 list_add_tail(&piocb->dlist, &abort_list);
6276 } 6274 }
6277 spin_lock_irq(&phba->hbalock); 6275 if (phba->sli_rev == LPFC_SLI_REV4)
6278 list_splice(&txcmplq_completions, &pring->txcmplq); 6276 spin_unlock(&pring->ring_lock);
6279 spin_unlock_irq(&phba->hbalock); 6277 spin_unlock_irq(&phba->hbalock);
6280 6278
6281 list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { 6279 list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
@@ -6317,15 +6315,50 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
6317void 6315void
6318lpfc_els_flush_cmd(struct lpfc_vport *vport) 6316lpfc_els_flush_cmd(struct lpfc_vport *vport)
6319{ 6317{
6320 LIST_HEAD(completions); 6318 LIST_HEAD(abort_list);
6321 struct lpfc_hba *phba = vport->phba; 6319 struct lpfc_hba *phba = vport->phba;
6322 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; 6320 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
6323 struct lpfc_iocbq *tmp_iocb, *piocb; 6321 struct lpfc_iocbq *tmp_iocb, *piocb;
6324 IOCB_t *cmd = NULL; 6322 IOCB_t *cmd = NULL;
6325 6323
6326 lpfc_fabric_abort_vport(vport); 6324 lpfc_fabric_abort_vport(vport);
6325 /*
6326 * For SLI3, only the hbalock is required. But SLI4 needs to coordinate
6327 * with the ring insert operation. Because lpfc_sli_issue_abort_iotag
6328 * ultimately grabs the ring_lock, the driver must splice the list into
6329 * a working list and release the locks before calling the abort.
6330 */
6331 spin_lock_irq(&phba->hbalock);
6332 if (phba->sli_rev == LPFC_SLI_REV4)
6333 spin_lock(&pring->ring_lock);
6334
6335 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
6336 if (piocb->iocb_flag & LPFC_IO_LIBDFC)
6337 continue;
6338
6339 if (piocb->vport != vport)
6340 continue;
6341 list_add_tail(&piocb->dlist, &abort_list);
6342 }
6343 if (phba->sli_rev == LPFC_SLI_REV4)
6344 spin_unlock(&pring->ring_lock);
6345 spin_unlock_irq(&phba->hbalock);
6346 /* Abort each iocb on the aborted list and remove the dlist links. */
6347 list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
6348 spin_lock_irq(&phba->hbalock);
6349 list_del_init(&piocb->dlist);
6350 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
6351 spin_unlock_irq(&phba->hbalock);
6352 }
6353 if (!list_empty(&abort_list))
6354 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
6355 "3387 abort list for txq not empty\n");
6356 INIT_LIST_HEAD(&abort_list);
6327 6357
6328 spin_lock_irq(&phba->hbalock); 6358 spin_lock_irq(&phba->hbalock);
6359 if (phba->sli_rev == LPFC_SLI_REV4)
6360 spin_lock(&pring->ring_lock);
6361
6329 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { 6362 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
6330 cmd = &piocb->iocb; 6363 cmd = &piocb->iocb;
6331 6364
@@ -6343,24 +6376,16 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
6343 if (piocb->vport != vport) 6376 if (piocb->vport != vport)
6344 continue; 6377 continue;
6345 6378
6346 list_move_tail(&piocb->list, &completions); 6379 list_del_init(&piocb->list);
6347 } 6380 list_add_tail(&piocb->list, &abort_list);
6348
6349 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
6350 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
6351 continue;
6352 }
6353
6354 if (piocb->vport != vport)
6355 continue;
6356
6357 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
6358 } 6381 }
6382 if (phba->sli_rev == LPFC_SLI_REV4)
6383 spin_unlock(&pring->ring_lock);
6359 spin_unlock_irq(&phba->hbalock); 6384 spin_unlock_irq(&phba->hbalock);
6360 6385
6361 /* Cancell all the IOCBs from the completions list */ 6386 /* Cancell all the IOCBs from the completions list */
6362 lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, 6387 lpfc_sli_cancel_iocbs(phba, &abort_list,
6363 IOERR_SLI_ABORTED); 6388 IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);
6364 6389
6365 return; 6390 return;
6366} 6391}
@@ -6385,35 +6410,9 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
6385void 6410void
6386lpfc_els_flush_all_cmd(struct lpfc_hba *phba) 6411lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
6387{ 6412{
6388 LIST_HEAD(completions); 6413 struct lpfc_vport *vport;
6389 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; 6414 list_for_each_entry(vport, &phba->port_list, listentry)
6390 struct lpfc_iocbq *tmp_iocb, *piocb; 6415 lpfc_els_flush_cmd(vport);
6391 IOCB_t *cmd = NULL;
6392
6393 lpfc_fabric_abort_hba(phba);
6394 spin_lock_irq(&phba->hbalock);
6395 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
6396 cmd = &piocb->iocb;
6397 if (piocb->iocb_flag & LPFC_IO_LIBDFC)
6398 continue;
6399 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
6400 if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
6401 cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
6402 cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
6403 cmd->ulpCommand == CMD_ABORT_XRI_CN)
6404 continue;
6405 list_move_tail(&piocb->list, &completions);
6406 }
6407 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
6408 if (piocb->iocb_flag & LPFC_IO_LIBDFC)
6409 continue;
6410 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
6411 }
6412 spin_unlock_irq(&phba->hbalock);
6413
6414 /* Cancel all the IOCBs from the completions list */
6415 lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
6416 IOERR_SLI_ABORTED);
6417 6416
6418 return; 6417 return;
6419} 6418}
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index abc361259d6d..c342f6afd747 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -203,8 +203,6 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
203int 203int
204lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) 204lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
205{ 205{
206 LIST_HEAD(completions);
207 LIST_HEAD(txcmplq_completions);
208 LIST_HEAD(abort_list); 206 LIST_HEAD(abort_list);
209 struct lpfc_sli *psli = &phba->sli; 207 struct lpfc_sli *psli = &phba->sli;
210 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; 208 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
@@ -216,32 +214,27 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
216 "Data: x%x x%x x%x\n", 214 "Data: x%x x%x x%x\n",
217 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, 215 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
218 ndlp->nlp_rpi); 216 ndlp->nlp_rpi);
219 217 /* Clean up all fabric IOs first.*/
220 lpfc_fabric_abort_nport(ndlp); 218 lpfc_fabric_abort_nport(ndlp);
221 219
222 /* First check the txq */ 220 /*
221 * Lock the ELS ring txcmplq for SLI3/SLI4 and build a local list
222 * of all ELS IOs that need an ABTS. The IOs need to stay on the
223 * txcmplq so that the abort operation completes them successfully.
224 */
223 spin_lock_irq(&phba->hbalock); 225 spin_lock_irq(&phba->hbalock);
224 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { 226 if (phba->sli_rev == LPFC_SLI_REV4)
225 /* Check to see if iocb matches the nport we are looking for */ 227 spin_lock(&pring->ring_lock);
226 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { 228 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
227 /* It matches, so deque and call compl with anp error */ 229 /* Add to abort_list on on NDLP match. */
228 list_move_tail(&iocb->list, &completions);
229 }
230 }
231
232 /* Next check the txcmplq */
233 list_splice_init(&pring->txcmplq, &txcmplq_completions);
234 spin_unlock_irq(&phba->hbalock);
235
236 list_for_each_entry_safe(iocb, next_iocb, &txcmplq_completions, list) {
237 /* Check to see if iocb matches the nport we are looking for */
238 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) 230 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
239 list_add_tail(&iocb->dlist, &abort_list); 231 list_add_tail(&iocb->dlist, &abort_list);
240 } 232 }
241 spin_lock_irq(&phba->hbalock); 233 if (phba->sli_rev == LPFC_SLI_REV4)
242 list_splice(&txcmplq_completions, &pring->txcmplq); 234 spin_unlock(&pring->ring_lock);
243 spin_unlock_irq(&phba->hbalock); 235 spin_unlock_irq(&phba->hbalock);
244 236
237 /* Abort the targeted IOs and remove them from the abort list. */
245 list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) { 238 list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
246 spin_lock_irq(&phba->hbalock); 239 spin_lock_irq(&phba->hbalock);
247 list_del_init(&iocb->dlist); 240 list_del_init(&iocb->dlist);
@@ -249,9 +242,28 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
249 spin_unlock_irq(&phba->hbalock); 242 spin_unlock_irq(&phba->hbalock);
250 } 243 }
251 244
245 INIT_LIST_HEAD(&abort_list);
246
247 /* Now process the txq */
248 spin_lock_irq(&phba->hbalock);
249 if (phba->sli_rev == LPFC_SLI_REV4)
250 spin_lock(&pring->ring_lock);
251
252 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
253 /* Check to see if iocb matches the nport we are looking for */
254 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
255 list_del_init(&iocb->list);
256 list_add_tail(&iocb->list, &abort_list);
257 }
258 }
259
260 if (phba->sli_rev == LPFC_SLI_REV4)
261 spin_unlock(&pring->ring_lock);
262 spin_unlock_irq(&phba->hbalock);
263
252 /* Cancel all the IOCBs from the completions list */ 264 /* Cancel all the IOCBs from the completions list */
253 lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, 265 lpfc_sli_cancel_iocbs(phba, &abort_list,
254 IOERR_SLI_ABORTED); 266 IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED);
255 267
256 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); 268 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
257 return 0; 269 return 0;