[SCSI] lpfc 8.3.11: FCF failover improvements
authorJames Smart <james.smart@emulex.com>
Mon, 15 Mar 2010 15:24:56 +0000 (11:24 -0400)
committerJames Bottomley <James.Bottomley@suse.de>
Sun, 11 Apr 2010 14:23:47 +0000 (09:23 -0500)
FCF failover improvements

- Add random FCF failover when there are multiple FCFs available.
- Prevent FCF log messages from being displayed for FC adapters.
- Separate the New FCF and Modified FCF log messages.

Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index 5fbdb22c1899a82be318ff127b28d93ffa1f8285..0a337dab211c3cc49c77c8abaabe2e48016f6d42 100644 (file)
@@ -893,11 +893,14 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
                if (!rc) {
                        /* Mark the FCF discovery process done */
-                       lpfc_printf_vlog(vport, KERN_INFO, LOG_FIP | LOG_ELS,
-                                        "2769 FLOGI successful on FCF record: "
-                                        "current_fcf_index:x%x, terminate FCF "
-                                        "round robin failover process\n",
-                                        phba->fcf.current_rec.fcf_indx);
+                       if (phba->hba_flag & HBA_FIP_SUPPORT)
+                               lpfc_printf_vlog(vport, KERN_INFO, LOG_FIP |
+                                               LOG_ELS,
+                                               "2769 FLOGI successful on FCF "
+                                               "record: current_fcf_index:"
+                                               "x%x, terminate FCF round "
+                                               "robin failover process\n",
+                                               phba->fcf.current_rec.fcf_indx);
                        spin_lock_irq(&phba->hbalock);
                        phba->fcf.fcf_flag &= ~FCF_DISCOVERY;
                        spin_unlock_irq(&phba->hbalock);
index e1466eec56b703ce1d8fda03d85d29b2be1d31cd..362730b6dd85641ddb0f28fcde37666b7a2a316f 100644 (file)
@@ -1531,7 +1531,37 @@ lpfc_check_pending_fcoe_event(struct lpfc_hba *phba, uint8_t unreg_fcf)
 }
 
 /**
- * lpfc_sli4_fcf_rec_mbox_parse - parse non-embedded fcf record mailbox command
+ * lpfc_sli4_new_fcf_random_select - Randomly select an eligible new fcf record
+ * @phba: pointer to lpfc hba data structure.
+ * @fcf_cnt: number of eligible fcf record seen so far.
+ *
+ * This function makes an running random selection decision on FCF record to
+ * use through a sequence of @fcf_cnt eligible FCF records with equal
+ * probability. To perform integer manunipulation of random numbers with
+ * size unit32_t, the lower 16 bits of the 32-bit random number returned
+ * from random32() are taken as the random random number generated.
+ *
+ * Returns true when outcome is for the newly read FCF record should be
+ * chosen; otherwise, return false when outcome is for keeping the previously
+ * chosen FCF record.
+ **/
+static bool
+lpfc_sli4_new_fcf_random_select(struct lpfc_hba *phba, uint32_t fcf_cnt)
+{
+       uint32_t rand_num;
+
+       /* Get 16-bit uniform random number */
+       rand_num = (0xFFFF & random32());
+
+       /* Decision with probability 1/fcf_cnt */
+       if ((fcf_cnt * rand_num) < 0xFFFF)
+               return true;
+       else
+               return false;
+}
+
+/**
+ * lpfc_mbx_cmpl_read_fcf_record - Completion handler for read_fcf mbox.
  * @phba: pointer to lpfc hba data structure.
  * @mboxq: pointer to mailbox object.
  * @next_fcf_index: pointer to holder of next fcf index.
@@ -1679,6 +1709,8 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
        uint16_t fcf_index, next_fcf_index;
        struct lpfc_fcf_rec *fcf_rec = NULL;
        uint16_t vlan_id;
+       uint32_t seed;
+       bool select_new_fcf;
        int rc;
 
        /* If there is pending FCoE event restart FCF table scan */
