OSDN Git Service

scsi: lpfc: Fix used-RPI accounting problem.
authorJames Smart <jsmart2021@gmail.com>
Mon, 15 May 2017 22:20:38 +0000 (15:20 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 17 May 2017 01:17:28 +0000 (21:17 -0400)
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>
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index 67827e3..3f9f6d5 100644 (file)
@@ -8667,7 +8667,8 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                lpfc_do_scr_ns_plogi(phba, vport);
        goto out;
 fdisc_failed:
-       if (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS)
+       if (vport->fc_vport &&
+           (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS))
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
        /* Cancel discovery timer */
        lpfc_can_disctmo(vport);
index 4b1eb98..b1b181a 100644 (file)
@@ -6525,7 +6525,6 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        uint16_t rpi_limit, curr_rpi_range;
        struct lpfc_dmabuf *dmabuf;
        struct lpfc_rpi_hdr *rpi_hdr;
-       uint32_t rpi_count;
 
        /*
         * 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)
                return NULL;
 
        /* The limit on the logical index is just the max_rpi count. */
-       rpi_limit = phba->sli4_hba.max_cfg_param.rpi_base +
-       phba->sli4_hba.max_cfg_param.max_rpi - 1;
+       rpi_limit = phba->sli4_hba.max_cfg_param.max_rpi;
 
        spin_lock_irq(&phba->hbalock);
        /*
@@ -6550,18 +6548,10 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        curr_rpi_range = phba->sli4_hba.next_rpi;
        spin_unlock_irq(&phba->hbalock);
 
-       /*
-        * The port has a limited number of rpis. The increment here
-        * is LPFC_RPI_HDR_COUNT - 1 to account for the starting value
-        * and to allow the full max_rpi range per port.
-        */
-       if ((curr_rpi_range + (LPFC_RPI_HDR_COUNT - 1)) > rpi_limit)
-               rpi_count = rpi_limit - curr_rpi_range;
-       else
-               rpi_count = LPFC_RPI_HDR_COUNT;
-
-       if (!rpi_count)
+       /* Reached full RPI range */
+       if (curr_rpi_range == rpi_limit)
                return NULL;
+
        /*
         * First allocate the protocol header region for the port.  The
         * 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)
 
        /* The rpi_hdr stores the logical index only. */
        rpi_hdr->start_rpi = curr_rpi_range;
+       rpi_hdr->next_rpi = phba->sli4_hba.next_rpi + LPFC_RPI_HDR_COUNT;
        list_add_tail(&rpi_hdr->list, &phba->sli4_hba.lpfc_rpi_hdr_list);
 
-       /*
-        * The next_rpi stores the next logical module-64 rpi value used
-        * to post physical rpis in subsequent rpi postings.
-        */
-       phba->sli4_hba.next_rpi += rpi_count;
        spin_unlock_irq(&phba->hbalock);
        return rpi_hdr;
 
index 2a4fc00..e2d25ae 100644 (file)
@@ -17137,6 +17137,14 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
                                "status x%x add_status x%x, mbx status x%x\n",
                                shdr_status, shdr_add_status, rc);
                rc = -ENXIO;
+       } else {
+               /*
+                * The next_rpi stores the next logical module-64 rpi value used
+                * to post physical rpis in subsequent rpi postings.
+                */
+               spin_lock_irq(&phba->hbalock);
+               phba->sli4_hba.next_rpi = rpi_page->next_rpi;
+               spin_unlock_irq(&phba->hbalock);
        }
        return rc;
 }
index da46471..915e8d5 100644 (file)
@@ -698,6 +698,7 @@ struct lpfc_rpi_hdr {
        struct lpfc_dmabuf *dmabuf;
        uint32_t page_count;
        uint32_t start_rpi;
+       uint16_t next_rpi;
 };
 
 struct lpfc_rsrc_blks {