diff options
author | James Smart <jsmart2021@gmail.com> | 2017-05-15 18:20:38 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-05-16 21:17:28 -0400 |
commit | 845d9e8df2fa879e6494e786f290e1fd5560ac8c (patch) | |
tree | 233bffeef163127322ed046af93bb173ef75ed1e | |
parent | dd6e1f71b785a6ac2511e2ddb86315f292873e59 (diff) |
scsi: lpfc: Fix used-RPI accounting problem.
With 255 vports created a link trasition can casue a crash.
When going through discovery after a link bounce the driver is using
rpis before the cmd FCOE_POST_HDR_TEMPLATES completes. By doing that the
next rpi bumps the rpi range out of the boundary.
The fix it to increment the next_rpi only when the
FCOE_POST_HDR_TEMPLATE succeeds.
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 24 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 8 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 1 |
4 files changed, 16 insertions, 20 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 67827e397431..3f9f6d5f8c69 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -8667,7 +8667,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
8667 | lpfc_do_scr_ns_plogi(phba, vport); | 8667 | lpfc_do_scr_ns_plogi(phba, vport); |
8668 | goto out; | 8668 | goto out; |
8669 | fdisc_failed: | 8669 | fdisc_failed: |
8670 | if (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS) | 8670 | if (vport->fc_vport && |
8671 | (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS)) | ||
8671 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 8672 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
8672 | /* Cancel discovery timer */ | 8673 | /* Cancel discovery timer */ |
8673 | lpfc_can_disctmo(vport); | 8674 | lpfc_can_disctmo(vport); |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 4b1eb98c228d..b1b181a756dc 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -6525,7 +6525,6 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
6525 | uint16_t rpi_limit, curr_rpi_range; | 6525 | uint16_t rpi_limit, curr_rpi_range; |
6526 | struct lpfc_dmabuf *dmabuf; | 6526 | struct lpfc_dmabuf *dmabuf; |
6527 | struct lpfc_rpi_hdr *rpi_hdr; | 6527 | struct lpfc_rpi_hdr *rpi_hdr; |
6528 | uint32_t rpi_count; | ||
6529 | 6528 | ||
6530 | /* | 6529 | /* |
6531 | * If the SLI4 port supports extents, posting the rpi header isn't | 6530 | * If the SLI4 port supports extents, posting the rpi header isn't |
@@ -6538,8 +6537,7 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
6538 | return NULL; | 6537 | return NULL; |
6539 | 6538 | ||
6540 | /* The limit on the logical index is just the max_rpi count. */ | 6539 | /* The limit on the logical index is just the max_rpi count. */ |
6541 | rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base + | 6540 | rpi_limit = phba->sli4_hba.max_cfg_param.max_rpi; |
6542 | phba->sli4_hba.max_cfg_param.max_rpi - 1; | ||
6543 | 6541 | ||
6544 | spin_lock_irq(&phba->hbalock); | 6542 | spin_lock_irq(&phba->hbalock); |
6545 | /* | 6543 | /* |
@@ -6550,18 +6548,10 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
6550 | curr_rpi_range = phba->sli4_hba.next_rpi; | 6548 | curr_rpi_range = phba->sli4_hba.next_rpi; |
6551 | spin_unlock_irq(&phba->hbalock); | 6549 | spin_unlock_irq(&phba->hbalock); |
6552 | 6550 | ||
6553 | /* | 6551 | /* Reached full RPI range */ |
6554 | * The port has a limited number of rpis. The increment here | 6552 | if (curr_rpi_range == rpi_limit) |
6555 | * is LPFC_RPI_HDR_COUNT - 1 to account for the starting value | ||
6556 | * and to allow the full max_rpi range per port. | ||
6557 | */ | ||
6558 | if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit) | ||
6559 | rpi_count = rpi_limit - curr_rpi_range; | ||
6560 | else | ||
6561 | rpi_count = LPFC_RPI_HDR_COUNT; | ||
6562 | |||
6563 | if (!rpi_count) | ||
6564 | return NULL; | 6553 | return NULL; |
6554 | |||
6565 | /* | 6555 | /* |
6566 | * First allocate the protocol header region for the port. The | 6556 | * First allocate the protocol header region for the port. The |
6567 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. | 6557 | * port expects a 4KB DMA-mapped memory region that is 4K aligned. |
@@ -6595,13 +6585,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba) | |||
6595 | 6585 | ||
6596 | /* The rpi_hdr stores the logical index only. */ | 6586 | /* The rpi_hdr stores the logical index only. */ |
6597 | rpi_hdr->start_rpi = curr_rpi_range; | 6587 | rpi_hdr->start_rpi = curr_rpi_range; |
6588 | rpi_hdr->next_rpi = phba->sli4_hba.next_rpi + LPFC_RPI_HDR_COUNT; | ||
6598 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); | 6589 | list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list); |
6599 | 6590 | ||
6600 | /* | ||
6601 | * The next_rpi stores the next logical module-64 rpi value used | ||
6602 | * to post physical rpis in subsequent rpi postings. | ||
6603 | */ | ||
6604 | phba->sli4_hba.next_rpi += rpi_count; | ||
6605 | spin_unlock_irq(&phba->hbalock); | 6591 | spin_unlock_irq(&phba->hbalock); |
6606 | return rpi_hdr; | 6592 | return rpi_hdr; |
6607 | 6593 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2a4fc00dfa9b..e2d25ae5ba45 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -17137,6 +17137,14 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | |||
17137 | "status x%x add_status x%x, mbx status x%x\n", | 17137 | "status x%x add_status x%x, mbx status x%x\n", |
17138 | shdr_status, shdr_add_status, rc); | 17138 | shdr_status, shdr_add_status, rc); |
17139 | rc = -ENXIO; | 17139 | rc = -ENXIO; |
17140 | } else { | ||
17141 | /* | ||
17142 | * The next_rpi stores the next logical module-64 rpi value used | ||
17143 | * to post physical rpis in subsequent rpi postings. | ||
17144 | */ | ||
17145 | spin_lock_irq(&phba->hbalock); | ||
17146 | phba->sli4_hba.next_rpi = rpi_page->next_rpi; | ||
17147 | spin_unlock_irq(&phba->hbalock); | ||
17140 | } | 17148 | } |
17141 | return rc; | 17149 | return rc; |
17142 | } | 17150 | } |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index da46471337c8..915e8d5581bd 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -698,6 +698,7 @@ struct lpfc_rpi_hdr { | |||
698 | struct lpfc_dmabuf *dmabuf; | 698 | struct lpfc_dmabuf *dmabuf; |
699 | uint32_t page_count; | 699 | uint32_t page_count; |
700 | uint32_t start_rpi; | 700 | uint32_t start_rpi; |
701 | uint16_t next_rpi; | ||
701 | }; | 702 | }; |
702 | 703 | ||
703 | struct lpfc_rsrc_blks { | 704 | struct lpfc_rsrc_blks { |