diff options
author | James Smart <james.smart@emulex.com> | 2010-02-26 14:15:57 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 08:40:09 -0500 |
commit | 0c9ab6f5cb28199ef5de84874d135ed44f64d92b (patch) | |
tree | 51140c5edce1250e0c06b5a38b540b533b092247 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | fc2b989be9190f3311a5ae41289828e24897a20e (diff) |
[SCSI] lpfc 8.3.10: Added round robin FCF failover
- Added round robin FCF failover on initial or FCF rediscovery FLOGI failure.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 218 |
1 files changed, 204 insertions, 14 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bb6a4426d469..fe6660ca6452 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -11996,15 +11996,19 @@ lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, | |||
11996 | } | 11996 | } |
11997 | 11997 | ||
11998 | /** | 11998 | /** |
11999 | * lpfc_sli4_read_fcf_record - Read the driver's default FCF Record. | 11999 | * lpfc_sli4_fcf_scan_read_fcf_rec - Read hba fcf record for fcf scan. |
12000 | * @phba: pointer to lpfc hba data structure. | 12000 | * @phba: pointer to lpfc hba data structure. |
12001 | * @fcf_index: FCF table entry offset. | 12001 | * @fcf_index: FCF table entry offset. |
12002 | * | 12002 | * |
12003 | * This routine is invoked to read up to @fcf_num of FCF record from the | 12003 | * This routine is invoked to scan the entire FCF table by reading FCF |
12004 | * device starting with the given @fcf_index. | 12004 | * record and processing it one at a time starting from the @fcf_index |
12005 | * for initial FCF discovery or fast FCF failover rediscovery. | ||
12006 | * | ||
12007 | * Return 0 if the mailbox command is submitted sucessfully, none 0 | ||
12008 | * otherwise. | ||
12005 | **/ | 12009 | **/ |
12006 | int | 12010 | int |
12007 | lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | 12011 | lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) |
12008 | { | 12012 | { |
12009 | int rc = 0, error; | 12013 | int rc = 0, error; |
12010 | LPFC_MBOXQ_t *mboxq; | 12014 | LPFC_MBOXQ_t *mboxq; |
@@ -12016,17 +12020,17 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | |||
12016 | "2000 Failed to allocate mbox for " | 12020 | "2000 Failed to allocate mbox for " |
12017 | "READ_FCF cmd\n"); | 12021 | "READ_FCF cmd\n"); |
12018 | error = -ENOMEM; | 12022 | error = -ENOMEM; |
12019 | goto fail_fcfscan; | 12023 | goto fail_fcf_scan; |
12020 | } | 12024 | } |
12021 | /* Construct the read FCF record mailbox command */ | 12025 | /* Construct the read FCF record mailbox command */ |
12022 | rc = lpfc_sli4_mbx_read_fcf_record(phba, mboxq, fcf_index); | 12026 | rc = lpfc_sli4_mbx_read_fcf_rec(phba, mboxq, fcf_index); |
12023 | if (rc) { | 12027 | if (rc) { |
12024 | error = -EINVAL; | 12028 | error = -EINVAL; |
12025 | goto fail_fcfscan; | 12029 | goto fail_fcf_scan; |
12026 | } | 12030 | } |
12027 | /* Issue the mailbox command asynchronously */ | 12031 | /* Issue the mailbox command asynchronously */ |
12028 | mboxq->vport = phba->pport; | 12032 | mboxq->vport = phba->pport; |
12029 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_read_fcf_record; | 12033 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_fcf_scan_read_fcf_rec; |
12030 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | 12034 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); |
12031 | if (rc == MBX_NOT_FINISHED) | 12035 | if (rc == MBX_NOT_FINISHED) |
12032 | error = -EIO; | 12036 | error = -EIO; |
@@ -12034,9 +12038,13 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | |||
12034 | spin_lock_irq(&phba->hbalock); | 12038 | spin_lock_irq(&phba->hbalock); |
12035 | phba->hba_flag |= FCF_DISC_INPROGRESS; | 12039 | phba->hba_flag |= FCF_DISC_INPROGRESS; |
12036 | spin_unlock_irq(&phba->hbalock); | 12040 | spin_unlock_irq(&phba->hbalock); |
12041 | /* Reset FCF round robin index bmask for new scan */ | ||
12042 | if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) | ||
12043 | memset(phba->fcf.fcf_rr_bmask, 0, | ||
12044 | sizeof(*phba->fcf.fcf_rr_bmask)); | ||
12037 | error = 0; | 12045 | error = 0; |
12038 | } | 12046 | } |
12039 | fail_fcfscan: | 12047 | fail_fcf_scan: |
12040 | if (error) { | 12048 | if (error) { |
12041 | if (mboxq) | 12049 | if (mboxq) |
12042 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | 12050 | lpfc_sli4_mbox_cmd_free(phba, mboxq); |
@@ -12049,6 +12057,181 @@ fail_fcfscan: | |||
12049 | } | 12057 | } |
12050 | 12058 | ||
12051 | /** | 12059 | /** |
12060 | * lpfc_sli4_fcf_rr_read_fcf_rec - Read hba fcf record for round robin fcf. | ||
12061 | * @phba: pointer to lpfc hba data structure. | ||
12062 | * @fcf_index: FCF table entry offset. | ||
12063 | * | ||
12064 | * This routine is invoked to read an FCF record indicated by @fcf_index | ||
12065 | * and to use it for FLOGI round robin FCF failover. | ||
12066 | * | ||
12067 | * Return 0 if the mailbox command is submitted sucessfully, none 0 | ||
12068 | * otherwise. | ||
12069 | **/ | ||
12070 | int | ||
12071 | lpfc_sli4_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) | ||
12072 | { | ||
12073 | int rc = 0, error; | ||
12074 | LPFC_MBOXQ_t *mboxq; | ||
12075 | |||
12076 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
12077 | if (!mboxq) { | ||
12078 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_INIT, | ||
12079 | "2763 Failed to allocate mbox for " | ||
12080 | "READ_FCF cmd\n"); | ||
12081 | error = -ENOMEM; | ||
12082 | goto fail_fcf_read; | ||
12083 | } | ||
12084 | /* Construct the read FCF record mailbox command */ | ||
12085 | rc = lpfc_sli4_mbx_read_fcf_rec(phba, mboxq, fcf_index); | ||
12086 | if (rc) { | ||
12087 | error = -EINVAL; | ||
12088 | goto fail_fcf_read; | ||
12089 | } | ||
12090 | /* Issue the mailbox command asynchronously */ | ||
12091 | mboxq->vport = phba->pport; | ||
12092 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_fcf_rr_read_fcf_rec; | ||
12093 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
12094 | if (rc == MBX_NOT_FINISHED) | ||
12095 | error = -EIO; | ||
12096 | else | ||
12097 | error = 0; | ||
12098 | |||
12099 | fail_fcf_read: | ||
12100 | if (error && mboxq) | ||
12101 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
12102 | return error; | ||
12103 | } | ||
12104 | |||
12105 | /** | ||
12106 | * lpfc_sli4_read_fcf_rec - Read hba fcf record for update eligible fcf bmask. | ||
12107 | * @phba: pointer to lpfc hba data structure. | ||
12108 | * @fcf_index: FCF table entry offset. | ||
12109 | * | ||
12110 | * This routine is invoked to read an FCF record indicated by @fcf_index to | ||
12111 | * determine whether it's eligible for FLOGI round robin failover list. | ||
12112 | * | ||
12113 | * Return 0 if the mailbox command is submitted sucessfully, none 0 | ||
12114 | * otherwise. | ||
12115 | **/ | ||
12116 | int | ||
12117 | lpfc_sli4_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) | ||
12118 | { | ||
12119 | int rc = 0, error; | ||
12120 | LPFC_MBOXQ_t *mboxq; | ||
12121 | |||
12122 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
12123 | if (!mboxq) { | ||
12124 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_INIT, | ||
12125 | "2758 Failed to allocate mbox for " | ||
12126 | "READ_FCF cmd\n"); | ||
12127 | error = -ENOMEM; | ||
12128 | goto fail_fcf_read; | ||
12129 | } | ||
12130 | /* Construct the read FCF record mailbox command */ | ||
12131 | rc = lpfc_sli4_mbx_read_fcf_rec(phba, mboxq, fcf_index); | ||
12132 | if (rc) { | ||
12133 | error = -EINVAL; | ||
12134 | goto fail_fcf_read; | ||
12135 | } | ||
12136 | /* Issue the mailbox command asynchronously */ | ||
12137 | mboxq->vport = phba->pport; | ||
12138 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_read_fcf_rec; | ||
12139 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
12140 | if (rc == MBX_NOT_FINISHED) | ||
12141 | error = -EIO; | ||
12142 | else | ||
12143 | error = 0; | ||
12144 | |||
12145 | fail_fcf_read: | ||
12146 | if (error && mboxq) | ||
12147 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
12148 | return error; | ||
12149 | } | ||
12150 | |||
12151 | /** | ||
12152 | * lpfc_sli4_fcf_rr_next_index_get - Get next eligible fcf record index | ||
12153 | * @phba: pointer to lpfc hba data structure. | ||
12154 | * | ||
12155 | * This routine is to get the next eligible FCF record index in a round | ||
12156 | * robin fashion. If the next eligible FCF record index equals to the | ||
12157 | * initial round robin FCF record index, LPFC_FCOE_FCF_NEXT_NONE (0xFFFF) | ||
12158 | * shall be returned, otherwise, the next eligible FCF record's index | ||
12159 | * shall be returned. | ||
12160 | **/ | ||
12161 | uint16_t | ||
12162 | lpfc_sli4_fcf_rr_next_index_get(struct lpfc_hba *phba) | ||
12163 | { | ||
12164 | uint16_t next_fcf_index; | ||
12165 | |||
12166 | /* Search from the currently registered FCF index */ | ||
12167 | next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask, | ||
12168 | LPFC_SLI4_FCF_TBL_INDX_MAX, | ||
12169 | phba->fcf.current_rec.fcf_indx); | ||
12170 | /* Wrap around condition on phba->fcf.fcf_rr_bmask */ | ||
12171 | if (next_fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) | ||
12172 | next_fcf_index = find_next_bit(phba->fcf.fcf_rr_bmask, | ||
12173 | LPFC_SLI4_FCF_TBL_INDX_MAX, 0); | ||
12174 | /* Round robin failover stop condition */ | ||
12175 | if (next_fcf_index == phba->fcf.fcf_rr_init_indx) | ||
12176 | return LPFC_FCOE_FCF_NEXT_NONE; | ||
12177 | |||
12178 | return next_fcf_index; | ||
12179 | } | ||
12180 | |||
12181 | /** | ||
12182 | * lpfc_sli4_fcf_rr_index_set - Set bmask with eligible fcf record index | ||
12183 | * @phba: pointer to lpfc hba data structure. | ||
12184 | * | ||
12185 | * This routine sets the FCF record index in to the eligible bmask for | ||
12186 | * round robin failover search. It checks to make sure that the index | ||
12187 | * does not go beyond the range of the driver allocated bmask dimension | ||
12188 | * before setting the bit. | ||
12189 | * | ||
12190 | * Returns 0 if the index bit successfully set, otherwise, it returns | ||
12191 | * -EINVAL. | ||
12192 | **/ | ||
12193 | int | ||
12194 | lpfc_sli4_fcf_rr_index_set(struct lpfc_hba *phba, uint16_t fcf_index) | ||
12195 | { | ||
12196 | if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { | ||
12197 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP, | ||
12198 | "2610 HBA FCF index reached driver's " | ||
12199 | "book keeping dimension: fcf_index:%d, " | ||
12200 | "driver_bmask_max:%d\n", | ||
12201 | fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); | ||
12202 | return -EINVAL; | ||
12203 | } | ||
12204 | /* Set the eligible FCF record index bmask */ | ||
12205 | set_bit(fcf_index, phba->fcf.fcf_rr_bmask); | ||
12206 | |||
12207 | return 0; | ||
12208 | } | ||
12209 | |||
12210 | /** | ||
12211 | * lpfc_sli4_fcf_rr_index_set - Clear bmask from eligible fcf record index | ||
12212 | * @phba: pointer to lpfc hba data structure. | ||
12213 | * | ||
12214 | * This routine clears the FCF record index from the eligible bmask for | ||
12215 | * round robin failover search. It checks to make sure that the index | ||
12216 | * does not go beyond the range of the driver allocated bmask dimension | ||
12217 | * before clearing the bit. | ||
12218 | **/ | ||
12219 | void | ||
12220 | lpfc_sli4_fcf_rr_index_clear(struct lpfc_hba *phba, uint16_t fcf_index) | ||
12221 | { | ||
12222 | if (fcf_index >= LPFC_SLI4_FCF_TBL_INDX_MAX) { | ||
12223 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP, | ||
12224 | "2762 HBA FCF index goes beyond driver's " | ||
12225 | "book keeping dimension: fcf_index:%d, " | ||
12226 | "driver_bmask_max:%d\n", | ||
12227 | fcf_index, LPFC_SLI4_FCF_TBL_INDX_MAX); | ||
12228 | return; | ||
12229 | } | ||
12230 | /* Clear the eligible FCF record index bmask */ | ||
12231 | clear_bit(fcf_index, phba->fcf.fcf_rr_bmask); | ||
12232 | } | ||
12233 | |||
12234 | /** | ||
12052 | * lpfc_mbx_cmpl_redisc_fcf_table - completion routine for rediscover FCF table | 12235 | * lpfc_mbx_cmpl_redisc_fcf_table - completion routine for rediscover FCF table |
12053 | * @phba: pointer to lpfc hba data structure. | 12236 | * @phba: pointer to lpfc hba data structure. |
12054 | * | 12237 | * |
@@ -12069,13 +12252,13 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
12069 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, | 12252 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, |
12070 | &redisc_fcf->header.cfg_shdr.response); | 12253 | &redisc_fcf->header.cfg_shdr.response); |
12071 | if (shdr_status || shdr_add_status) { | 12254 | if (shdr_status || shdr_add_status) { |
12072 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 12255 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP, |
12073 | "2746 Requesting for FCF rediscovery failed " | 12256 | "2746 Requesting for FCF rediscovery failed " |
12074 | "status x%x add_status x%x\n", | 12257 | "status x%x add_status x%x\n", |
12075 | shdr_status, shdr_add_status); | 12258 | shdr_status, shdr_add_status); |
12076 | if (phba->fcf.fcf_flag & FCF_CVL_FOVER) { | 12259 | if (phba->fcf.fcf_flag & FCF_ACVL_DISC) { |
12077 | spin_lock_irq(&phba->hbalock); | 12260 | spin_lock_irq(&phba->hbalock); |
12078 | phba->fcf.fcf_flag &= ~FCF_CVL_FOVER; | 12261 | phba->fcf.fcf_flag &= ~FCF_ACVL_DISC; |
12079 | spin_unlock_irq(&phba->hbalock); | 12262 | spin_unlock_irq(&phba->hbalock); |
12080 | /* | 12263 | /* |
12081 | * CVL event triggered FCF rediscover request failed, | 12264 | * CVL event triggered FCF rediscover request failed, |
@@ -12084,7 +12267,7 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
12084 | lpfc_retry_pport_discovery(phba); | 12267 | lpfc_retry_pport_discovery(phba); |
12085 | } else { | 12268 | } else { |
12086 | spin_lock_irq(&phba->hbalock); | 12269 | spin_lock_irq(&phba->hbalock); |
12087 | phba->fcf.fcf_flag &= ~FCF_DEAD_FOVER; | 12270 | phba->fcf.fcf_flag &= ~FCF_DEAD_DISC; |
12088 | spin_unlock_irq(&phba->hbalock); | 12271 | spin_unlock_irq(&phba->hbalock); |
12089 | /* | 12272 | /* |
12090 | * DEAD FCF event triggered FCF rediscover request | 12273 | * DEAD FCF event triggered FCF rediscover request |
@@ -12093,12 +12276,16 @@ lpfc_mbx_cmpl_redisc_fcf_table(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
12093 | */ | 12276 | */ |
12094 | lpfc_sli4_fcf_dead_failthrough(phba); | 12277 | lpfc_sli4_fcf_dead_failthrough(phba); |
12095 | } | 12278 | } |
12096 | } else | 12279 | } else { |
12280 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, | ||
12281 | "2775 Start FCF rediscovery quiescent period " | ||
12282 | "wait timer before scaning FCF table\n"); | ||
12097 | /* | 12283 | /* |
12098 | * Start FCF rediscovery wait timer for pending FCF | 12284 | * Start FCF rediscovery wait timer for pending FCF |
12099 | * before rescan FCF record table. | 12285 | * before rescan FCF record table. |
12100 | */ | 12286 | */ |
12101 | lpfc_fcf_redisc_wait_start_timer(phba); | 12287 | lpfc_fcf_redisc_wait_start_timer(phba); |
12288 | } | ||
12102 | 12289 | ||
12103 | mempool_free(mbox, phba->mbox_mem_pool); | 12290 | mempool_free(mbox, phba->mbox_mem_pool); |
12104 | } | 12291 | } |
@@ -12117,6 +12304,9 @@ lpfc_sli4_redisc_fcf_table(struct lpfc_hba *phba) | |||
12117 | struct lpfc_mbx_redisc_fcf_tbl *redisc_fcf; | 12304 | struct lpfc_mbx_redisc_fcf_tbl *redisc_fcf; |
12118 | int rc, length; | 12305 | int rc, length; |
12119 | 12306 | ||
12307 | /* Cancel retry delay timers to all vports before FCF rediscover */ | ||
12308 | lpfc_cancel_all_vport_retry_delay_timer(phba); | ||
12309 | |||
12120 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 12310 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
12121 | if (!mbox) { | 12311 | if (!mbox) { |
12122 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 12312 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |