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 | |
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>
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 33 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 133 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_logmsg.h | 10 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mem.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 4 |
9 files changed, 127 insertions, 66 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 10f983b479c6..6c178f1c8786 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -307,6 +307,7 @@ struct lpfc_vport { | |||
307 | 307 | ||
308 | uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */ | 308 | uint32_t fc_nlp_cnt; /* outstanding NODELIST requests */ |
309 | uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */ | 309 | uint32_t fc_rscn_id_cnt; /* count of RSCNs payloads in list */ |
310 | uint32_t fc_rscn_flush; /* flag use of fc_rscn_id_list */ | ||
310 | struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN]; | 311 | struct lpfc_dmabuf *fc_rscn_id_list[FC_MAX_HOLD_RSCN]; |
311 | struct lpfc_name fc_nodename; /* fc nodename */ | 312 | struct lpfc_name fc_nodename; /* fc nodename */ |
312 | struct lpfc_name fc_portname; /* fc portname */ | 313 | struct lpfc_name fc_portname; /* fc portname */ |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index aea8d33f6d09..3d0ccd9b341d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -775,7 +775,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
775 | "0267 NameServer GFF Rsp " | 775 | "0267 NameServer GFF Rsp " |
776 | "x%x Error (%d %d) Data: x%x x%x\n", | 776 | "x%x Error (%d %d) Data: x%x x%x\n", |
777 | did, irsp->ulpStatus, irsp->un.ulpWord[4], | 777 | did, irsp->ulpStatus, irsp->un.ulpWord[4], |
778 | vport->fc_flag, vport->fc_rscn_id_cnt) | 778 | vport->fc_flag, vport->fc_rscn_id_cnt); |
779 | } | 779 | } |
780 | 780 | ||
781 | /* This is a target port, unregistered port, or the GFF_ID failed */ | 781 | /* This is a target port, unregistered port, or the GFF_ID failed */ |
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 8eb007309599..2db0b74b6fad 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -91,25 +91,26 @@ struct lpfc_nodelist { | |||
91 | }; | 91 | }; |
92 | 92 | ||
93 | /* Defines for nlp_flag (uint32) */ | 93 | /* Defines for nlp_flag (uint32) */ |
94 | #define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */ | 94 | #define NLP_PLOGI_SND 0x00000020 /* sent PLOGI request for this entry */ |
95 | #define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */ | 95 | #define NLP_PRLI_SND 0x00000040 /* sent PRLI request for this entry */ |
96 | #define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */ | 96 | #define NLP_ADISC_SND 0x00000080 /* sent ADISC request for this entry */ |
97 | #define NLP_LOGO_SND 0x100 /* sent LOGO request for this entry */ | 97 | #define NLP_LOGO_SND 0x00000100 /* sent LOGO request for this entry */ |
98 | #define NLP_RNID_SND 0x400 /* sent RNID request for this entry */ | 98 | #define NLP_RNID_SND 0x00000400 /* sent RNID request for this entry */ |
99 | #define NLP_ELS_SND_MASK 0x7e0 /* sent ELS request for this entry */ | 99 | #define NLP_ELS_SND_MASK 0x000007e0 /* sent ELS request for this entry */ |
100 | #define NLP_DEFER_RM 0x10000 /* Remove this ndlp if no longer used */ | 100 | #define NLP_DEFER_RM 0x00010000 /* Remove this ndlp if no longer used */ |
101 | #define NLP_DELAY_TMO 0x20000 /* delay timeout is running for node */ | 101 | #define NLP_DELAY_TMO 0x00020000 /* delay timeout is running for node */ |
102 | #define NLP_NPR_2B_DISC 0x40000 /* node is included in num_disc_nodes */ | 102 | #define NLP_NPR_2B_DISC 0x00040000 /* node is included in num_disc_nodes */ |
103 | #define NLP_RCV_PLOGI 0x80000 /* Rcv'ed PLOGI from remote system */ | 103 | #define NLP_RCV_PLOGI 0x00080000 /* Rcv'ed PLOGI from remote system */ |
104 | #define NLP_LOGO_ACC 0x100000 /* Process LOGO after ACC completes */ | 104 | #define NLP_LOGO_ACC 0x00100000 /* Process LOGO after ACC completes */ |
105 | #define NLP_TGT_NO_SCSIID 0x200000 /* good PRLI but no binding for scsid */ | 105 | #define NLP_TGT_NO_SCSIID 0x00200000 /* good PRLI but no binding for scsid */ |
106 | #define NLP_ACC_REGLOGIN 0x1000000 /* Issue Reg Login after successful | 106 | #define NLP_ACC_REGLOGIN 0x01000000 /* Issue Reg Login after successful |
107 | ACC */ | 107 | ACC */ |
108 | #define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from | 108 | #define NLP_NPR_ADISC 0x02000000 /* Issue ADISC when dq'ed from |
109 | NPR list */ | 109 | NPR list */ |
110 | #define NLP_RM_DFLT_RPI 0x4000000 /* need to remove leftover dflt RPI */ | 110 | #define NLP_RM_DFLT_RPI 0x04000000 /* need to remove leftover dflt RPI */ |
111 | #define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */ | 111 | #define NLP_NODEV_REMOVE 0x08000000 /* Defer removal till discovery ends */ |
112 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ | 112 | #define NLP_TARGET_REMOVE 0x10000000 /* Target remove in process */ |
113 | #define NLP_SC_REQ 0x20000000 /* Target requires authentication */ | ||
113 | 114 | ||
114 | /* ndlp usage management macros */ | 115 | /* ndlp usage management macros */ |
115 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ | 116 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ |
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) { |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 041f83e7634a..543ed3ca8b76 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -581,6 +581,7 @@ struct ls_rjt { /* Structure is in Big Endian format */ | |||
581 | #define LSEXP_INVALID_O_SID 0x15 | 581 | #define LSEXP_INVALID_O_SID 0x15 |
582 | #define LSEXP_INVALID_OX_RX 0x17 | 582 | #define LSEXP_INVALID_OX_RX 0x17 |
583 | #define LSEXP_CMD_IN_PROGRESS 0x19 | 583 | #define LSEXP_CMD_IN_PROGRESS 0x19 |
584 | #define LSEXP_PORT_LOGIN_REQ 0x1E | ||
584 | #define LSEXP_INVALID_NPORT_ID 0x1F | 585 | #define LSEXP_INVALID_NPORT_ID 0x1F |
585 | #define LSEXP_INVALID_SEQ_ID 0x21 | 586 | #define LSEXP_INVALID_SEQ_ID 0x21 |
586 | #define LSEXP_INVALID_XCHG 0x23 | 587 | #define LSEXP_INVALID_XCHG 0x23 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index a087524acf41..7a5ce3355808 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -475,7 +475,8 @@ lpfc_hba_down_prep(struct lpfc_hba *phba) | |||
475 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) | 475 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) |
476 | lpfc_cleanup_discovery_resources(vports[i]); | 476 | lpfc_cleanup_discovery_resources(vports[i]); |
477 | lpfc_destroy_vport_work_array(phba, vports); | 477 | lpfc_destroy_vport_work_array(phba, vports); |
478 | } return 0; | 478 | } |
479 | return 0; | ||
479 | } | 480 | } |
480 | 481 | ||
481 | /************************************************************************/ | 482 | /************************************************************************/ |
@@ -1740,9 +1741,9 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |||
1740 | 1741 | ||
1741 | vport = (struct lpfc_vport *) shost->hostdata; | 1742 | vport = (struct lpfc_vport *) shost->hostdata; |
1742 | vport->phba = phba; | 1743 | vport->phba = phba; |
1743 | |||
1744 | vport->load_flag |= FC_LOADING; | 1744 | vport->load_flag |= FC_LOADING; |
1745 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 1745 | vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
1746 | vport->fc_rscn_flush = 0; | ||
1746 | 1747 | ||
1747 | lpfc_get_vport_cfgparam(vport); | 1748 | lpfc_get_vport_cfgparam(vport); |
1748 | shost->unique_id = instance; | 1749 | shost->unique_id = instance; |
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index c5841d7565f7..39fd2b843bec 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2005 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2008 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -35,11 +35,15 @@ | |||
35 | #define LOG_ALL_MSG 0xffff /* LOG all messages */ | 35 | #define LOG_ALL_MSG 0xffff /* LOG all messages */ |
36 | 36 | ||
37 | #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ | 37 | #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ |
38 | do { \ | ||
38 | { if (((mask) &(vport)->cfg_log_verbose) || (level[1] <= '3')) \ | 39 | { if (((mask) &(vport)->cfg_log_verbose) || (level[1] <= '3')) \ |
39 | dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ | 40 | dev_printk(level, &((vport)->phba->pcidev)->dev, "%d:(%d):" \ |
40 | fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } | 41 | fmt, (vport)->phba->brd_no, vport->vpi, ##arg); } \ |
42 | } while (0) | ||
41 | 43 | ||
42 | #define lpfc_printf_log(phba, level, mask, fmt, arg...) \ | 44 | #define lpfc_printf_log(phba, level, mask, fmt, arg...) \ |
45 | do { \ | ||
43 | { if (((mask) &(phba)->pport->cfg_log_verbose) || (level[1] <= '3')) \ | 46 | { if (((mask) &(phba)->pport->cfg_log_verbose) || (level[1] <= '3')) \ |
44 | dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ | 47 | dev_printk(level, &((phba)->pcidev)->dev, "%d:" \ |
45 | fmt, phba->brd_no, ##arg); } | 48 | fmt, phba->brd_no, ##arg); } \ |
49 | } while (0) | ||
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 6dc5ab8d6716..27448c98c07a 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
@@ -265,6 +265,9 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) | |||
265 | { | 265 | { |
266 | struct hbq_dmabuf *hbq_entry; | 266 | struct hbq_dmabuf *hbq_entry; |
267 | 267 | ||
268 | if (!mp) | ||
269 | return; | ||
270 | |||
268 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { | 271 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { |
269 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); | 272 | hbq_entry = container_of(mp, struct hbq_dmabuf, dbuf); |
270 | if (hbq_entry->tag == -1) { | 273 | if (hbq_entry->tag == -1) { |
@@ -279,4 +282,3 @@ lpfc_in_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) | |||
279 | } | 282 | } |
280 | return; | 283 | return; |
281 | } | 284 | } |
282 | |||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 456b8ec7753b..c8c5b48baa66 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -2623,14 +2623,14 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
2623 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | 2623 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); |
2624 | 2624 | ||
2625 | /* Mbox command <mbxCommand> cannot issue */ | 2625 | /* Mbox command <mbxCommand> cannot issue */ |
2626 | LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag) | 2626 | LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag); |
2627 | return MBX_NOT_FINISHED; | 2627 | return MBX_NOT_FINISHED; |
2628 | } | 2628 | } |
2629 | 2629 | ||
2630 | if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT && | 2630 | if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT && |
2631 | !(readl(phba->HCregaddr) & HC_MBINT_ENA)) { | 2631 | !(readl(phba->HCregaddr) & HC_MBINT_ENA)) { |
2632 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | 2632 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); |
2633 | LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag) | 2633 | LOG_MBOX_CANNOT_ISSUE_DATA(phba, pmbox, psli, flag); |
2634 | return MBX_NOT_FINISHED; | 2634 | return MBX_NOT_FINISHED; |
2635 | } | 2635 | } |
2636 | 2636 | ||