diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_bsg.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 79c13c3263f1..b92aec989d60 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -317,6 +317,11 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, | |||
317 | } | 317 | } |
318 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 318 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
319 | 319 | ||
320 | /* Close the timeout handler abort window */ | ||
321 | spin_lock_irqsave(&phba->hbalock, flags); | ||
322 | cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; | ||
323 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
324 | |||
320 | iocb = &dd_data->context_un.iocb; | 325 | iocb = &dd_data->context_un.iocb; |
321 | ndlp = iocb->ndlp; | 326 | ndlp = iocb->ndlp; |
322 | rmp = iocb->rmp; | 327 | rmp = iocb->rmp; |
@@ -387,6 +392,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
387 | int request_nseg; | 392 | int request_nseg; |
388 | int reply_nseg; | 393 | int reply_nseg; |
389 | struct bsg_job_data *dd_data; | 394 | struct bsg_job_data *dd_data; |
395 | unsigned long flags; | ||
390 | uint32_t creg_val; | 396 | uint32_t creg_val; |
391 | int rc = 0; | 397 | int rc = 0; |
392 | int iocb_stat; | 398 | int iocb_stat; |
@@ -501,14 +507,24 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
501 | } | 507 | } |
502 | 508 | ||
503 | iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); | 509 | iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); |
504 | if (iocb_stat == IOCB_SUCCESS) | 510 | |
511 | if (iocb_stat == IOCB_SUCCESS) { | ||
512 | spin_lock_irqsave(&phba->hbalock, flags); | ||
513 | /* make sure the I/O had not been completed yet */ | ||
514 | if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { | ||
515 | /* open up abort window to timeout handler */ | ||
516 | cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; | ||
517 | } | ||
518 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
505 | return 0; /* done for now */ | 519 | return 0; /* done for now */ |
506 | else if (iocb_stat == IOCB_BUSY) | 520 | } else if (iocb_stat == IOCB_BUSY) { |
507 | rc = -EAGAIN; | 521 | rc = -EAGAIN; |
508 | else | 522 | } else { |
509 | rc = -EIO; | 523 | rc = -EIO; |
524 | } | ||
510 | 525 | ||
511 | /* iocb failed so cleanup */ | 526 | /* iocb failed so cleanup */ |
527 | job->dd_data = NULL; | ||
512 | 528 | ||
513 | free_rmp: | 529 | free_rmp: |
514 | lpfc_free_bsg_buffers(phba, rmp); | 530 | lpfc_free_bsg_buffers(phba, rmp); |
@@ -577,6 +593,11 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, | |||
577 | } | 593 | } |
578 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 594 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
579 | 595 | ||
596 | /* Close the timeout handler abort window */ | ||
597 | spin_lock_irqsave(&phba->hbalock, flags); | ||
598 | cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; | ||
599 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
600 | |||
580 | rsp = &rspiocbq->iocb; | 601 | rsp = &rspiocbq->iocb; |
581 | pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2; | 602 | pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2; |
582 | prsp = (struct lpfc_dmabuf *)pcmd->list.next; | 603 | prsp = (struct lpfc_dmabuf *)pcmd->list.next; |
@@ -639,6 +660,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) | |||
639 | struct lpfc_iocbq *cmdiocbq; | 660 | struct lpfc_iocbq *cmdiocbq; |
640 | uint16_t rpi = 0; | 661 | uint16_t rpi = 0; |
641 | struct bsg_job_data *dd_data; | 662 | struct bsg_job_data *dd_data; |
663 | unsigned long flags; | ||
642 | uint32_t creg_val; | 664 | uint32_t creg_val; |
643 | int rc = 0; | 665 | int rc = 0; |
644 | 666 | ||
@@ -721,15 +743,25 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job) | |||
721 | 743 | ||
722 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); | 744 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); |
723 | 745 | ||
724 | if (rc == IOCB_SUCCESS) | 746 | if (rc == IOCB_SUCCESS) { |
747 | spin_lock_irqsave(&phba->hbalock, flags); | ||
748 | /* make sure the I/O had not been completed/released */ | ||
749 | if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) { | ||
750 | /* open up abort window to timeout handler */ | ||
751 | cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; | ||
752 | } | ||
753 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
725 | return 0; /* done for now */ | 754 | return 0; /* done for now */ |
726 | else if (rc == IOCB_BUSY) | 755 | } else if (rc == IOCB_BUSY) { |
727 | rc = -EAGAIN; | 756 | rc = -EAGAIN; |
728 | else | 757 | } else { |
729 | rc = -EIO; | 758 | rc = -EIO; |
759 | } | ||
730 | 760 | ||
731 | linkdown_err: | 761 | /* iocb failed so cleanup */ |
762 | job->dd_data = NULL; | ||
732 | 763 | ||
764 | linkdown_err: | ||
733 | cmdiocbq->context1 = ndlp; | 765 | cmdiocbq->context1 = ndlp; |
734 | lpfc_els_free_iocb(phba, cmdiocbq); | 766 | lpfc_els_free_iocb(phba, cmdiocbq); |
735 | 767 | ||
@@ -1249,7 +1281,7 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) | |||
1249 | struct lpfc_hba *phba = vport->phba; | 1281 | struct lpfc_hba *phba = vport->phba; |
1250 | struct get_ct_event *event_req; | 1282 | struct get_ct_event *event_req; |
1251 | struct get_ct_event_reply *event_reply; | 1283 | struct get_ct_event_reply *event_reply; |
1252 | struct lpfc_bsg_event *evt; | 1284 | struct lpfc_bsg_event *evt, *evt_next; |
1253 | struct event_data *evt_dat = NULL; | 1285 | struct event_data *evt_dat = NULL; |
1254 | unsigned long flags; | 1286 | unsigned long flags; |
1255 | uint32_t rc = 0; | 1287 | uint32_t rc = 0; |
@@ -1269,7 +1301,7 @@ lpfc_bsg_hba_get_event(struct fc_bsg_job *job) | |||
1269 | event_reply = (struct get_ct_event_reply *) | 1301 | event_reply = (struct get_ct_event_reply *) |
1270 | job->reply->reply_data.vendor_reply.vendor_rsp; | 1302 | job->reply->reply_data.vendor_reply.vendor_rsp; |
1271 | spin_lock_irqsave(&phba->ct_ev_lock, flags); | 1303 | spin_lock_irqsave(&phba->ct_ev_lock, flags); |
1272 | list_for_each_entry(evt, &phba->ct_ev_waiters, node) { | 1304 | list_for_each_entry_safe(evt, evt_next, &phba->ct_ev_waiters, node) { |
1273 | if (evt->reg_id == event_req->ev_reg_id) { | 1305 | if (evt->reg_id == event_req->ev_reg_id) { |
1274 | if (list_empty(&evt->events_to_get)) | 1306 | if (list_empty(&evt->events_to_get)) |
1275 | break; | 1307 | break; |
@@ -1370,6 +1402,11 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, | |||
1370 | } | 1402 | } |
1371 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | 1403 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
1372 | 1404 | ||
1405 | /* Close the timeout handler abort window */ | ||
1406 | spin_lock_irqsave(&phba->hbalock, flags); | ||
1407 | cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING; | ||
1408 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
1409 | |||
1373 | ndlp = dd_data->context_un.iocb.ndlp; | 1410 | ndlp = dd_data->context_un.iocb.ndlp; |
1374 | cmp = cmdiocbq->context2; | 1411 | cmp = cmdiocbq->context2; |
1375 | bmp = cmdiocbq->context3; | 1412 | bmp = cmdiocbq->context3; |
@@ -1433,6 +1470,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
1433 | int rc = 0; | 1470 | int rc = 0; |
1434 | struct lpfc_nodelist *ndlp = NULL; | 1471 | struct lpfc_nodelist *ndlp = NULL; |
1435 | struct bsg_job_data *dd_data; | 1472 | struct bsg_job_data *dd_data; |
1473 | unsigned long flags; | ||
1436 | uint32_t creg_val; | 1474 | uint32_t creg_val; |
1437 | 1475 | ||
1438 | /* allocate our bsg tracking structure */ | 1476 | /* allocate our bsg tracking structure */ |
@@ -1542,8 +1580,19 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
1542 | 1580 | ||
1543 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); | 1581 | rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); |
1544 | 1582 | ||
1545 | if (rc == IOCB_SUCCESS) | 1583 | if (rc == IOCB_SUCCESS) { |
1584 | spin_lock_irqsave(&phba->hbalock, flags); | ||
1585 | /* make sure the I/O had not been completed/released */ | ||
1586 | if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) { | ||
1587 | /* open up abort window to timeout handler */ | ||
1588 | ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING; | ||
1589 | } | ||
1590 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
1546 | return 0; /* done for now */ | 1591 | return 0; /* done for now */ |
1592 | } | ||
1593 | |||
1594 | /* iocb failed so cleanup */ | ||
1595 | job->dd_data = NULL; | ||
1547 | 1596 | ||
1548 | issue_ct_rsp_exit: | 1597 | issue_ct_rsp_exit: |
1549 | lpfc_sli_release_iocbq(phba, ctiocb); | 1598 | lpfc_sli_release_iocbq(phba, ctiocb); |
@@ -5284,9 +5333,15 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
5284 | * remove it from the txq queue and call cancel iocbs. | 5333 | * remove it from the txq queue and call cancel iocbs. |
5285 | * Otherwise, call abort iotag | 5334 | * Otherwise, call abort iotag |
5286 | */ | 5335 | */ |
5287 | |||
5288 | cmdiocb = dd_data->context_un.iocb.cmdiocbq; | 5336 | cmdiocb = dd_data->context_un.iocb.cmdiocbq; |
5289 | spin_lock_irq(&phba->hbalock); | 5337 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
5338 | |||
5339 | spin_lock_irqsave(&phba->hbalock, flags); | ||
5340 | /* make sure the I/O abort window is still open */ | ||
5341 | if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) { | ||
5342 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
5343 | return -EAGAIN; | ||
5344 | } | ||
5290 | list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, | 5345 | list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, |
5291 | list) { | 5346 | list) { |
5292 | if (check_iocb == cmdiocb) { | 5347 | if (check_iocb == cmdiocb) { |
@@ -5296,8 +5351,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
5296 | } | 5351 | } |
5297 | if (list_empty(&completions)) | 5352 | if (list_empty(&completions)) |
5298 | lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); | 5353 | lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); |
5299 | spin_unlock_irq(&phba->hbalock); | 5354 | spin_unlock_irqrestore(&phba->hbalock, flags); |
5300 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
5301 | if (!list_empty(&completions)) { | 5355 | if (!list_empty(&completions)) { |
5302 | lpfc_sli_cancel_iocbs(phba, &completions, | 5356 | lpfc_sli_cancel_iocbs(phba, &completions, |
5303 | IOSTAT_LOCAL_REJECT, | 5357 | IOSTAT_LOCAL_REJECT, |
@@ -5321,9 +5375,10 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
5321 | * remove it from the txq queue and call cancel iocbs. | 5375 | * remove it from the txq queue and call cancel iocbs. |
5322 | * Otherwise, call abort iotag. | 5376 | * Otherwise, call abort iotag. |
5323 | */ | 5377 | */ |
5324 | |||
5325 | cmdiocb = dd_data->context_un.menlo.cmdiocbq; | 5378 | cmdiocb = dd_data->context_un.menlo.cmdiocbq; |
5326 | spin_lock_irq(&phba->hbalock); | 5379 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); |
5380 | |||
5381 | spin_lock_irqsave(&phba->hbalock, flags); | ||
5327 | list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, | 5382 | list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, |
5328 | list) { | 5383 | list) { |
5329 | if (check_iocb == cmdiocb) { | 5384 | if (check_iocb == cmdiocb) { |
@@ -5333,8 +5388,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job) | |||
5333 | } | 5388 | } |
5334 | if (list_empty(&completions)) | 5389 | if (list_empty(&completions)) |
5335 | lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); | 5390 | lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); |
5336 | spin_unlock_irq(&phba->hbalock); | 5391 | spin_unlock_irqrestore(&phba->hbalock, flags); |
5337 | spin_unlock_irqrestore(&phba->ct_ev_lock, flags); | ||
5338 | if (!list_empty(&completions)) { | 5392 | if (!list_empty(&completions)) { |
5339 | lpfc_sli_cancel_iocbs(phba, &completions, | 5393 | lpfc_sli_cancel_iocbs(phba, &completions, |
5340 | IOSTAT_LOCAL_REJECT, | 5394 | IOSTAT_LOCAL_REJECT, |