@@ -1809,9 +1841,21 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                 * than the driver FCF record, use the new record.
                 */
                if (new_fcf_record->fip_priority < fcf_rec->priority) {
-                       /* Choose this FCF record */
+                       /* Choose the new FCF record with lower priority */
                        __lpfc_update_fcf_record(phba, fcf_rec, new_fcf_record,
                                        addr_mode, vlan_id, 0);
+                       /* Reset running random FCF selection count */
+                       phba->fcf.eligible_fcf_cnt = 1;
+               } else if (new_fcf_record->fip_priority == fcf_rec->priority) {
+                       /* Update running random FCF selection count */
+                       phba->fcf.eligible_fcf_cnt++;
+                       select_new_fcf = lpfc_sli4_new_fcf_random_select(phba,
+                                               phba->fcf.eligible_fcf_cnt);
+                       if (select_new_fcf)
+                               /* Choose the new FCF by random selection */
+                               __lpfc_update_fcf_record(phba, fcf_rec,
+                                                        new_fcf_record,
+                                                        addr_mode, vlan_id, 0);
                }
                spin_unlock_irq(&phba->hbalock);
                goto read_next_fcf;
@@ -1825,6 +1869,11 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                                         addr_mode, vlan_id, (boot_flag ?
                                         BOOT_ENABLE : 0));
                phba->fcf.fcf_flag |= FCF_AVAILABLE;
+               /* Setup initial running random FCF selection count */
+               phba->fcf.eligible_fcf_cnt = 1;
+               /* Seeding the random number generator for random selection */
+               seed = (uint32_t)(0xFFFFFFFF & jiffies);
+               srandom32(seed);
        }
        spin_unlock_irq(&phba->hbalock);
        goto read_next_fcf;
index 774663e8e1fe0ff39caf1171de5c29b5ec6d3697..25ee8cc6ab7a1c516b03e6064f81678e7b32590b 100644 (file)
@@ -3304,11 +3304,20 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
        switch (event_type) {
        case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
        case LPFC_FCOE_EVENT_TYPE_FCF_PARAM_MOD:
-               lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY,
-                       "2546 New FCF found/FCF parameter modified event: "
-                       "evt_tag:x%x, fcf_index:x%x\n",
-                       acqe_fcoe->event_tag, acqe_fcoe->index);
-
+               if (event_type == LPFC_FCOE_EVENT_TYPE_NEW_FCF)
+                       lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
+                                       LOG_DISCOVERY,
+                                       "2546 New FCF found event: "
+                                       "evt_tag:x%x, fcf_index:x%x\n",
+                                       acqe_fcoe->event_tag,
+                                       acqe_fcoe->index);
+               else
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_FIP |
+                                       LOG_DISCOVERY,
+                                       "2788 FCF parameter modified event: "
+                                       "evt_tag:x%x, fcf_index:x%x\n",
+                                       acqe_fcoe->event_tag,
+                                       acqe_fcoe->index);
                spin_lock_irq(&phba->hbalock);
                if ((phba->fcf.fcf_flag & FCF_SCAN_DONE) ||
                    (phba->hba_flag & FCF_DISC_INPROGRESS)) {
index 049fb9a17b3f2c7ae730253709c65187289f418e..2eff81d366f970fbfab58decdd1eb3485057b245 100644 (file)
@@ -12040,9 +12040,11 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index)
                phba->hba_flag |= FCF_DISC_INPROGRESS;
                spin_unlock_irq(&phba->hbalock);
                /* Reset FCF round robin index bmask for new scan */
-               if (fcf_index == LPFC_FCOE_FCF_GET_FIRST)
+               if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) {
                        memset(phba->fcf.fcf_rr_bmask, 0,
                               sizeof(*phba->fcf.fcf_rr_bmask));
+                       phba->fcf.eligible_fcf_cnt = 0;
+               }
                error = 0;
        }
 fail_fcf_scan:
index 4a35e7b9bc5b2bd0e36b947cfc77168921c721f6..5b6cb9742c58948ed49a1770d8bb281655b54ece 100644 (file)
@@ -162,6 +162,7 @@ struct lpfc_fcf {
 #define FCF_REDISC_FOV 0x200 /* Post FCF rediscovery fast failover */
        uint32_t addr_mode;
        uint16_t fcf_rr_init_indx;
+       uint32_t eligible_fcf_cnt;
        struct lpfc_fcf_rec current_rec;
        struct lpfc_fcf_rec failover_rec;
        struct timer_list redisc_wait;