diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-02-08 18:50:14 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-11 18:52:58 -0500 |
commit | 7f5f3d0d02aa2f124e764aee5c775589ce72fd42 (patch) | |
tree | 511bc7777d9053acbb04215bb682f534d88942f6 /drivers/scsi/lpfc/lpfc_els.c | |
parent | db2378e09151c855e8f92c1b4b2fb4fc5cd8cb40 (diff) |
[SCSI] lpfc 8.2.5 : Miscellaneous discovery Fixes
Miscellaneous discovery fixes:
- Flush RSCN buffers on vports when reseting HBA.
- Fix incorrect FLOGI after vport reg failed
- Fix a potential fabric ELS race condition
- Fix handling of failed PLOGI command under high lip rates
- Fix FDISC handling
- Fix debug logging for npiv handling
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 133 |
1 files changed, 92 insertions, 41 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 60afc8028ff5..cbb68a942255 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1920,18 +1920,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1920 | break; | 1920 | break; |
1921 | 1921 | ||
1922 | case IOERR_ILLEGAL_COMMAND: | 1922 | case IOERR_ILLEGAL_COMMAND: |
1923 | if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) && | 1923 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
1924 | (cmd == ELS_CMD_FDISC)) { | 1924 | "0124 Retry illegal cmd x%x " |
1925 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | 1925 | "retry:x%x delay:x%x\n", |
1926 | "0124 FDISC failed (3/6) " | 1926 | cmd, cmdiocb->retry, delay); |
1927 | "retrying...\n"); | 1927 | retry = 1; |
1928 | lpfc_mbx_unreg_vpi(vport); | 1928 | /* All command's retry policy */ |
1929 | retry = 1; | 1929 | maxretry = 8; |
1930 | /* FDISC retry policy */ | 1930 | if (cmdiocb->retry > 2) |
1931 | maxretry = 48; | 1931 | delay = 1000; |
1932 | if (cmdiocb->retry >= 32) | ||
1933 | delay = 1000; | ||
1934 | } | ||
1935 | break; | 1932 | break; |
1936 | 1933 | ||
1937 | case IOERR_NO_RESOURCES: | 1934 | case IOERR_NO_RESOURCES: |
@@ -2017,6 +2014,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2017 | break; | 2014 | break; |
2018 | 2015 | ||
2019 | case LSRJT_LOGICAL_ERR: | 2016 | case LSRJT_LOGICAL_ERR: |
2017 | /* There are some cases where switches return this | ||
2018 | * error when they are not ready and should be returning | ||
2019 | * Logical Busy. We should delay every time. | ||
2020 | */ | ||
2021 | if (cmd == ELS_CMD_FDISC && | ||
2022 | stat.un.b.lsRjtRsnCodeExp == LSEXP_PORT_LOGIN_REQ) { | ||
2023 | maxretry = 3; | ||
2024 | delay = 1000; | ||
2025 | retry = 1; | ||
2026 | break; | ||
2027 | } | ||
2020 | case LSRJT_PROTOCOL_ERR: | 2028 | case LSRJT_PROTOCOL_ERR: |
2021 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 2029 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
2022 | (cmd == ELS_CMD_FDISC) && | 2030 | (cmd == ELS_CMD_FDISC) && |
@@ -2931,6 +2939,16 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) | |||
2931 | struct lpfc_hba *phba = vport->phba; | 2939 | struct lpfc_hba *phba = vport->phba; |
2932 | int i; | 2940 | int i; |
2933 | 2941 | ||
2942 | spin_lock_irq(shost->host_lock); | ||
2943 | if (vport->fc_rscn_flush) { | ||
2944 | /* Another thread is walking fc_rscn_id_list on this vport */ | ||
2945 | spin_unlock_irq(shost->host_lock); | ||
2946 | return; | ||
2947 | } | ||
2948 | /* Indicate we are walking lpfc_els_flush_rscn on this vport */ | ||
2949 | vport->fc_rscn_flush = 1; | ||
2950 | spin_unlock_irq(shost->host_lock); | ||
2951 | |||
2934 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { | 2952 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { |
2935 | lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]); | 2953 | lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]); |
2936 | vport->fc_rscn_id_list[i] = NULL; | 2954 | vport->fc_rscn_id_list[i] = NULL; |
@@ -2940,6 +2958,8 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport) | |||
2940 | vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); | 2958 | vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); |
2941 | spin_unlock_irq(shost->host_lock); | 2959 | spin_unlock_irq(shost->host_lock); |
2942 | lpfc_can_disctmo(vport); | 2960 | lpfc_can_disctmo(vport); |
2961 | /* Indicate we are done walking this fc_rscn_id_list */ | ||
2962 | vport->fc_rscn_flush = 0; | ||
2943 | } | 2963 | } |
2944 | 2964 | ||
2945 | int | 2965 | int |
@@ -2949,6 +2969,7 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) | |||
2949 | D_ID rscn_did; | 2969 | D_ID rscn_did; |
2950 | uint32_t *lp; | 2970 | uint32_t *lp; |
2951 | uint32_t payload_len, i; | 2971 | uint32_t payload_len, i; |
2972 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
2952 | 2973 | ||
2953 | ns_did.un.word = did; | 2974 | ns_did.un.word = did; |
2954 | 2975 | ||
@@ -2960,6 +2981,15 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) | |||
2960 | if (vport->fc_flag & FC_RSCN_DISCOVERY) | 2981 | if (vport->fc_flag & FC_RSCN_DISCOVERY) |
2961 | return did; | 2982 | return did; |
2962 | 2983 | ||
2984 | spin_lock_irq(shost->host_lock); | ||
2985 | if (vport->fc_rscn_flush) { | ||
2986 | /* Another thread is walking fc_rscn_id_list on this vport */ | ||
2987 | spin_unlock_irq(shost->host_lock); | ||
2988 | return 0; | ||
2989 | } | ||
2990 | /* Indicate we are walking fc_rscn_id_list on this vport */ | ||
2991 | vport->fc_rscn_flush = 1; | ||
2992 | spin_unlock_irq(shost->host_lock); | ||
2963 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { | 2993 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { |
2964 | lp = vport->fc_rscn_id_list[i]->virt; | 2994 | lp = vport->fc_rscn_id_list[i]->virt; |
2965 | payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK); | 2995 | payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK); |
@@ -2970,16 +3000,16 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) | |||
2970 | switch (rscn_did.un.b.resv) { | 3000 | switch (rscn_did.un.b.resv) { |
2971 | case 0: /* Single N_Port ID effected */ | 3001 | case 0: /* Single N_Port ID effected */ |
2972 | if (ns_did.un.word == rscn_did.un.word) | 3002 | if (ns_did.un.word == rscn_did.un.word) |
2973 | return did; | 3003 | goto return_did_out; |
2974 | break; | 3004 | break; |
2975 | case 1: /* Whole N_Port Area effected */ | 3005 | case 1: /* Whole N_Port Area effected */ |
2976 | if ((ns_did.un.b.domain == rscn_did.un.b.domain) | 3006 | if ((ns_did.un.b.domain == rscn_did.un.b.domain) |
2977 | && (ns_did.un.b.area == rscn_did.un.b.area)) | 3007 | && (ns_did.un.b.area == rscn_did.un.b.area)) |
2978 | return did; | 3008 | goto return_did_out; |
2979 | break; | 3009 | break; |
2980 | case 2: /* Whole N_Port Domain effected */ | 3010 | case 2: /* Whole N_Port Domain effected */ |
2981 | if (ns_did.un.b.domain == rscn_did.un.b.domain) | 3011 | if (ns_did.un.b.domain == rscn_did.un.b.domain) |
2982 | return did; | 3012 | goto return_did_out; |
2983 | break; | 3013 | break; |
2984 | default: | 3014 | default: |
2985 | /* Unknown Identifier in RSCN node */ | 3015 | /* Unknown Identifier in RSCN node */ |
@@ -2988,11 +3018,17 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) | |||
2988 | "RSCN payload Data: x%x\n", | 3018 | "RSCN payload Data: x%x\n", |
2989 | rscn_did.un.word); | 3019 | rscn_did.un.word); |
2990 | case 3: /* Whole Fabric effected */ | 3020 | case 3: /* Whole Fabric effected */ |
2991 | return did; | 3021 | goto return_did_out; |
2992 | } | 3022 | } |
2993 | } | 3023 | } |
2994 | } | 3024 | } |
3025 | /* Indicate we are done with walking fc_rscn_id_list on this vport */ | ||
3026 | vport->fc_rscn_flush = 0; | ||
2995 | return 0; | 3027 | return 0; |
3028 | return_did_out: | ||
3029 | /* Indicate we are done with walking fc_rscn_id_list on this vport */ | ||
3030 | vport->fc_rscn_flush = 0; | ||
3031 | return did; | ||
2996 | } | 3032 | } |
2997 | 3033 | ||
2998 | static int | 3034 | static int |
@@ -3034,7 +3070,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3034 | uint32_t *lp, *datap; | 3070 | uint32_t *lp, *datap; |
3035 | IOCB_t *icmd; | 3071 | IOCB_t *icmd; |
3036 | uint32_t payload_len, length, nportid, *cmd; | 3072 | uint32_t payload_len, length, nportid, *cmd; |
3037 | int rscn_cnt = vport->fc_rscn_id_cnt; | 3073 | int rscn_cnt; |
3038 | int rscn_id = 0, hba_id = 0; | 3074 | int rscn_id = 0, hba_id = 0; |
3039 | int i; | 3075 | int i; |
3040 | 3076 | ||
@@ -3047,7 +3083,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3047 | /* RSCN received */ | 3083 | /* RSCN received */ |
3048 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 3084 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
3049 | "0214 RSCN received Data: x%x x%x x%x x%x\n", | 3085 | "0214 RSCN received Data: x%x x%x x%x x%x\n", |
3050 | vport->fc_flag, payload_len, *lp, rscn_cnt); | 3086 | vport->fc_flag, payload_len, *lp, |
3087 | vport->fc_rscn_id_cnt); | ||
3051 | for (i = 0; i < payload_len/sizeof(uint32_t); i++) | 3088 | for (i = 0; i < payload_len/sizeof(uint32_t); i++) |
3052 | fc_host_post_event(shost, fc_get_event_number(), | 3089 | fc_host_post_event(shost, fc_get_event_number(), |
3053 | FCH_EVT_RSCN, lp[i]); | 3090 | FCH_EVT_RSCN, lp[i]); |
@@ -3085,7 +3122,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3085 | "0214 Ignore RSCN " | 3122 | "0214 Ignore RSCN " |
3086 | "Data: x%x x%x x%x x%x\n", | 3123 | "Data: x%x x%x x%x x%x\n", |
3087 | vport->fc_flag, payload_len, | 3124 | vport->fc_flag, payload_len, |
3088 | *lp, rscn_cnt); | 3125 | *lp, vport->fc_rscn_id_cnt); |
3089 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3126 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
3090 | "RCV RSCN vport: did:x%x/ste:x%x flg:x%x", | 3127 | "RCV RSCN vport: did:x%x/ste:x%x flg:x%x", |
3091 | ndlp->nlp_DID, vport->port_state, | 3128 | ndlp->nlp_DID, vport->port_state, |
@@ -3097,6 +3134,18 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3097 | } | 3134 | } |
3098 | } | 3135 | } |
3099 | 3136 | ||
3137 | spin_lock_irq(shost->host_lock); | ||
3138 | if (vport->fc_rscn_flush) { | ||
3139 | /* Another thread is walking fc_rscn_id_list on this vport */ | ||
3140 | spin_unlock_irq(shost->host_lock); | ||
3141 | vport->fc_flag |= FC_RSCN_DISCOVERY; | ||
3142 | return 0; | ||
3143 | } | ||
3144 | /* Indicate we are walking fc_rscn_id_list on this vport */ | ||
3145 | vport->fc_rscn_flush = 1; | ||
3146 | spin_unlock_irq(shost->host_lock); | ||
3147 | /* Get the array count after sucessfully have the token */ | ||
3148 | rscn_cnt = vport->fc_rscn_id_cnt; | ||
3100 | /* If we are already processing an RSCN, save the received | 3149 | /* If we are already processing an RSCN, save the received |
3101 | * RSCN payload buffer, cmdiocb->context2 to process later. | 3150 | * RSCN payload buffer, cmdiocb->context2 to process later. |
3102 | */ | 3151 | */ |
@@ -3118,7 +3167,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3118 | if ((rscn_cnt) && | 3167 | if ((rscn_cnt) && |
3119 | (payload_len + length <= LPFC_BPL_SIZE)) { | 3168 | (payload_len + length <= LPFC_BPL_SIZE)) { |
3120 | *cmd &= ELS_CMD_MASK; | 3169 | *cmd &= ELS_CMD_MASK; |
3121 | *cmd |= be32_to_cpu(payload_len + length); | 3170 | *cmd |= cpu_to_be32(payload_len + length); |
3122 | memcpy(((uint8_t *)cmd) + length, lp, | 3171 | memcpy(((uint8_t *)cmd) + length, lp, |
3123 | payload_len); | 3172 | payload_len); |
3124 | } else { | 3173 | } else { |
@@ -3129,7 +3178,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3129 | */ | 3178 | */ |
3130 | cmdiocb->context2 = NULL; | 3179 | cmdiocb->context2 = NULL; |
3131 | } | 3180 | } |
3132 | |||
3133 | /* Deferred RSCN */ | 3181 | /* Deferred RSCN */ |
3134 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 3182 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
3135 | "0235 Deferred RSCN " | 3183 | "0235 Deferred RSCN " |
@@ -3146,9 +3194,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3146 | vport->fc_rscn_id_cnt, vport->fc_flag, | 3194 | vport->fc_rscn_id_cnt, vport->fc_flag, |
3147 | vport->port_state); | 3195 | vport->port_state); |
3148 | } | 3196 | } |
3197 | /* Indicate we are done walking fc_rscn_id_list on this vport */ | ||
3198 | vport->fc_rscn_flush = 0; | ||
3149 | /* Send back ACC */ | 3199 | /* Send back ACC */ |
3150 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 3200 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
3151 | |||
3152 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 3201 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
3153 | lpfc_rscn_recovery_check(vport); | 3202 | lpfc_rscn_recovery_check(vport); |
3154 | spin_lock_irq(shost->host_lock); | 3203 | spin_lock_irq(shost->host_lock); |
@@ -3156,7 +3205,6 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3156 | spin_unlock_irq(shost->host_lock); | 3205 | spin_unlock_irq(shost->host_lock); |
3157 | return 0; | 3206 | return 0; |
3158 | } | 3207 | } |
3159 | |||
3160 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 3208 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
3161 | "RCV RSCN: did:x%x/ste:x%x flg:x%x", | 3209 | "RCV RSCN: did:x%x/ste:x%x flg:x%x", |
3162 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); | 3210 | ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag); |
@@ -3165,20 +3213,18 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
3165 | vport->fc_flag |= FC_RSCN_MODE; | 3213 | vport->fc_flag |= FC_RSCN_MODE; |
3166 | spin_unlock_irq(shost->host_lock); | 3214 | spin_unlock_irq(shost->host_lock); |
3167 | vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd; | 3215 | vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd; |
3216 | /* Indicate we are done walking fc_rscn_id_list on this vport */ | ||
3217 | vport->fc_rscn_flush = 0; | ||
3168 | /* | 3218 | /* |
3169 | * If we zero, cmdiocb->context2, the calling routine will | 3219 | * If we zero, cmdiocb->context2, the calling routine will |
3170 | * not try to free it. | 3220 | * not try to free it. |
3171 | */ | 3221 | */ |
3172 | cmdiocb->context2 = NULL; | 3222 | cmdiocb->context2 = NULL; |
3173 | |||
3174 | lpfc_set_disctmo(vport); | 3223 | lpfc_set_disctmo(vport); |
3175 | |||
3176 | /* Send back ACC */ | 3224 | /* Send back ACC */ |
3177 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 3225 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
3178 | |||
3179 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 3226 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
3180 | lpfc_rscn_recovery_check(vport); | 3227 | lpfc_rscn_recovery_check(vport); |
3181 | |||
3182 | return lpfc_els_handle_rscn(vport); | 3228 | return lpfc_els_handle_rscn(vport); |
3183 | } | 3229 | } |
3184 | 3230 | ||
@@ -4343,15 +4389,15 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
4343 | vport = lpfc_find_vport_by_vpid(phba, vpi); | 4389 | vport = lpfc_find_vport_by_vpid(phba, vpi); |
4344 | } | 4390 | } |
4345 | } | 4391 | } |
4346 | /* If there are no BDEs associated | 4392 | /* If there are no BDEs associated |
4347 | * with this IOCB, there is nothing to do. | 4393 | * with this IOCB, there is nothing to do. |
4348 | */ | 4394 | */ |
4349 | if (icmd->ulpBdeCount == 0) | 4395 | if (icmd->ulpBdeCount == 0) |
4350 | return; | 4396 | return; |
4351 | 4397 | ||
4352 | /* type of ELS cmd is first 32bit word | 4398 | /* type of ELS cmd is first 32bit word |
4353 | * in packet | 4399 | * in packet |
4354 | */ | 4400 | */ |
4355 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 4401 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
4356 | elsiocb->context2 = bdeBuf1; | 4402 | elsiocb->context2 = bdeBuf1; |
4357 | } else { | 4403 | } else { |
@@ -4464,6 +4510,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
4464 | switch (mb->mbxStatus) { | 4510 | switch (mb->mbxStatus) { |
4465 | case 0x11: /* unsupported feature */ | 4511 | case 0x11: /* unsupported feature */ |
4466 | case 0x9603: /* max_vpi exceeded */ | 4512 | case 0x9603: /* max_vpi exceeded */ |
4513 | case 0x9602: /* Link event since CLEAR_LA */ | ||
4467 | /* giving up on vport registration */ | 4514 | /* giving up on vport registration */ |
4468 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 4515 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
4469 | spin_lock_irq(shost->host_lock); | 4516 | spin_lock_irq(shost->host_lock); |
@@ -4477,7 +4524,10 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
4477 | spin_lock_irq(shost->host_lock); | 4524 | spin_lock_irq(shost->host_lock); |
4478 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 4525 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
4479 | spin_unlock_irq(shost->host_lock); | 4526 | spin_unlock_irq(shost->host_lock); |
4480 | lpfc_initial_fdisc(vport); | 4527 | if (vport->port_type == LPFC_PHYSICAL_PORT) |
4528 | lpfc_initial_flogi(vport); | ||
4529 | else | ||
4530 | lpfc_initial_fdisc(vport); | ||
4481 | break; | 4531 | break; |
4482 | } | 4532 | } |
4483 | 4533 | ||
@@ -4795,11 +4845,12 @@ lpfc_resume_fabric_iocbs(struct lpfc_hba *phba) | |||
4795 | repeat: | 4845 | repeat: |
4796 | iocb = NULL; | 4846 | iocb = NULL; |
4797 | spin_lock_irqsave(&phba->hbalock, iflags); | 4847 | spin_lock_irqsave(&phba->hbalock, iflags); |
4798 | /* Post any pending iocb to the SLI layer */ | 4848 | /* Post any pending iocb to the SLI layer */ |
4799 | if (atomic_read(&phba->fabric_iocb_count) == 0) { | 4849 | if (atomic_read(&phba->fabric_iocb_count) == 0) { |
4800 | list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb), | 4850 | list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb), |
4801 | list); | 4851 | list); |
4802 | if (iocb) | 4852 | if (iocb) |
4853 | /* Increment fabric iocb count to hold the position */ | ||
4803 | atomic_inc(&phba->fabric_iocb_count); | 4854 | atomic_inc(&phba->fabric_iocb_count); |
4804 | } | 4855 | } |
4805 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 4856 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
@@ -4846,9 +4897,7 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) | |||
4846 | int blocked; | 4897 | int blocked; |
4847 | 4898 | ||
4848 | blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); | 4899 | blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); |
4849 | /* Start a timer to unblock fabric | 4900 | /* Start a timer to unblock fabric iocbs after 100ms */ |
4850 | * iocbs after 100ms | ||
4851 | */ | ||
4852 | if (!blocked) | 4901 | if (!blocked) |
4853 | mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 ); | 4902 | mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 ); |
4854 | 4903 | ||
@@ -4896,8 +4945,8 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
4896 | 4945 | ||
4897 | atomic_dec(&phba->fabric_iocb_count); | 4946 | atomic_dec(&phba->fabric_iocb_count); |
4898 | if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) { | 4947 | if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) { |
4899 | /* Post any pending iocbs to HBA */ | 4948 | /* Post any pending iocbs to HBA */ |
4900 | lpfc_resume_fabric_iocbs(phba); | 4949 | lpfc_resume_fabric_iocbs(phba); |
4901 | } | 4950 | } |
4902 | } | 4951 | } |
4903 | 4952 | ||
@@ -4916,6 +4965,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) | |||
4916 | ready = atomic_read(&phba->fabric_iocb_count) == 0 && | 4965 | ready = atomic_read(&phba->fabric_iocb_count) == 0 && |
4917 | !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); | 4966 | !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); |
4918 | 4967 | ||
4968 | if (ready) | ||
4969 | /* Increment fabric iocb count to hold the position */ | ||
4970 | atomic_inc(&phba->fabric_iocb_count); | ||
4919 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 4971 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
4920 | if (ready) { | 4972 | if (ready) { |
4921 | iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; | 4973 | iocb->fabric_iocb_cmpl = iocb->iocb_cmpl; |
@@ -4926,7 +4978,6 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb) | |||
4926 | "Fabric sched2: ste:x%x", | 4978 | "Fabric sched2: ste:x%x", |
4927 | iocb->vport->port_state, 0, 0); | 4979 | iocb->vport->port_state, 0, 0); |
4928 | 4980 | ||
4929 | atomic_inc(&phba->fabric_iocb_count); | ||
4930 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); | 4981 | ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0); |
4931 | 4982 | ||
4932 | if (ret == IOCB_ERROR) { | 4983 | if (ret == IOCB_ERROR) { |