| From c550d34a17483d373c104257759e7920b28fb5c4 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 4 Nov 2019 16:56:58 -0800 |
| Subject: scsi: lpfc: Fix duplicate unreg_rpi error in port offline flow |
| |
| From: James Smart <jsmart2021@gmail.com> |
| |
| [ Upstream commit 7cfd5639d99bec0d27af089d0c8c114330e43a72 ] |
| |
| If the driver receives a login that is later then LOGO'd by the remote port |
| (aka ndlp), the driver, upon the completion of the LOGO ACC transmission, |
| will logout the node and unregister the rpi that is being used for the |
| node. As part of the unreg, the node's rpi value is replaced by the |
| LPFC_RPI_ALLOC_ERROR value. If the port is subsequently offlined, the |
| offline walks the nodes and ensures they are logged out, which possibly |
| entails unreg'ing their rpi values. This path does not validate the node's |
| rpi value, thus doesn't detect that it has been unreg'd already. The |
| replaced rpi value is then used when accessing the rpi bitmask array which |
| tracks active rpi values. As the LPFC_RPI_ALLOC_ERROR value is not a valid |
| index for the bitmask, it may fault the system. |
| |
| Revise the rpi release code to detect when the rpi value is the replaced |
| RPI_ALLOC_ERROR value and ignore further release steps. |
| |
| Link: https://lore.kernel.org/r/20191105005708.7399-2-jsmart2021@gmail.com |
| Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> |
| Signed-off-by: James Smart <jsmart2021@gmail.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/scsi/lpfc/lpfc_sli.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c |
| index bd555f886d27..a801917d3c19 100644 |
| --- a/drivers/scsi/lpfc/lpfc_sli.c |
| +++ b/drivers/scsi/lpfc/lpfc_sli.c |
| @@ -17867,6 +17867,13 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) |
| static void |
| __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) |
| { |
| + /* |
| + * if the rpi value indicates a prior unreg has already |
| + * been done, skip the unreg. |
| + */ |
| + if (rpi == LPFC_RPI_ALLOC_ERROR) |
| + return; |
| + |
| if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { |
| phba->sli4_hba.rpi_count--; |
| phba->sli4_hba.max_cfg_param.rpi_used--; |
| -- |
| 2.20.1 |
| |