diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 1325 |
1 files changed, 729 insertions, 596 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index b309841e3846..bca2f5c9b4ba 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1,4 +1,4 @@ | |||
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-2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * |
@@ -35,20 +35,22 @@ | |||
35 | #include "lpfc.h" | 35 | #include "lpfc.h" |
36 | #include "lpfc_logmsg.h" | 36 | #include "lpfc_logmsg.h" |
37 | #include "lpfc_crtn.h" | 37 | #include "lpfc_crtn.h" |
38 | #include "lpfc_vport.h" | ||
39 | #include "lpfc_debugfs.h" | ||
38 | 40 | ||
39 | 41 | ||
40 | /* Called to verify a rcv'ed ADISC was intended for us. */ | 42 | /* Called to verify a rcv'ed ADISC was intended for us. */ |
41 | static int | 43 | static int |
42 | lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 44 | lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
43 | struct lpfc_name * nn, struct lpfc_name * pn) | 45 | struct lpfc_name *nn, struct lpfc_name *pn) |
44 | { | 46 | { |
45 | /* Compare the ADISC rsp WWNN / WWPN matches our internal node | 47 | /* Compare the ADISC rsp WWNN / WWPN matches our internal node |
46 | * table entry for that node. | 48 | * table entry for that node. |
47 | */ | 49 | */ |
48 | if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)) != 0) | 50 | if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name))) |
49 | return 0; | 51 | return 0; |
50 | 52 | ||
51 | if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)) != 0) | 53 | if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name))) |
52 | return 0; | 54 | return 0; |
53 | 55 | ||
54 | /* we match, return success */ | 56 | /* we match, return success */ |
@@ -56,11 +58,10 @@ lpfc_check_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
56 | } | 58 | } |
57 | 59 | ||
58 | int | 60 | int |
59 | lpfc_check_sparm(struct lpfc_hba * phba, | 61 | lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
60 | struct lpfc_nodelist * ndlp, struct serv_parm * sp, | 62 | struct serv_parm * sp, uint32_t class) |
61 | uint32_t class) | ||
62 | { | 63 | { |
63 | volatile struct serv_parm *hsp = &phba->fc_sparam; | 64 | volatile struct serv_parm *hsp = &vport->fc_sparam; |
64 | uint16_t hsp_value, ssp_value = 0; | 65 | uint16_t hsp_value, ssp_value = 0; |
65 | 66 | ||
66 | /* | 67 | /* |
@@ -75,12 +76,14 @@ lpfc_check_sparm(struct lpfc_hba * phba, | |||
75 | hsp->cls1.rcvDataSizeLsb; | 76 | hsp->cls1.rcvDataSizeLsb; |
76 | ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | | 77 | ssp_value = (sp->cls1.rcvDataSizeMsb << 8) | |
77 | sp->cls1.rcvDataSizeLsb; | 78 | sp->cls1.rcvDataSizeLsb; |
79 | if (!ssp_value) | ||
80 | goto bad_service_param; | ||
78 | if (ssp_value > hsp_value) { | 81 | if (ssp_value > hsp_value) { |
79 | sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; | 82 | sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb; |
80 | sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; | 83 | sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb; |
81 | } | 84 | } |
82 | } else if (class == CLASS1) { | 85 | } else if (class == CLASS1) { |
83 | return 0; | 86 | goto bad_service_param; |
84 | } | 87 | } |
85 | 88 | ||
86 | if (sp->cls2.classValid) { | 89 | if (sp->cls2.classValid) { |
@@ -88,12 +91,14 @@ lpfc_check_sparm(struct lpfc_hba * phba, | |||
88 | hsp->cls2.rcvDataSizeLsb; | 91 | hsp->cls2.rcvDataSizeLsb; |
89 | ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | | 92 | ssp_value = (sp->cls2.rcvDataSizeMsb << 8) | |
90 | sp->cls2.rcvDataSizeLsb; | 93 | sp->cls2.rcvDataSizeLsb; |
94 | if (!ssp_value) | ||
95 | goto bad_service_param; | ||
91 | if (ssp_value > hsp_value) { | 96 | if (ssp_value > hsp_value) { |
92 | sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; | 97 | sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb; |
93 | sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; | 98 | sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb; |
94 | } | 99 | } |
95 | } else if (class == CLASS2) { | 100 | } else if (class == CLASS2) { |
96 | return 0; | 101 | goto bad_service_param; |
97 | } | 102 | } |
98 | 103 | ||
99 | if (sp->cls3.classValid) { | 104 | if (sp->cls3.classValid) { |
@@ -101,12 +106,14 @@ lpfc_check_sparm(struct lpfc_hba * phba, | |||
101 | hsp->cls3.rcvDataSizeLsb; | 106 | hsp->cls3.rcvDataSizeLsb; |
102 | ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | | 107 | ssp_value = (sp->cls3.rcvDataSizeMsb << 8) | |
103 | sp->cls3.rcvDataSizeLsb; | 108 | sp->cls3.rcvDataSizeLsb; |
109 | if (!ssp_value) | ||
110 | goto bad_service_param; | ||
104 | if (ssp_value > hsp_value) { | 111 | if (ssp_value > hsp_value) { |
105 | sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; | 112 | sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb; |
106 | sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; | 113 | sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb; |
107 | } | 114 | } |
108 | } else if (class == CLASS3) { | 115 | } else if (class == CLASS3) { |
109 | return 0; | 116 | goto bad_service_param; |
110 | } | 117 | } |
111 | 118 | ||
112 | /* | 119 | /* |
@@ -125,12 +132,22 @@ lpfc_check_sparm(struct lpfc_hba * phba, | |||
125 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); | 132 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); |
126 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); | 133 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name)); |
127 | return 1; | 134 | return 1; |
135 | bad_service_param: | ||
136 | lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, | ||
137 | "%d (%d):0207 Device %x " | ||
138 | "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent " | ||
139 | "invalid service parameters. Ignoring device.\n", | ||
140 | vport->phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, | ||
141 | sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1], | ||
142 | sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3], | ||
143 | sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5], | ||
144 | sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]); | ||
145 | return 0; | ||
128 | } | 146 | } |
129 | 147 | ||
130 | static void * | 148 | static void * |
131 | lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, | 149 | lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
132 | struct lpfc_iocbq *cmdiocb, | 150 | struct lpfc_iocbq *rspiocb) |
133 | struct lpfc_iocbq *rspiocb) | ||
134 | { | 151 | { |
135 | struct lpfc_dmabuf *pcmd, *prsp; | 152 | struct lpfc_dmabuf *pcmd, *prsp; |
136 | uint32_t *lp; | 153 | uint32_t *lp; |
@@ -168,32 +185,29 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba, | |||
168 | * routine effectively results in a "software abort". | 185 | * routine effectively results in a "software abort". |
169 | */ | 186 | */ |
170 | int | 187 | int |
171 | lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | 188 | lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
172 | { | 189 | { |
173 | LIST_HEAD(completions); | 190 | LIST_HEAD(completions); |
174 | struct lpfc_sli *psli; | 191 | struct lpfc_sli *psli = &phba->sli; |
175 | struct lpfc_sli_ring *pring; | 192 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
176 | struct lpfc_iocbq *iocb, *next_iocb; | 193 | struct lpfc_iocbq *iocb, *next_iocb; |
177 | IOCB_t *cmd; | 194 | IOCB_t *cmd; |
178 | 195 | ||
179 | /* Abort outstanding I/O on NPort <nlp_DID> */ | 196 | /* Abort outstanding I/O on NPort <nlp_DID> */ |
180 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 197 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
181 | "%d:0205 Abort outstanding I/O on NPort x%x " | 198 | "%d (%d):0205 Abort outstanding I/O on NPort x%x " |
182 | "Data: x%x x%x x%x\n", | 199 | "Data: x%x x%x x%x\n", |
183 | phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, | 200 | phba->brd_no, ndlp->vport->vpi, ndlp->nlp_DID, |
184 | ndlp->nlp_state, ndlp->nlp_rpi); | 201 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
185 | 202 | ||
186 | psli = &phba->sli; | 203 | lpfc_fabric_abort_nport(ndlp); |
187 | pring = &psli->ring[LPFC_ELS_RING]; | ||
188 | 204 | ||
189 | /* First check the txq */ | 205 | /* First check the txq */ |
190 | spin_lock_irq(phba->host->host_lock); | 206 | spin_lock_irq(&phba->hbalock); |
191 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 207 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
192 | /* Check to see if iocb matches the nport we are looking | 208 | /* Check to see if iocb matches the nport we are looking for */ |
193 | for */ | ||
194 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { | 209 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
195 | /* It matches, so deque and call compl with an | 210 | /* It matches, so deque and call compl with anp error */ |
196 | error */ | ||
197 | list_move_tail(&iocb->list, &completions); | 211 | list_move_tail(&iocb->list, &completions); |
198 | pring->txq_cnt--; | 212 | pring->txq_cnt--; |
199 | } | 213 | } |
@@ -201,37 +215,39 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) | |||
201 | 215 | ||
202 | /* Next check the txcmplq */ | 216 | /* Next check the txcmplq */ |
203 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 217 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
204 | /* Check to see if iocb matches the nport we are looking | 218 | /* Check to see if iocb matches the nport we are looking for */ |
205 | for */ | 219 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { |
206 | if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) | ||
207 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 220 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
221 | } | ||
208 | } | 222 | } |
209 | spin_unlock_irq(phba->host->host_lock); | 223 | spin_unlock_irq(&phba->hbalock); |
210 | 224 | ||
211 | while (!list_empty(&completions)) { | 225 | while (!list_empty(&completions)) { |
212 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | 226 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); |
213 | cmd = &iocb->iocb; | 227 | cmd = &iocb->iocb; |
214 | list_del(&iocb->list); | 228 | list_del_init(&iocb->list); |
215 | 229 | ||
216 | if (iocb->iocb_cmpl) { | 230 | if (!iocb->iocb_cmpl) |
231 | lpfc_sli_release_iocbq(phba, iocb); | ||
232 | else { | ||
217 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | 233 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
218 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | 234 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
219 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 235 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
220 | } else | 236 | } |
221 | lpfc_sli_release_iocbq(phba, iocb); | ||
222 | } | 237 | } |
223 | 238 | ||
224 | /* If we are delaying issuing an ELS command, cancel it */ | 239 | /* If we are delaying issuing an ELS command, cancel it */ |
225 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 240 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
226 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 241 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); |
227 | return 0; | 242 | return 0; |
228 | } | 243 | } |
229 | 244 | ||
230 | static int | 245 | static int |
231 | lpfc_rcv_plogi(struct lpfc_hba * phba, | 246 | lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
232 | struct lpfc_nodelist * ndlp, | 247 | struct lpfc_iocbq *cmdiocb) |
233 | struct lpfc_iocbq *cmdiocb) | ||
234 | { | 248 | { |
249 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
250 | struct lpfc_hba *phba = vport->phba; | ||
235 | struct lpfc_dmabuf *pcmd; | 251 | struct lpfc_dmabuf *pcmd; |
236 | uint32_t *lp; | 252 | uint32_t *lp; |
237 | IOCB_t *icmd; | 253 | IOCB_t *icmd; |
@@ -241,14 +257,14 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
241 | int rc; | 257 | int rc; |
242 | 258 | ||
243 | memset(&stat, 0, sizeof (struct ls_rjt)); | 259 | memset(&stat, 0, sizeof (struct ls_rjt)); |
244 | if (phba->hba_state <= LPFC_FLOGI) { | 260 | if (vport->port_state <= LPFC_FLOGI) { |
245 | /* Before responding to PLOGI, check for pt2pt mode. | 261 | /* Before responding to PLOGI, check for pt2pt mode. |
246 | * If we are pt2pt, with an outstanding FLOGI, abort | 262 | * If we are pt2pt, with an outstanding FLOGI, abort |
247 | * the FLOGI and resend it first. | 263 | * the FLOGI and resend it first. |
248 | */ | 264 | */ |
249 | if (phba->fc_flag & FC_PT2PT) { | 265 | if (vport->fc_flag & FC_PT2PT) { |
250 | lpfc_els_abort_flogi(phba); | 266 | lpfc_els_abort_flogi(phba); |
251 | if (!(phba->fc_flag & FC_PT2PT_PLOGI)) { | 267 | if (!(vport->fc_flag & FC_PT2PT_PLOGI)) { |
252 | /* If the other side is supposed to initiate | 268 | /* If the other side is supposed to initiate |
253 | * the PLOGI anyway, just ACC it now and | 269 | * the PLOGI anyway, just ACC it now and |
254 | * move on with discovery. | 270 | * move on with discovery. |
@@ -257,45 +273,42 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
257 | phba->fc_ratov = FF_DEF_RATOV; | 273 | phba->fc_ratov = FF_DEF_RATOV; |
258 | /* Start discovery - this should just do | 274 | /* Start discovery - this should just do |
259 | CLEAR_LA */ | 275 | CLEAR_LA */ |
260 | lpfc_disc_start(phba); | 276 | lpfc_disc_start(vport); |
261 | } else { | 277 | } else |
262 | lpfc_initial_flogi(phba); | 278 | lpfc_initial_flogi(vport); |
263 | } | ||
264 | } else { | 279 | } else { |
265 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; | 280 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; |
266 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 281 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
267 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, | 282 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, |
268 | ndlp); | 283 | ndlp, NULL); |
269 | return 0; | 284 | return 0; |
270 | } | 285 | } |
271 | } | 286 | } |
272 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 287 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
273 | lp = (uint32_t *) pcmd->virt; | 288 | lp = (uint32_t *) pcmd->virt; |
274 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 289 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
275 | if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3) == 0)) { | 290 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) { |
276 | /* Reject this request because invalid parameters */ | 291 | /* Reject this request because invalid parameters */ |
277 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 292 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
278 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 293 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
279 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 294 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
295 | NULL); | ||
280 | return 0; | 296 | return 0; |
281 | } | 297 | } |
282 | icmd = &cmdiocb->iocb; | 298 | icmd = &cmdiocb->iocb; |
283 | 299 | ||
284 | /* PLOGI chkparm OK */ | 300 | /* PLOGI chkparm OK */ |
285 | lpfc_printf_log(phba, | 301 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
286 | KERN_INFO, | 302 | "%d (%d):0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", |
287 | LOG_ELS, | 303 | phba->brd_no, vport->vpi, |
288 | "%d:0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", | ||
289 | phba->brd_no, | ||
290 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, | 304 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, |
291 | ndlp->nlp_rpi); | 305 | ndlp->nlp_rpi); |
292 | 306 | ||
293 | if ((phba->cfg_fcp_class == 2) && | 307 | if (phba->cfg_fcp_class == 2 && sp->cls2.classValid) |
294 | (sp->cls2.classValid)) { | ||
295 | ndlp->nlp_fcp_info |= CLASS2; | 308 | ndlp->nlp_fcp_info |= CLASS2; |
296 | } else { | 309 | else |
297 | ndlp->nlp_fcp_info |= CLASS3; | 310 | ndlp->nlp_fcp_info |= CLASS3; |
298 | } | 311 | |
299 | ndlp->nlp_class_sup = 0; | 312 | ndlp->nlp_class_sup = 0; |
300 | if (sp->cls1.classValid) | 313 | if (sp->cls1.classValid) |
301 | ndlp->nlp_class_sup |= FC_COS_CLASS1; | 314 | ndlp->nlp_class_sup |= FC_COS_CLASS1; |
@@ -317,35 +330,37 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
317 | case NLP_STE_PRLI_ISSUE: | 330 | case NLP_STE_PRLI_ISSUE: |
318 | case NLP_STE_UNMAPPED_NODE: | 331 | case NLP_STE_UNMAPPED_NODE: |
319 | case NLP_STE_MAPPED_NODE: | 332 | case NLP_STE_MAPPED_NODE: |
320 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); | 333 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, 0); |
321 | return 1; | 334 | return 1; |
322 | } | 335 | } |
323 | 336 | ||
324 | if ((phba->fc_flag & FC_PT2PT) | 337 | if ((vport->fc_flag & FC_PT2PT) && |
325 | && !(phba->fc_flag & FC_PT2PT_PLOGI)) { | 338 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { |
326 | /* rcv'ed PLOGI decides what our NPortId will be */ | 339 | /* rcv'ed PLOGI decides what our NPortId will be */ |
327 | phba->fc_myDID = icmd->un.rcvels.parmRo; | 340 | vport->fc_myDID = icmd->un.rcvels.parmRo; |
328 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 341 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
329 | if (mbox == NULL) | 342 | if (mbox == NULL) |
330 | goto out; | 343 | goto out; |
331 | lpfc_config_link(phba, mbox); | 344 | lpfc_config_link(phba, mbox); |
332 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 345 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
346 | mbox->vport = vport; | ||
333 | rc = lpfc_sli_issue_mbox | 347 | rc = lpfc_sli_issue_mbox |
334 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); | 348 | (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); |
335 | if (rc == MBX_NOT_FINISHED) { | 349 | if (rc == MBX_NOT_FINISHED) { |
336 | mempool_free( mbox, phba->mbox_mem_pool); | 350 | mempool_free(mbox, phba->mbox_mem_pool); |
337 | goto out; | 351 | goto out; |
338 | } | 352 | } |
339 | 353 | ||
340 | lpfc_can_disctmo(phba); | 354 | lpfc_can_disctmo(vport); |
341 | } | 355 | } |
342 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 356 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
343 | if (mbox == NULL) | 357 | if (!mbox) |
344 | goto out; | 358 | goto out; |
345 | 359 | ||
346 | if (lpfc_reg_login(phba, icmd->un.rcvels.remoteID, | 360 | rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID, |
347 | (uint8_t *) sp, mbox, 0)) { | 361 | (uint8_t *) sp, mbox, 0); |
348 | mempool_free( mbox, phba->mbox_mem_pool); | 362 | if (rc) { |
363 | mempool_free(mbox, phba->mbox_mem_pool); | ||
349 | goto out; | 364 | goto out; |
350 | } | 365 | } |
351 | 366 | ||
@@ -357,7 +372,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
357 | * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox | 372 | * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox |
358 | * command issued in lpfc_cmpl_els_acc(). | 373 | * command issued in lpfc_cmpl_els_acc(). |
359 | */ | 374 | */ |
375 | mbox->vport = vport; | ||
376 | spin_lock_irq(shost->host_lock); | ||
360 | ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); | 377 | ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); |
378 | spin_unlock_irq(shost->host_lock); | ||
361 | 379 | ||
362 | /* | 380 | /* |
363 | * If there is an outstanding PLOGI issued, abort it before | 381 | * If there is an outstanding PLOGI issued, abort it before |
@@ -373,24 +391,41 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, | |||
373 | lpfc_els_abort(phba, ndlp); | 391 | lpfc_els_abort(phba, ndlp); |
374 | } | 392 | } |
375 | 393 | ||
376 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); | 394 | if ((vport->port_type == LPFC_NPIV_PORT && |
395 | phba->cfg_vport_restrict_login)) { | ||
396 | |||
397 | /* In order to preserve RPIs, we want to cleanup | ||
398 | * the default RPI the firmware created to rcv | ||
399 | * this ELS request. The only way to do this is | ||
400 | * to register, then unregister the RPI. | ||
401 | */ | ||
402 | spin_lock_irq(shost->host_lock); | ||
403 | ndlp->nlp_flag |= NLP_RM_DFLT_RPI; | ||
404 | spin_unlock_irq(shost->host_lock); | ||
405 | stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD; | ||
406 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
407 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, | ||
408 | ndlp, mbox); | ||
409 | return 1; | ||
410 | } | ||
411 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); | ||
377 | return 1; | 412 | return 1; |
378 | 413 | ||
379 | out: | 414 | out: |
380 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 415 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
381 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; | 416 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; |
382 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 417 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
383 | return 0; | 418 | return 0; |
384 | } | 419 | } |
385 | 420 | ||
386 | static int | 421 | static int |
387 | lpfc_rcv_padisc(struct lpfc_hba * phba, | 422 | lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
388 | struct lpfc_nodelist * ndlp, | ||
389 | struct lpfc_iocbq *cmdiocb) | 423 | struct lpfc_iocbq *cmdiocb) |
390 | { | 424 | { |
425 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
391 | struct lpfc_dmabuf *pcmd; | 426 | struct lpfc_dmabuf *pcmd; |
392 | struct serv_parm *sp; | 427 | struct serv_parm *sp; |
393 | struct lpfc_name *pnn, *ppn; | 428 | struct lpfc_name *pnn, *ppn; |
394 | struct ls_rjt stat; | 429 | struct ls_rjt stat; |
395 | ADISC *ap; | 430 | ADISC *ap; |
396 | IOCB_t *icmd; | 431 | IOCB_t *icmd; |
@@ -412,13 +447,12 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, | |||
412 | } | 447 | } |
413 | 448 | ||
414 | icmd = &cmdiocb->iocb; | 449 | icmd = &cmdiocb->iocb; |
415 | if ((icmd->ulpStatus == 0) && | 450 | if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) { |
416 | (lpfc_check_adisc(phba, ndlp, pnn, ppn))) { | ||
417 | if (cmd == ELS_CMD_ADISC) { | 451 | if (cmd == ELS_CMD_ADISC) { |
418 | lpfc_els_rsp_adisc_acc(phba, cmdiocb, ndlp); | 452 | lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); |
419 | } else { | 453 | } else { |
420 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, | 454 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, |
421 | NULL, 0); | 455 | NULL, 0); |
422 | } | 456 | } |
423 | return 1; | 457 | return 1; |
424 | } | 458 | } |
@@ -427,55 +461,57 @@ lpfc_rcv_padisc(struct lpfc_hba * phba, | |||
427 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 461 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
428 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 462 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
429 | stat.un.b.vendorUnique = 0; | 463 | stat.un.b.vendorUnique = 0; |
430 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 464 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
431 | 465 | ||
432 | /* 1 sec timeout */ | 466 | /* 1 sec timeout */ |
433 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 467 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
434 | 468 | ||
435 | spin_lock_irq(phba->host->host_lock); | 469 | spin_lock_irq(shost->host_lock); |
436 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 470 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
437 | spin_unlock_irq(phba->host->host_lock); | 471 | spin_unlock_irq(shost->host_lock); |
438 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 472 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
439 | ndlp->nlp_prev_state = ndlp->nlp_state; | 473 | ndlp->nlp_prev_state = ndlp->nlp_state; |
440 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 474 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
441 | return 0; | 475 | return 0; |
442 | } | 476 | } |
443 | 477 | ||
444 | static int | 478 | static int |
445 | lpfc_rcv_logo(struct lpfc_hba * phba, | 479 | lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
446 | struct lpfc_nodelist * ndlp, | 480 | struct lpfc_iocbq *cmdiocb, uint32_t els_cmd) |
447 | struct lpfc_iocbq *cmdiocb, | ||
448 | uint32_t els_cmd) | ||
449 | { | 481 | { |
450 | /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */ | 482 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
483 | |||
484 | /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */ | ||
451 | /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary | 485 | /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary |
452 | * PLOGIs during LOGO storms from a device. | 486 | * PLOGIs during LOGO storms from a device. |
453 | */ | 487 | */ |
488 | spin_lock_irq(shost->host_lock); | ||
454 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 489 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
490 | spin_unlock_irq(shost->host_lock); | ||
455 | if (els_cmd == ELS_CMD_PRLO) | 491 | if (els_cmd == ELS_CMD_PRLO) |
456 | lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 492 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); |
457 | else | 493 | else |
458 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 494 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
459 | 495 | ||
460 | if (!(ndlp->nlp_type & NLP_FABRIC) || | 496 | if (!(ndlp->nlp_type & NLP_FABRIC) || |
461 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 497 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
462 | /* Only try to re-login if this is NOT a Fabric Node */ | 498 | /* Only try to re-login if this is NOT a Fabric Node */ |
463 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 499 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
464 | spin_lock_irq(phba->host->host_lock); | 500 | spin_lock_irq(shost->host_lock); |
465 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 501 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
466 | spin_unlock_irq(phba->host->host_lock); | 502 | spin_unlock_irq(shost->host_lock); |
467 | 503 | ||
468 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 504 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
469 | ndlp->nlp_prev_state = ndlp->nlp_state; | 505 | ndlp->nlp_prev_state = ndlp->nlp_state; |
470 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 506 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
471 | } else { | 507 | } else { |
472 | ndlp->nlp_prev_state = ndlp->nlp_state; | 508 | ndlp->nlp_prev_state = ndlp->nlp_state; |
473 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 509 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
474 | } | 510 | } |
475 | 511 | ||
476 | spin_lock_irq(phba->host->host_lock); | 512 | spin_lock_irq(shost->host_lock); |
477 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 513 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
478 | spin_unlock_irq(phba->host->host_lock); | 514 | spin_unlock_irq(shost->host_lock); |
479 | /* The driver has to wait until the ACC completes before it continues | 515 | /* The driver has to wait until the ACC completes before it continues |
480 | * processing the LOGO. The action will resume in | 516 | * processing the LOGO. The action will resume in |
481 | * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an | 517 | * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an |
@@ -485,9 +521,8 @@ lpfc_rcv_logo(struct lpfc_hba * phba, | |||
485 | } | 521 | } |
486 | 522 | ||
487 | static void | 523 | static void |
488 | lpfc_rcv_prli(struct lpfc_hba * phba, | 524 | lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
489 | struct lpfc_nodelist * ndlp, | 525 | struct lpfc_iocbq *cmdiocb) |
490 | struct lpfc_iocbq *cmdiocb) | ||
491 | { | 526 | { |
492 | struct lpfc_dmabuf *pcmd; | 527 | struct lpfc_dmabuf *pcmd; |
493 | uint32_t *lp; | 528 | uint32_t *lp; |
@@ -501,8 +536,7 @@ lpfc_rcv_prli(struct lpfc_hba * phba, | |||
501 | 536 | ||
502 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); | 537 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
503 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | 538 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
504 | if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) && | 539 | if (npr->prliType == PRLI_FCP_TYPE) { |
505 | (npr->prliType == PRLI_FCP_TYPE)) { | ||
506 | if (npr->initiatorFunc) | 540 | if (npr->initiatorFunc) |
507 | ndlp->nlp_type |= NLP_FCP_INITIATOR; | 541 | ndlp->nlp_type |= NLP_FCP_INITIATOR; |
508 | if (npr->targetFunc) | 542 | if (npr->targetFunc) |
@@ -517,36 +551,42 @@ lpfc_rcv_prli(struct lpfc_hba * phba, | |||
517 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 551 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
518 | if (ndlp->nlp_type & NLP_FCP_TARGET) | 552 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
519 | roles |= FC_RPORT_ROLE_FCP_TARGET; | 553 | roles |= FC_RPORT_ROLE_FCP_TARGET; |
554 | |||
555 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | ||
556 | "rport rolechg: role:x%x did:x%x flg:x%x", | ||
557 | roles, ndlp->nlp_DID, ndlp->nlp_flag); | ||
558 | |||
520 | fc_remote_port_rolechg(rport, roles); | 559 | fc_remote_port_rolechg(rport, roles); |
521 | } | 560 | } |
522 | } | 561 | } |
523 | 562 | ||
524 | static uint32_t | 563 | static uint32_t |
525 | lpfc_disc_set_adisc(struct lpfc_hba * phba, | 564 | lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
526 | struct lpfc_nodelist * ndlp) | ||
527 | { | 565 | { |
566 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
567 | struct lpfc_hba *phba = vport->phba; | ||
568 | |||
528 | /* Check config parameter use-adisc or FCP-2 */ | 569 | /* Check config parameter use-adisc or FCP-2 */ |
529 | if ((phba->cfg_use_adisc == 0) && | 570 | if ((phba->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) || |
530 | !(phba->fc_flag & FC_RSCN_MODE)) { | 571 | ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) { |
531 | if (!(ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) | 572 | spin_lock_irq(shost->host_lock); |
532 | return 0; | 573 | ndlp->nlp_flag |= NLP_NPR_ADISC; |
574 | spin_unlock_irq(shost->host_lock); | ||
575 | return 1; | ||
533 | } | 576 | } |
534 | spin_lock_irq(phba->host->host_lock); | 577 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
535 | ndlp->nlp_flag |= NLP_NPR_ADISC; | 578 | lpfc_unreg_rpi(vport, ndlp); |
536 | spin_unlock_irq(phba->host->host_lock); | 579 | return 0; |
537 | return 1; | ||
538 | } | 580 | } |
539 | 581 | ||
540 | static uint32_t | 582 | static uint32_t |
541 | lpfc_disc_illegal(struct lpfc_hba * phba, | 583 | lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
542 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 584 | void *arg, uint32_t evt) |
543 | { | 585 | { |
544 | lpfc_printf_log(phba, | 586 | lpfc_printf_log(vport->phba, KERN_ERR, LOG_DISCOVERY, |
545 | KERN_ERR, | 587 | "%d (%d):0253 Illegal State Transition: node x%x " |
546 | LOG_DISCOVERY, | 588 | "event x%x, state x%x Data: x%x x%x\n", |
547 | "%d:0253 Illegal State Transition: node x%x event x%x, " | 589 | vport->phba->brd_no, vport->vpi, |
548 | "state x%x Data: x%x x%x\n", | ||
549 | phba->brd_no, | ||
550 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, | 590 | ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi, |
551 | ndlp->nlp_flag); | 591 | ndlp->nlp_flag); |
552 | return ndlp->nlp_state; | 592 | return ndlp->nlp_state; |
@@ -555,151 +595,162 @@ lpfc_disc_illegal(struct lpfc_hba * phba, | |||
555 | /* Start of Discovery State Machine routines */ | 595 | /* Start of Discovery State Machine routines */ |
556 | 596 | ||
557 | static uint32_t | 597 | static uint32_t |
558 | lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba, | 598 | lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
559 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 599 | void *arg, uint32_t evt) |
560 | { | 600 | { |
561 | struct lpfc_iocbq *cmdiocb; | 601 | struct lpfc_iocbq *cmdiocb; |
562 | 602 | ||
563 | cmdiocb = (struct lpfc_iocbq *) arg; | 603 | cmdiocb = (struct lpfc_iocbq *) arg; |
564 | 604 | ||
565 | if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { | 605 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
566 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | 606 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; |
567 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 607 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
568 | return ndlp->nlp_state; | 608 | return ndlp->nlp_state; |
569 | } | 609 | } |
570 | lpfc_drop_node(phba, ndlp); | 610 | lpfc_drop_node(vport, ndlp); |
571 | return NLP_STE_FREED_NODE; | 611 | return NLP_STE_FREED_NODE; |
572 | } | 612 | } |
573 | 613 | ||
574 | static uint32_t | 614 | static uint32_t |
575 | lpfc_rcv_els_unused_node(struct lpfc_hba * phba, | 615 | lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
576 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 616 | void *arg, uint32_t evt) |
577 | { | 617 | { |
578 | lpfc_issue_els_logo(phba, ndlp, 0); | 618 | lpfc_issue_els_logo(vport, ndlp, 0); |
579 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 619 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
580 | return ndlp->nlp_state; | 620 | return ndlp->nlp_state; |
581 | } | 621 | } |
582 | 622 | ||
583 | static uint32_t | 623 | static uint32_t |
584 | lpfc_rcv_logo_unused_node(struct lpfc_hba * phba, | 624 | lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
585 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 625 | void *arg, uint32_t evt) |
586 | { | 626 | { |
587 | struct lpfc_iocbq *cmdiocb; | 627 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
588 | 628 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | |
589 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
590 | 629 | ||
591 | spin_lock_irq(phba->host->host_lock); | 630 | spin_lock_irq(shost->host_lock); |
592 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 631 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
593 | spin_unlock_irq(phba->host->host_lock); | 632 | spin_unlock_irq(shost->host_lock); |
594 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 633 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
595 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 634 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
596 | 635 | ||
597 | return ndlp->nlp_state; | 636 | return ndlp->nlp_state; |
598 | } | 637 | } |
599 | 638 | ||
600 | static uint32_t | 639 | static uint32_t |
601 | lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba, | 640 | lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
602 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 641 | void *arg, uint32_t evt) |
603 | { | 642 | { |
604 | lpfc_drop_node(phba, ndlp); | 643 | lpfc_drop_node(vport, ndlp); |
605 | return NLP_STE_FREED_NODE; | 644 | return NLP_STE_FREED_NODE; |
606 | } | 645 | } |
607 | 646 | ||
608 | static uint32_t | 647 | static uint32_t |
609 | lpfc_device_rm_unused_node(struct lpfc_hba * phba, | 648 | lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
610 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 649 | void *arg, uint32_t evt) |
611 | { | 650 | { |
612 | lpfc_drop_node(phba, ndlp); | 651 | lpfc_drop_node(vport, ndlp); |
613 | return NLP_STE_FREED_NODE; | 652 | return NLP_STE_FREED_NODE; |
614 | } | 653 | } |
615 | 654 | ||
616 | static uint32_t | 655 | static uint32_t |
617 | lpfc_rcv_plogi_plogi_issue(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 656 | lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
618 | void *arg, uint32_t evt) | 657 | void *arg, uint32_t evt) |
619 | { | 658 | { |
659 | struct lpfc_hba *phba = vport->phba; | ||
620 | struct lpfc_iocbq *cmdiocb = arg; | 660 | struct lpfc_iocbq *cmdiocb = arg; |
621 | struct lpfc_dmabuf *pcmd; | 661 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
622 | struct serv_parm *sp; | 662 | uint32_t *lp = (uint32_t *) pcmd->virt; |
623 | uint32_t *lp; | 663 | struct serv_parm *sp = (struct serv_parm *) (lp + 1); |
624 | struct ls_rjt stat; | 664 | struct ls_rjt stat; |
625 | int port_cmp; | 665 | int port_cmp; |
626 | 666 | ||
627 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
628 | lp = (uint32_t *) pcmd->virt; | ||
629 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | ||
630 | |||
631 | memset(&stat, 0, sizeof (struct ls_rjt)); | 667 | memset(&stat, 0, sizeof (struct ls_rjt)); |
632 | 668 | ||
633 | /* For a PLOGI, we only accept if our portname is less | 669 | /* For a PLOGI, we only accept if our portname is less |
634 | * than the remote portname. | 670 | * than the remote portname. |
635 | */ | 671 | */ |
636 | phba->fc_stat.elsLogiCol++; | 672 | phba->fc_stat.elsLogiCol++; |
637 | port_cmp = memcmp(&phba->fc_portname, &sp->portName, | 673 | port_cmp = memcmp(&vport->fc_portname, &sp->portName, |
638 | sizeof (struct lpfc_name)); | 674 | sizeof(struct lpfc_name)); |
639 | 675 | ||
640 | if (port_cmp >= 0) { | 676 | if (port_cmp >= 0) { |
641 | /* Reject this request because the remote node will accept | 677 | /* Reject this request because the remote node will accept |
642 | ours */ | 678 | ours */ |
643 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 679 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
644 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; | 680 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; |
645 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 681 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
682 | NULL); | ||
646 | } else { | 683 | } else { |
647 | lpfc_rcv_plogi(phba, ndlp, cmdiocb); | 684 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
648 | } /* if our portname was less */ | 685 | } /* If our portname was less */ |
649 | 686 | ||
650 | return ndlp->nlp_state; | 687 | return ndlp->nlp_state; |
651 | } | 688 | } |
652 | 689 | ||
653 | static uint32_t | 690 | static uint32_t |
654 | lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba, | 691 | lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
655 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 692 | void *arg, uint32_t evt) |
656 | { | 693 | { |
657 | struct lpfc_iocbq *cmdiocb; | 694 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
695 | struct ls_rjt stat; | ||
658 | 696 | ||
659 | cmdiocb = (struct lpfc_iocbq *) arg; | 697 | memset(&stat, 0, sizeof (struct ls_rjt)); |
698 | stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; | ||
699 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | ||
700 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | ||
701 | return ndlp->nlp_state; | ||
702 | } | ||
660 | 703 | ||
661 | /* software abort outstanding PLOGI */ | 704 | static uint32_t |
662 | lpfc_els_abort(phba, ndlp); | 705 | lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
706 | void *arg, uint32_t evt) | ||
707 | { | ||
708 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | ||
709 | |||
710 | /* software abort outstanding PLOGI */ | ||
711 | lpfc_els_abort(vport->phba, ndlp); | ||
663 | 712 | ||
664 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 713 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
665 | return ndlp->nlp_state; | 714 | return ndlp->nlp_state; |
666 | } | 715 | } |
667 | 716 | ||
668 | static uint32_t | 717 | static uint32_t |
669 | lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba, | 718 | lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
670 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 719 | void *arg, uint32_t evt) |
671 | { | 720 | { |
672 | struct lpfc_iocbq *cmdiocb; | 721 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
673 | 722 | struct lpfc_hba *phba = vport->phba; | |
674 | cmdiocb = (struct lpfc_iocbq *) arg; | 723 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
675 | 724 | ||
676 | /* software abort outstanding PLOGI */ | 725 | /* software abort outstanding PLOGI */ |
677 | lpfc_els_abort(phba, ndlp); | 726 | lpfc_els_abort(phba, ndlp); |
678 | 727 | ||
679 | if (evt == NLP_EVT_RCV_LOGO) { | 728 | if (evt == NLP_EVT_RCV_LOGO) { |
680 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 729 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
681 | } else { | 730 | } else { |
682 | lpfc_issue_els_logo(phba, ndlp, 0); | 731 | lpfc_issue_els_logo(vport, ndlp, 0); |
683 | } | 732 | } |
684 | 733 | ||
685 | /* Put ndlp in npr list set plogi timer for 1 sec */ | 734 | /* Put ndlp in npr state set plogi timer for 1 sec */ |
686 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 735 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
687 | spin_lock_irq(phba->host->host_lock); | 736 | spin_lock_irq(shost->host_lock); |
688 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 737 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
689 | spin_unlock_irq(phba->host->host_lock); | 738 | spin_unlock_irq(shost->host_lock); |
690 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 739 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
691 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; | 740 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; |
692 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 741 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
693 | 742 | ||
694 | return ndlp->nlp_state; | 743 | return ndlp->nlp_state; |
695 | } | 744 | } |
696 | 745 | ||
697 | static uint32_t | 746 | static uint32_t |
698 | lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | 747 | lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, |
699 | struct lpfc_nodelist * ndlp, void *arg, | 748 | struct lpfc_nodelist *ndlp, |
749 | void *arg, | ||
700 | uint32_t evt) | 750 | uint32_t evt) |
701 | { | 751 | { |
702 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 752 | struct lpfc_hba *phba = vport->phba; |
753 | struct lpfc_iocbq *cmdiocb, *rspiocb; | ||
703 | struct lpfc_dmabuf *pcmd, *prsp, *mp; | 754 | struct lpfc_dmabuf *pcmd, *prsp, *mp; |
704 | uint32_t *lp; | 755 | uint32_t *lp; |
705 | IOCB_t *irsp; | 756 | IOCB_t *irsp; |
@@ -721,31 +772,26 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
721 | 772 | ||
722 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 773 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
723 | 774 | ||
724 | prsp = list_get_first(&pcmd->list, | 775 | prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); |
725 | struct lpfc_dmabuf, | ||
726 | list); | ||
727 | lp = (uint32_t *) prsp->virt; | ||
728 | 776 | ||
777 | lp = (uint32_t *) prsp->virt; | ||
729 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 778 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
730 | if (!lpfc_check_sparm(phba, ndlp, sp, CLASS3)) | 779 | if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3)) |
731 | goto out; | 780 | goto out; |
732 | 781 | ||
733 | /* PLOGI chkparm OK */ | 782 | /* PLOGI chkparm OK */ |
734 | lpfc_printf_log(phba, | 783 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
735 | KERN_INFO, | 784 | "%d (%d):0121 PLOGI chkparm OK " |
736 | LOG_ELS, | ||
737 | "%d:0121 PLOGI chkparm OK " | ||
738 | "Data: x%x x%x x%x x%x\n", | 785 | "Data: x%x x%x x%x x%x\n", |
739 | phba->brd_no, | 786 | phba->brd_no, vport->vpi, |
740 | ndlp->nlp_DID, ndlp->nlp_state, | 787 | ndlp->nlp_DID, ndlp->nlp_state, |
741 | ndlp->nlp_flag, ndlp->nlp_rpi); | 788 | ndlp->nlp_flag, ndlp->nlp_rpi); |
742 | 789 | ||
743 | if ((phba->cfg_fcp_class == 2) && | 790 | if (phba->cfg_fcp_class == 2 && (sp->cls2.classValid)) |
744 | (sp->cls2.classValid)) { | ||
745 | ndlp->nlp_fcp_info |= CLASS2; | 791 | ndlp->nlp_fcp_info |= CLASS2; |
746 | } else { | 792 | else |
747 | ndlp->nlp_fcp_info |= CLASS3; | 793 | ndlp->nlp_fcp_info |= CLASS3; |
748 | } | 794 | |
749 | ndlp->nlp_class_sup = 0; | 795 | ndlp->nlp_class_sup = 0; |
750 | if (sp->cls1.classValid) | 796 | if (sp->cls1.classValid) |
751 | ndlp->nlp_class_sup |= FC_COS_CLASS1; | 797 | ndlp->nlp_class_sup |= FC_COS_CLASS1; |
@@ -756,16 +802,23 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
756 | if (sp->cls4.classValid) | 802 | if (sp->cls4.classValid) |
757 | ndlp->nlp_class_sup |= FC_COS_CLASS4; | 803 | ndlp->nlp_class_sup |= FC_COS_CLASS4; |
758 | ndlp->nlp_maxframe = | 804 | ndlp->nlp_maxframe = |
759 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | | 805 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
760 | sp->cmn.bbRcvSizeLsb; | ||
761 | 806 | ||
762 | if (!(mbox = mempool_alloc(phba->mbox_mem_pool, | 807 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
763 | GFP_KERNEL))) | 808 | if (!mbox) { |
809 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
810 | "%d (%d):0133 PLOGI: no memory for reg_login " | ||
811 | "Data: x%x x%x x%x x%x\n", | ||
812 | phba->brd_no, vport->vpi, | ||
813 | ndlp->nlp_DID, ndlp->nlp_state, | ||
814 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
764 | goto out; | 815 | goto out; |
816 | } | ||
765 | 817 | ||
766 | lpfc_unreg_rpi(phba, ndlp); | 818 | lpfc_unreg_rpi(vport, ndlp); |
767 | if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp, | 819 | |
768 | mbox, 0) == 0) { | 820 | if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID, |
821 | (uint8_t *) sp, mbox, 0) == 0) { | ||
769 | switch (ndlp->nlp_DID) { | 822 | switch (ndlp->nlp_DID) { |
770 | case NameServer_DID: | 823 | case NameServer_DID: |
771 | mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; | 824 | mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login; |
@@ -777,68 +830,104 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
777 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 830 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
778 | } | 831 | } |
779 | mbox->context2 = lpfc_nlp_get(ndlp); | 832 | mbox->context2 = lpfc_nlp_get(ndlp); |
833 | mbox->vport = vport; | ||
780 | if (lpfc_sli_issue_mbox(phba, mbox, | 834 | if (lpfc_sli_issue_mbox(phba, mbox, |
781 | (MBX_NOWAIT | MBX_STOP_IOCB)) | 835 | (MBX_NOWAIT | MBX_STOP_IOCB)) |
782 | != MBX_NOT_FINISHED) { | 836 | != MBX_NOT_FINISHED) { |
783 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); | 837 | lpfc_nlp_set_state(vport, ndlp, |
838 | NLP_STE_REG_LOGIN_ISSUE); | ||
784 | return ndlp->nlp_state; | 839 | return ndlp->nlp_state; |
785 | } | 840 | } |
786 | lpfc_nlp_put(ndlp); | 841 | lpfc_nlp_put(ndlp); |
787 | mp = (struct lpfc_dmabuf *)mbox->context1; | 842 | mp = (struct lpfc_dmabuf *) mbox->context1; |
788 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 843 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
789 | kfree(mp); | 844 | kfree(mp); |
790 | mempool_free(mbox, phba->mbox_mem_pool); | 845 | mempool_free(mbox, phba->mbox_mem_pool); |
846 | |||
847 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
848 | "%d (%d):0134 PLOGI: cannot issue reg_login " | ||
849 | "Data: x%x x%x x%x x%x\n", | ||
850 | phba->brd_no, vport->vpi, | ||
851 | ndlp->nlp_DID, ndlp->nlp_state, | ||
852 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
791 | } else { | 853 | } else { |
792 | mempool_free(mbox, phba->mbox_mem_pool); | 854 | mempool_free(mbox, phba->mbox_mem_pool); |
855 | |||
856 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
857 | "%d (%d):0135 PLOGI: cannot format reg_login " | ||
858 | "Data: x%x x%x x%x x%x\n", | ||
859 | phba->brd_no, vport->vpi, | ||
860 | ndlp->nlp_DID, ndlp->nlp_state, | ||
861 | ndlp->nlp_flag, ndlp->nlp_rpi); | ||
793 | } | 862 | } |
794 | 863 | ||
795 | 864 | ||
796 | out: | 865 | out: |
866 | if (ndlp->nlp_DID == NameServer_DID) { | ||
867 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
868 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
869 | "%d (%d):0261 Cannot Register NameServer login\n", | ||
870 | phba->brd_no, vport->vpi); | ||
871 | } | ||
872 | |||
797 | /* Free this node since the driver cannot login or has the wrong | 873 | /* Free this node since the driver cannot login or has the wrong |
798 | sparm */ | 874 | sparm */ |
799 | lpfc_drop_node(phba, ndlp); | 875 | lpfc_drop_node(vport, ndlp); |
800 | return NLP_STE_FREED_NODE; | 876 | return NLP_STE_FREED_NODE; |
801 | } | 877 | } |
802 | 878 | ||
803 | static uint32_t | 879 | static uint32_t |
804 | lpfc_device_rm_plogi_issue(struct lpfc_hba * phba, | 880 | lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
805 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 881 | void *arg, uint32_t evt) |
806 | { | 882 | { |
807 | if(ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 883 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
884 | |||
885 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
886 | spin_lock_irq(shost->host_lock); | ||
808 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; | 887 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; |
888 | spin_unlock_irq(shost->host_lock); | ||
809 | return ndlp->nlp_state; | 889 | return ndlp->nlp_state; |
810 | } | 890 | } else { |
811 | else { | ||
812 | /* software abort outstanding PLOGI */ | 891 | /* software abort outstanding PLOGI */ |
813 | lpfc_els_abort(phba, ndlp); | 892 | lpfc_els_abort(vport->phba, ndlp); |
814 | 893 | ||
815 | lpfc_drop_node(phba, ndlp); | 894 | lpfc_drop_node(vport, ndlp); |
816 | return NLP_STE_FREED_NODE; | 895 | return NLP_STE_FREED_NODE; |
817 | } | 896 | } |
818 | } | 897 | } |
819 | 898 | ||
820 | static uint32_t | 899 | static uint32_t |
821 | lpfc_device_recov_plogi_issue(struct lpfc_hba * phba, | 900 | lpfc_device_recov_plogi_issue(struct lpfc_vport *vport, |
822 | struct lpfc_nodelist * ndlp, void *arg, | 901 | struct lpfc_nodelist *ndlp, |
823 | uint32_t evt) | 902 | void *arg, |
903 | uint32_t evt) | ||
824 | { | 904 | { |
905 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
906 | struct lpfc_hba *phba = vport->phba; | ||
907 | |||
908 | /* Don't do anything that will mess up processing of the | ||
909 | * previous RSCN. | ||
910 | */ | ||
911 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
912 | return ndlp->nlp_state; | ||
913 | |||
825 | /* software abort outstanding PLOGI */ | 914 | /* software abort outstanding PLOGI */ |
826 | lpfc_els_abort(phba, ndlp); | 915 | lpfc_els_abort(phba, ndlp); |
827 | 916 | ||
828 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; | 917 | ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; |
829 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 918 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
830 | spin_lock_irq(phba->host->host_lock); | 919 | spin_lock_irq(shost->host_lock); |
831 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 920 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
832 | spin_unlock_irq(phba->host->host_lock); | 921 | spin_unlock_irq(shost->host_lock); |
833 | 922 | ||
834 | return ndlp->nlp_state; | 923 | return ndlp->nlp_state; |
835 | } | 924 | } |
836 | 925 | ||
837 | static uint32_t | 926 | static uint32_t |
838 | lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, | 927 | lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
839 | struct lpfc_nodelist * ndlp, void *arg, | 928 | void *arg, uint32_t evt) |
840 | uint32_t evt) | ||
841 | { | 929 | { |
930 | struct lpfc_hba *phba = vport->phba; | ||
842 | struct lpfc_iocbq *cmdiocb; | 931 | struct lpfc_iocbq *cmdiocb; |
843 | 932 | ||
844 | /* software abort outstanding ADISC */ | 933 | /* software abort outstanding ADISC */ |
@@ -846,34 +935,31 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba, | |||
846 | 935 | ||
847 | cmdiocb = (struct lpfc_iocbq *) arg; | 936 | cmdiocb = (struct lpfc_iocbq *) arg; |
848 | 937 | ||
849 | if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { | 938 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) |
850 | return ndlp->nlp_state; | 939 | return ndlp->nlp_state; |
851 | } | 940 | |
852 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 941 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
853 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 942 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
854 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 943 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
855 | 944 | ||
856 | return ndlp->nlp_state; | 945 | return ndlp->nlp_state; |
857 | } | 946 | } |
858 | 947 | ||
859 | static uint32_t | 948 | static uint32_t |
860 | lpfc_rcv_prli_adisc_issue(struct lpfc_hba * phba, | 949 | lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
861 | struct lpfc_nodelist * ndlp, void *arg, | 950 | void *arg, uint32_t evt) |
862 | uint32_t evt) | ||
863 | { | 951 | { |
864 | struct lpfc_iocbq *cmdiocb; | 952 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
865 | |||
866 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
867 | 953 | ||
868 | lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); | 954 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); |
869 | return ndlp->nlp_state; | 955 | return ndlp->nlp_state; |
870 | } | 956 | } |
871 | 957 | ||
872 | static uint32_t | 958 | static uint32_t |
873 | lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba, | 959 | lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
874 | struct lpfc_nodelist * ndlp, void *arg, | 960 | void *arg, uint32_t evt) |
875 | uint32_t evt) | ||
876 | { | 961 | { |
962 | struct lpfc_hba *phba = vport->phba; | ||
877 | struct lpfc_iocbq *cmdiocb; | 963 | struct lpfc_iocbq *cmdiocb; |
878 | 964 | ||
879 | cmdiocb = (struct lpfc_iocbq *) arg; | 965 | cmdiocb = (struct lpfc_iocbq *) arg; |
@@ -881,42 +967,43 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba, | |||
881 | /* software abort outstanding ADISC */ | 967 | /* software abort outstanding ADISC */ |
882 | lpfc_els_abort(phba, ndlp); | 968 | lpfc_els_abort(phba, ndlp); |
883 | 969 | ||
884 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 970 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
885 | return ndlp->nlp_state; | 971 | return ndlp->nlp_state; |
886 | } | 972 | } |
887 | 973 | ||
888 | static uint32_t | 974 | static uint32_t |
889 | lpfc_rcv_padisc_adisc_issue(struct lpfc_hba * phba, | 975 | lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport, |
890 | struct lpfc_nodelist * ndlp, void *arg, | 976 | struct lpfc_nodelist *ndlp, |
891 | uint32_t evt) | 977 | void *arg, uint32_t evt) |
892 | { | 978 | { |
893 | struct lpfc_iocbq *cmdiocb; | 979 | struct lpfc_iocbq *cmdiocb; |
894 | 980 | ||
895 | cmdiocb = (struct lpfc_iocbq *) arg; | 981 | cmdiocb = (struct lpfc_iocbq *) arg; |
896 | 982 | ||
897 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | 983 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
898 | return ndlp->nlp_state; | 984 | return ndlp->nlp_state; |
899 | } | 985 | } |
900 | 986 | ||
901 | static uint32_t | 987 | static uint32_t |
902 | lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba, | 988 | lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
903 | struct lpfc_nodelist * ndlp, void *arg, | 989 | void *arg, uint32_t evt) |
904 | uint32_t evt) | ||
905 | { | 990 | { |
906 | struct lpfc_iocbq *cmdiocb; | 991 | struct lpfc_iocbq *cmdiocb; |
907 | 992 | ||
908 | cmdiocb = (struct lpfc_iocbq *) arg; | 993 | cmdiocb = (struct lpfc_iocbq *) arg; |
909 | 994 | ||
910 | /* Treat like rcv logo */ | 995 | /* Treat like rcv logo */ |
911 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO); | 996 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); |
912 | return ndlp->nlp_state; | 997 | return ndlp->nlp_state; |
913 | } | 998 | } |
914 | 999 | ||
915 | static uint32_t | 1000 | static uint32_t |
916 | lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, | 1001 | lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, |
917 | struct lpfc_nodelist * ndlp, void *arg, | 1002 | struct lpfc_nodelist *ndlp, |
918 | uint32_t evt) | 1003 | void *arg, uint32_t evt) |
919 | { | 1004 | { |
1005 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1006 | struct lpfc_hba *phba = vport->phba; | ||
920 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1007 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
921 | IOCB_t *irsp; | 1008 | IOCB_t *irsp; |
922 | ADISC *ap; | 1009 | ADISC *ap; |
@@ -928,101 +1015,112 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba, | |||
928 | irsp = &rspiocb->iocb; | 1015 | irsp = &rspiocb->iocb; |
929 | 1016 | ||
930 | if ((irsp->ulpStatus) || | 1017 | if ((irsp->ulpStatus) || |
931 | (!lpfc_check_adisc(phba, ndlp, &ap->nodeName, &ap->portName))) { | 1018 | (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { |
932 | /* 1 sec timeout */ | 1019 | /* 1 sec timeout */ |
933 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 1020 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
934 | spin_lock_irq(phba->host->host_lock); | 1021 | spin_lock_irq(shost->host_lock); |
935 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1022 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
936 | spin_unlock_irq(phba->host->host_lock); | 1023 | spin_unlock_irq(shost->host_lock); |
937 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 1024 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
938 | 1025 | ||
939 | memset(&ndlp->nlp_nodename, 0, sizeof (struct lpfc_name)); | 1026 | memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name)); |
940 | memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name)); | 1027 | memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name)); |
941 | 1028 | ||
942 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1029 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
943 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1030 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
944 | lpfc_unreg_rpi(phba, ndlp); | 1031 | lpfc_unreg_rpi(vport, ndlp); |
945 | return ndlp->nlp_state; | 1032 | return ndlp->nlp_state; |
946 | } | 1033 | } |
947 | 1034 | ||
948 | if (ndlp->nlp_type & NLP_FCP_TARGET) { | 1035 | if (ndlp->nlp_type & NLP_FCP_TARGET) { |
949 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1036 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
950 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE); | 1037 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); |
951 | } else { | 1038 | } else { |
952 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1039 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
953 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); | 1040 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
954 | } | 1041 | } |
955 | return ndlp->nlp_state; | 1042 | return ndlp->nlp_state; |
956 | } | 1043 | } |
957 | 1044 | ||
958 | static uint32_t | 1045 | static uint32_t |
959 | lpfc_device_rm_adisc_issue(struct lpfc_hba * phba, | 1046 | lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
960 | struct lpfc_nodelist * ndlp, void *arg, | 1047 | void *arg, uint32_t evt) |
961 | uint32_t evt) | ||
962 | { | 1048 | { |
963 | if(ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1049 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1050 | |||
1051 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
1052 | spin_lock_irq(shost->host_lock); | ||
964 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; | 1053 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; |
1054 | spin_unlock_irq(shost->host_lock); | ||
965 | return ndlp->nlp_state; | 1055 | return ndlp->nlp_state; |
966 | } | 1056 | } else { |
967 | else { | ||
968 | /* software abort outstanding ADISC */ | 1057 | /* software abort outstanding ADISC */ |
969 | lpfc_els_abort(phba, ndlp); | 1058 | lpfc_els_abort(vport->phba, ndlp); |
970 | 1059 | ||
971 | lpfc_drop_node(phba, ndlp); | 1060 | lpfc_drop_node(vport, ndlp); |
972 | return NLP_STE_FREED_NODE; | 1061 | return NLP_STE_FREED_NODE; |
973 | } | 1062 | } |
974 | } | 1063 | } |
975 | 1064 | ||
976 | static uint32_t | 1065 | static uint32_t |
977 | lpfc_device_recov_adisc_issue(struct lpfc_hba * phba, | 1066 | lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, |
978 | struct lpfc_nodelist * ndlp, void *arg, | 1067 | struct lpfc_nodelist *ndlp, |
979 | uint32_t evt) | 1068 | void *arg, |
1069 | uint32_t evt) | ||
980 | { | 1070 | { |
1071 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1072 | struct lpfc_hba *phba = vport->phba; | ||
1073 | |||
1074 | /* Don't do anything that will mess up processing of the | ||
1075 | * previous RSCN. | ||
1076 | */ | ||
1077 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1078 | return ndlp->nlp_state; | ||
1079 | |||
981 | /* software abort outstanding ADISC */ | 1080 | /* software abort outstanding ADISC */ |
982 | lpfc_els_abort(phba, ndlp); | 1081 | lpfc_els_abort(phba, ndlp); |
983 | 1082 | ||
984 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1083 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
985 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1084 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
986 | spin_lock_irq(phba->host->host_lock); | 1085 | spin_lock_irq(shost->host_lock); |
987 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1086 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
988 | ndlp->nlp_flag |= NLP_NPR_ADISC; | 1087 | spin_unlock_irq(shost->host_lock); |
989 | spin_unlock_irq(phba->host->host_lock); | 1088 | lpfc_disc_set_adisc(vport, ndlp); |
990 | |||
991 | return ndlp->nlp_state; | 1089 | return ndlp->nlp_state; |
992 | } | 1090 | } |
993 | 1091 | ||
994 | static uint32_t | 1092 | static uint32_t |
995 | lpfc_rcv_plogi_reglogin_issue(struct lpfc_hba * phba, | 1093 | lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport, |
996 | struct lpfc_nodelist * ndlp, void *arg, | 1094 | struct lpfc_nodelist *ndlp, |
1095 | void *arg, | ||
997 | uint32_t evt) | 1096 | uint32_t evt) |
998 | { | 1097 | { |
999 | struct lpfc_iocbq *cmdiocb; | 1098 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1000 | 1099 | ||
1001 | cmdiocb = (struct lpfc_iocbq *) arg; | 1100 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
1002 | |||
1003 | lpfc_rcv_plogi(phba, ndlp, cmdiocb); | ||
1004 | return ndlp->nlp_state; | 1101 | return ndlp->nlp_state; |
1005 | } | 1102 | } |
1006 | 1103 | ||
1007 | static uint32_t | 1104 | static uint32_t |
1008 | lpfc_rcv_prli_reglogin_issue(struct lpfc_hba * phba, | 1105 | lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport, |
1009 | struct lpfc_nodelist * ndlp, void *arg, | 1106 | struct lpfc_nodelist *ndlp, |
1107 | void *arg, | ||
1010 | uint32_t evt) | 1108 | uint32_t evt) |
1011 | { | 1109 | { |
1012 | struct lpfc_iocbq *cmdiocb; | 1110 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1013 | 1111 | ||
1014 | cmdiocb = (struct lpfc_iocbq *) arg; | 1112 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); |
1015 | |||
1016 | lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); | ||
1017 | return ndlp->nlp_state; | 1113 | return ndlp->nlp_state; |
1018 | } | 1114 | } |
1019 | 1115 | ||
1020 | static uint32_t | 1116 | static uint32_t |
1021 | lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, | 1117 | lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, |
1022 | struct lpfc_nodelist * ndlp, void *arg, | 1118 | struct lpfc_nodelist *ndlp, |
1119 | void *arg, | ||
1023 | uint32_t evt) | 1120 | uint32_t evt) |
1024 | { | 1121 | { |
1025 | struct lpfc_iocbq *cmdiocb; | 1122 | struct lpfc_hba *phba = vport->phba; |
1123 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | ||
1026 | LPFC_MBOXQ_t *mb; | 1124 | LPFC_MBOXQ_t *mb; |
1027 | LPFC_MBOXQ_t *nextmb; | 1125 | LPFC_MBOXQ_t *nextmb; |
1028 | struct lpfc_dmabuf *mp; | 1126 | struct lpfc_dmabuf *mp; |
@@ -1033,12 +1131,13 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, | |||
1033 | if ((mb = phba->sli.mbox_active)) { | 1131 | if ((mb = phba->sli.mbox_active)) { |
1034 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && | 1132 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && |
1035 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 1133 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
1134 | lpfc_nlp_put(ndlp); | ||
1036 | mb->context2 = NULL; | 1135 | mb->context2 = NULL; |
1037 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 1136 | mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
1038 | } | 1137 | } |
1039 | } | 1138 | } |
1040 | 1139 | ||
1041 | spin_lock_irq(phba->host->host_lock); | 1140 | spin_lock_irq(&phba->hbalock); |
1042 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { | 1141 | list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { |
1043 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && | 1142 | if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && |
1044 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { | 1143 | (ndlp == (struct lpfc_nodelist *) mb->context2)) { |
@@ -1047,61 +1146,61 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba, | |||
1047 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 1146 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
1048 | kfree(mp); | 1147 | kfree(mp); |
1049 | } | 1148 | } |
1149 | lpfc_nlp_put(ndlp); | ||
1050 | list_del(&mb->list); | 1150 | list_del(&mb->list); |
1051 | mempool_free(mb, phba->mbox_mem_pool); | 1151 | mempool_free(mb, phba->mbox_mem_pool); |
1052 | } | 1152 | } |
1053 | } | 1153 | } |
1054 | spin_unlock_irq(phba->host->host_lock); | 1154 | spin_unlock_irq(&phba->hbalock); |
1055 | 1155 | ||
1056 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 1156 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
1057 | return ndlp->nlp_state; | 1157 | return ndlp->nlp_state; |
1058 | } | 1158 | } |
1059 | 1159 | ||
1060 | static uint32_t | 1160 | static uint32_t |
1061 | lpfc_rcv_padisc_reglogin_issue(struct lpfc_hba * phba, | 1161 | lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport, |
1062 | struct lpfc_nodelist * ndlp, void *arg, | 1162 | struct lpfc_nodelist *ndlp, |
1163 | void *arg, | ||
1063 | uint32_t evt) | 1164 | uint32_t evt) |
1064 | { | 1165 | { |
1065 | struct lpfc_iocbq *cmdiocb; | 1166 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1066 | 1167 | ||
1067 | cmdiocb = (struct lpfc_iocbq *) arg; | 1168 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1068 | |||
1069 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | ||
1070 | return ndlp->nlp_state; | 1169 | return ndlp->nlp_state; |
1071 | } | 1170 | } |
1072 | 1171 | ||
1073 | static uint32_t | 1172 | static uint32_t |
1074 | lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba, | 1173 | lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport, |
1075 | struct lpfc_nodelist * ndlp, void *arg, | 1174 | struct lpfc_nodelist *ndlp, |
1175 | void *arg, | ||
1076 | uint32_t evt) | 1176 | uint32_t evt) |
1077 | { | 1177 | { |
1078 | struct lpfc_iocbq *cmdiocb; | 1178 | struct lpfc_iocbq *cmdiocb; |
1079 | 1179 | ||
1080 | cmdiocb = (struct lpfc_iocbq *) arg; | 1180 | cmdiocb = (struct lpfc_iocbq *) arg; |
1081 | lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 1181 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); |
1082 | return ndlp->nlp_state; | 1182 | return ndlp->nlp_state; |
1083 | } | 1183 | } |
1084 | 1184 | ||
1085 | static uint32_t | 1185 | static uint32_t |
1086 | lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, | 1186 | lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, |
1087 | struct lpfc_nodelist * ndlp, | 1187 | struct lpfc_nodelist *ndlp, |
1088 | void *arg, uint32_t evt) | 1188 | void *arg, |
1189 | uint32_t evt) | ||
1089 | { | 1190 | { |
1090 | LPFC_MBOXQ_t *pmb; | 1191 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1091 | MAILBOX_t *mb; | 1192 | struct lpfc_hba *phba = vport->phba; |
1092 | uint32_t did; | 1193 | LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; |
1194 | MAILBOX_t *mb = &pmb->mb; | ||
1195 | uint32_t did = mb->un.varWords[1]; | ||
1093 | 1196 | ||
1094 | pmb = (LPFC_MBOXQ_t *) arg; | ||
1095 | mb = &pmb->mb; | ||
1096 | did = mb->un.varWords[1]; | ||
1097 | if (mb->mbxStatus) { | 1197 | if (mb->mbxStatus) { |
1098 | /* RegLogin failed */ | 1198 | /* RegLogin failed */ |
1099 | lpfc_printf_log(phba, | 1199 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
1100 | KERN_ERR, | 1200 | "%d (%d):0246 RegLogin failed Data: x%x x%x " |
1101 | LOG_DISCOVERY, | 1201 | "x%x\n", |
1102 | "%d:0246 RegLogin failed Data: x%x x%x x%x\n", | 1202 | phba->brd_no, vport->vpi, |
1103 | phba->brd_no, | 1203 | did, mb->mbxStatus, vport->port_state); |
1104 | did, mb->mbxStatus, phba->hba_state); | ||
1105 | 1204 | ||
1106 | /* | 1205 | /* |
1107 | * If RegLogin failed due to lack of HBA resources do not | 1206 | * If RegLogin failed due to lack of HBA resources do not |
@@ -1109,20 +1208,20 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, | |||
1109 | */ | 1208 | */ |
1110 | if (mb->mbxStatus == MBXERR_RPI_FULL) { | 1209 | if (mb->mbxStatus == MBXERR_RPI_FULL) { |
1111 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; | 1210 | ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; |
1112 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 1211 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
1113 | return ndlp->nlp_state; | 1212 | return ndlp->nlp_state; |
1114 | } | 1213 | } |
1115 | 1214 | ||
1116 | /* Put ndlp in npr list set plogi timer for 1 sec */ | 1215 | /* Put ndlp in npr state set plogi timer for 1 sec */ |
1117 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 1216 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
1118 | spin_lock_irq(phba->host->host_lock); | 1217 | spin_lock_irq(shost->host_lock); |
1119 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1218 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
1120 | spin_unlock_irq(phba->host->host_lock); | 1219 | spin_unlock_irq(shost->host_lock); |
1121 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 1220 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
1122 | 1221 | ||
1123 | lpfc_issue_els_logo(phba, ndlp, 0); | 1222 | lpfc_issue_els_logo(vport, ndlp, 0); |
1124 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1223 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1125 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1224 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1126 | return ndlp->nlp_state; | 1225 | return ndlp->nlp_state; |
1127 | } | 1226 | } |
1128 | 1227 | ||
@@ -1131,91 +1230,99 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba, | |||
1131 | /* Only if we are not a fabric nport do we issue PRLI */ | 1230 | /* Only if we are not a fabric nport do we issue PRLI */ |
1132 | if (!(ndlp->nlp_type & NLP_FABRIC)) { | 1231 | if (!(ndlp->nlp_type & NLP_FABRIC)) { |
1133 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1232 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1134 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); | 1233 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
1135 | lpfc_issue_els_prli(phba, ndlp, 0); | 1234 | lpfc_issue_els_prli(vport, ndlp, 0); |
1136 | } else { | 1235 | } else { |
1137 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1236 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1138 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); | 1237 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
1139 | } | 1238 | } |
1140 | return ndlp->nlp_state; | 1239 | return ndlp->nlp_state; |
1141 | } | 1240 | } |
1142 | 1241 | ||
1143 | static uint32_t | 1242 | static uint32_t |
1144 | lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba, | 1243 | lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport, |
1145 | struct lpfc_nodelist * ndlp, void *arg, | 1244 | struct lpfc_nodelist *ndlp, |
1245 | void *arg, | ||
1146 | uint32_t evt) | 1246 | uint32_t evt) |
1147 | { | 1247 | { |
1148 | if(ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1248 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1249 | |||
1250 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
1251 | spin_lock_irq(shost->host_lock); | ||
1149 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; | 1252 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; |
1253 | spin_unlock_irq(shost->host_lock); | ||
1150 | return ndlp->nlp_state; | 1254 | return ndlp->nlp_state; |
1151 | } | 1255 | } else { |
1152 | else { | 1256 | lpfc_drop_node(vport, ndlp); |
1153 | lpfc_drop_node(phba, ndlp); | ||
1154 | return NLP_STE_FREED_NODE; | 1257 | return NLP_STE_FREED_NODE; |
1155 | } | 1258 | } |
1156 | } | 1259 | } |
1157 | 1260 | ||
1158 | static uint32_t | 1261 | static uint32_t |
1159 | lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba, | 1262 | lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, |
1160 | struct lpfc_nodelist * ndlp, void *arg, | 1263 | struct lpfc_nodelist *ndlp, |
1161 | uint32_t evt) | 1264 | void *arg, |
1265 | uint32_t evt) | ||
1162 | { | 1266 | { |
1267 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1268 | |||
1269 | /* Don't do anything that will mess up processing of the | ||
1270 | * previous RSCN. | ||
1271 | */ | ||
1272 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1273 | return ndlp->nlp_state; | ||
1274 | |||
1163 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; | 1275 | ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; |
1164 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1276 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1165 | spin_lock_irq(phba->host->host_lock); | 1277 | spin_lock_irq(shost->host_lock); |
1166 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1278 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1167 | spin_unlock_irq(phba->host->host_lock); | 1279 | spin_unlock_irq(shost->host_lock); |
1280 | lpfc_disc_set_adisc(vport, ndlp); | ||
1168 | return ndlp->nlp_state; | 1281 | return ndlp->nlp_state; |
1169 | } | 1282 | } |
1170 | 1283 | ||
1171 | static uint32_t | 1284 | static uint32_t |
1172 | lpfc_rcv_plogi_prli_issue(struct lpfc_hba * phba, | 1285 | lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1173 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1286 | void *arg, uint32_t evt) |
1174 | { | 1287 | { |
1175 | struct lpfc_iocbq *cmdiocb; | 1288 | struct lpfc_iocbq *cmdiocb; |
1176 | 1289 | ||
1177 | cmdiocb = (struct lpfc_iocbq *) arg; | 1290 | cmdiocb = (struct lpfc_iocbq *) arg; |
1178 | 1291 | ||
1179 | lpfc_rcv_plogi(phba, ndlp, cmdiocb); | 1292 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
1180 | return ndlp->nlp_state; | 1293 | return ndlp->nlp_state; |
1181 | } | 1294 | } |
1182 | 1295 | ||
1183 | static uint32_t | 1296 | static uint32_t |
1184 | lpfc_rcv_prli_prli_issue(struct lpfc_hba * phba, | 1297 | lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1185 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1298 | void *arg, uint32_t evt) |
1186 | { | 1299 | { |
1187 | struct lpfc_iocbq *cmdiocb; | 1300 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1188 | |||
1189 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1190 | 1301 | ||
1191 | lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); | 1302 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); |
1192 | return ndlp->nlp_state; | 1303 | return ndlp->nlp_state; |
1193 | } | 1304 | } |
1194 | 1305 | ||
1195 | static uint32_t | 1306 | static uint32_t |
1196 | lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba, | 1307 | lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1197 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1308 | void *arg, uint32_t evt) |
1198 | { | 1309 | { |
1199 | struct lpfc_iocbq *cmdiocb; | 1310 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1200 | |||
1201 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1202 | 1311 | ||
1203 | /* Software abort outstanding PRLI before sending acc */ | 1312 | /* Software abort outstanding PRLI before sending acc */ |
1204 | lpfc_els_abort(phba, ndlp); | 1313 | lpfc_els_abort(vport->phba, ndlp); |
1205 | 1314 | ||
1206 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | 1315 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
1207 | return ndlp->nlp_state; | 1316 | return ndlp->nlp_state; |
1208 | } | 1317 | } |
1209 | 1318 | ||
1210 | static uint32_t | 1319 | static uint32_t |
1211 | lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba, | 1320 | lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1212 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1321 | void *arg, uint32_t evt) |
1213 | { | 1322 | { |
1214 | struct lpfc_iocbq *cmdiocb; | 1323 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1215 | |||
1216 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1217 | 1324 | ||
1218 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | 1325 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1219 | return ndlp->nlp_state; | 1326 | return ndlp->nlp_state; |
1220 | } | 1327 | } |
1221 | 1328 | ||
@@ -1225,21 +1332,22 @@ lpfc_rcv_padisc_prli_issue(struct lpfc_hba * phba, | |||
1225 | * NEXT STATE = PRLI_ISSUE | 1332 | * NEXT STATE = PRLI_ISSUE |
1226 | */ | 1333 | */ |
1227 | static uint32_t | 1334 | static uint32_t |
1228 | lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba, | 1335 | lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1229 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1336 | void *arg, uint32_t evt) |
1230 | { | 1337 | { |
1231 | struct lpfc_iocbq *cmdiocb; | 1338 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1232 | 1339 | ||
1233 | cmdiocb = (struct lpfc_iocbq *) arg; | 1340 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); |
1234 | lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | ||
1235 | return ndlp->nlp_state; | 1341 | return ndlp->nlp_state; |
1236 | } | 1342 | } |
1237 | 1343 | ||
1238 | static uint32_t | 1344 | static uint32_t |
1239 | lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, | 1345 | lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1240 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1346 | void *arg, uint32_t evt) |
1241 | { | 1347 | { |
1348 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1242 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1349 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
1350 | struct lpfc_hba *phba = vport->phba; | ||
1243 | IOCB_t *irsp; | 1351 | IOCB_t *irsp; |
1244 | PRLI *npr; | 1352 | PRLI *npr; |
1245 | 1353 | ||
@@ -1249,8 +1357,12 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, | |||
1249 | 1357 | ||
1250 | irsp = &rspiocb->iocb; | 1358 | irsp = &rspiocb->iocb; |
1251 | if (irsp->ulpStatus) { | 1359 | if (irsp->ulpStatus) { |
1360 | if ((vport->port_type == LPFC_NPIV_PORT) && | ||
1361 | phba->cfg_vport_restrict_login) { | ||
1362 | goto out; | ||
1363 | } | ||
1252 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1364 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1253 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE); | 1365 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
1254 | return ndlp->nlp_state; | 1366 | return ndlp->nlp_state; |
1255 | } | 1367 | } |
1256 | 1368 | ||
@@ -1266,319 +1378,329 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba, | |||
1266 | if (npr->Retry) | 1378 | if (npr->Retry) |
1267 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; | 1379 | ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; |
1268 | } | 1380 | } |
1381 | if (!(ndlp->nlp_type & NLP_FCP_TARGET) && | ||
1382 | (vport->port_type == LPFC_NPIV_PORT) && | ||
1383 | phba->cfg_vport_restrict_login) { | ||
1384 | out: | ||
1385 | spin_lock_irq(shost->host_lock); | ||
1386 | ndlp->nlp_flag |= NLP_TARGET_REMOVE; | ||
1387 | spin_unlock_irq(shost->host_lock); | ||
1388 | lpfc_issue_els_logo(vport, ndlp, 0); | ||
1389 | |||
1390 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | ||
1391 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | ||
1392 | return ndlp->nlp_state; | ||
1393 | } | ||
1269 | 1394 | ||
1270 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1395 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1271 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE); | 1396 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
1397 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE); | ||
1398 | else | ||
1399 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | ||
1272 | return ndlp->nlp_state; | 1400 | return ndlp->nlp_state; |
1273 | } | 1401 | } |
1274 | 1402 | ||
1275 | /*! lpfc_device_rm_prli_issue | 1403 | /*! lpfc_device_rm_prli_issue |
1276 | * | 1404 | * |
1277 | * \pre | 1405 | * \pre |
1278 | * \post | 1406 | * \post |
1279 | * \param phba | 1407 | * \param phba |
1280 | * \param ndlp | 1408 | * \param ndlp |
1281 | * \param arg | 1409 | * \param arg |
1282 | * \param evt | 1410 | * \param evt |
1283 | * \return uint32_t | 1411 | * \return uint32_t |
1284 | * | 1412 | * |
1285 | * \b Description: | 1413 | * \b Description: |
1286 | * This routine is envoked when we a request to remove a nport we are in the | 1414 | * This routine is envoked when we a request to remove a nport we are in the |
1287 | * process of PRLIing. We should software abort outstanding prli, unreg | 1415 | * process of PRLIing. We should software abort outstanding prli, unreg |
1288 | * login, send a logout. We will change node state to UNUSED_NODE, put it | 1416 | * login, send a logout. We will change node state to UNUSED_NODE, put it |
1289 | * on plogi list so it can be freed when LOGO completes. | 1417 | * on plogi list so it can be freed when LOGO completes. |
1290 | * | 1418 | * |
1291 | */ | 1419 | */ |
1420 | |||
1292 | static uint32_t | 1421 | static uint32_t |
1293 | lpfc_device_rm_prli_issue(struct lpfc_hba * phba, | 1422 | lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1294 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1423 | void *arg, uint32_t evt) |
1295 | { | 1424 | { |
1296 | if(ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1425 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1426 | |||
1427 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
1428 | spin_lock_irq(shost->host_lock); | ||
1297 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; | 1429 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; |
1430 | spin_unlock_irq(shost->host_lock); | ||
1298 | return ndlp->nlp_state; | 1431 | return ndlp->nlp_state; |
1299 | } | 1432 | } else { |
1300 | else { | ||
1301 | /* software abort outstanding PLOGI */ | 1433 | /* software abort outstanding PLOGI */ |
1302 | lpfc_els_abort(phba, ndlp); | 1434 | lpfc_els_abort(vport->phba, ndlp); |
1303 | 1435 | ||
1304 | lpfc_drop_node(phba, ndlp); | 1436 | lpfc_drop_node(vport, ndlp); |
1305 | return NLP_STE_FREED_NODE; | 1437 | return NLP_STE_FREED_NODE; |
1306 | } | 1438 | } |
1307 | } | 1439 | } |
1308 | 1440 | ||
1309 | 1441 | ||
1310 | /*! lpfc_device_recov_prli_issue | 1442 | /*! lpfc_device_recov_prli_issue |
1311 | * | 1443 | * |
1312 | * \pre | 1444 | * \pre |
1313 | * \post | 1445 | * \post |
1314 | * \param phba | 1446 | * \param phba |
1315 | * \param ndlp | 1447 | * \param ndlp |
1316 | * \param arg | 1448 | * \param arg |
1317 | * \param evt | 1449 | * \param evt |
1318 | * \return uint32_t | 1450 | * \return uint32_t |
1319 | * | 1451 | * |
1320 | * \b Description: | 1452 | * \b Description: |
1321 | * The routine is envoked when the state of a device is unknown, like | 1453 | * The routine is envoked when the state of a device is unknown, like |
1322 | * during a link down. We should remove the nodelist entry from the | 1454 | * during a link down. We should remove the nodelist entry from the |
1323 | * unmapped list, issue a UNREG_LOGIN, do a software abort of the | 1455 | * unmapped list, issue a UNREG_LOGIN, do a software abort of the |
1324 | * outstanding PRLI command, then free the node entry. | 1456 | * outstanding PRLI command, then free the node entry. |
1325 | */ | 1457 | */ |
1326 | static uint32_t | 1458 | static uint32_t |
1327 | lpfc_device_recov_prli_issue(struct lpfc_hba * phba, | 1459 | lpfc_device_recov_prli_issue(struct lpfc_vport *vport, |
1328 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1460 | struct lpfc_nodelist *ndlp, |
1461 | void *arg, | ||
1462 | uint32_t evt) | ||
1329 | { | 1463 | { |
1464 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1465 | struct lpfc_hba *phba = vport->phba; | ||
1466 | |||
1467 | /* Don't do anything that will mess up processing of the | ||
1468 | * previous RSCN. | ||
1469 | */ | ||
1470 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1471 | return ndlp->nlp_state; | ||
1472 | |||
1330 | /* software abort outstanding PRLI */ | 1473 | /* software abort outstanding PRLI */ |
1331 | lpfc_els_abort(phba, ndlp); | 1474 | lpfc_els_abort(phba, ndlp); |
1332 | 1475 | ||
1333 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; | 1476 | ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; |
1334 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1477 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1335 | spin_lock_irq(phba->host->host_lock); | 1478 | spin_lock_irq(shost->host_lock); |
1336 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1479 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1337 | spin_unlock_irq(phba->host->host_lock); | 1480 | spin_unlock_irq(shost->host_lock); |
1481 | lpfc_disc_set_adisc(vport, ndlp); | ||
1338 | return ndlp->nlp_state; | 1482 | return ndlp->nlp_state; |
1339 | } | 1483 | } |
1340 | 1484 | ||
1341 | static uint32_t | 1485 | static uint32_t |
1342 | lpfc_rcv_plogi_unmap_node(struct lpfc_hba * phba, | 1486 | lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1343 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1487 | void *arg, uint32_t evt) |
1344 | { | 1488 | { |
1345 | struct lpfc_iocbq *cmdiocb; | 1489 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1346 | |||
1347 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1348 | 1490 | ||
1349 | lpfc_rcv_plogi(phba, ndlp, cmdiocb); | 1491 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
1350 | return ndlp->nlp_state; | 1492 | return ndlp->nlp_state; |
1351 | } | 1493 | } |
1352 | 1494 | ||
1353 | static uint32_t | 1495 | static uint32_t |
1354 | lpfc_rcv_prli_unmap_node(struct lpfc_hba * phba, | 1496 | lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1355 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1497 | void *arg, uint32_t evt) |
1356 | { | 1498 | { |
1357 | struct lpfc_iocbq *cmdiocb; | 1499 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1358 | 1500 | ||
1359 | cmdiocb = (struct lpfc_iocbq *) arg; | 1501 | lpfc_rcv_prli(vport, ndlp, cmdiocb); |
1360 | 1502 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); | |
1361 | lpfc_rcv_prli(phba, ndlp, cmdiocb); | ||
1362 | lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); | ||
1363 | return ndlp->nlp_state; | 1503 | return ndlp->nlp_state; |
1364 | } | 1504 | } |
1365 | 1505 | ||
1366 | static uint32_t | 1506 | static uint32_t |
1367 | lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba, | 1507 | lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1368 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1508 | void *arg, uint32_t evt) |
1369 | { | 1509 | { |
1370 | struct lpfc_iocbq *cmdiocb; | 1510 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1371 | 1511 | ||
1372 | cmdiocb = (struct lpfc_iocbq *) arg; | 1512 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
1373 | |||
1374 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | ||
1375 | return ndlp->nlp_state; | 1513 | return ndlp->nlp_state; |
1376 | } | 1514 | } |
1377 | 1515 | ||
1378 | static uint32_t | 1516 | static uint32_t |
1379 | lpfc_rcv_padisc_unmap_node(struct lpfc_hba * phba, | 1517 | lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1380 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1518 | void *arg, uint32_t evt) |
1381 | { | 1519 | { |
1382 | struct lpfc_iocbq *cmdiocb; | 1520 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1383 | 1521 | ||
1384 | cmdiocb = (struct lpfc_iocbq *) arg; | 1522 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1385 | |||
1386 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | ||
1387 | return ndlp->nlp_state; | 1523 | return ndlp->nlp_state; |
1388 | } | 1524 | } |
1389 | 1525 | ||
1390 | static uint32_t | 1526 | static uint32_t |
1391 | lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba, | 1527 | lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1392 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1528 | void *arg, uint32_t evt) |
1393 | { | 1529 | { |
1394 | struct lpfc_iocbq *cmdiocb; | 1530 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1395 | |||
1396 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1397 | 1531 | ||
1398 | lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); | 1532 | lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0); |
1399 | return ndlp->nlp_state; | 1533 | return ndlp->nlp_state; |
1400 | } | 1534 | } |
1401 | 1535 | ||
1402 | static uint32_t | 1536 | static uint32_t |
1403 | lpfc_device_recov_unmap_node(struct lpfc_hba * phba, | 1537 | lpfc_device_recov_unmap_node(struct lpfc_vport *vport, |
1404 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1538 | struct lpfc_nodelist *ndlp, |
1539 | void *arg, | ||
1540 | uint32_t evt) | ||
1405 | { | 1541 | { |
1542 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1543 | |||
1406 | ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE; | 1544 | ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE; |
1407 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1545 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1546 | spin_lock_irq(shost->host_lock); | ||
1408 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1547 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1409 | lpfc_disc_set_adisc(phba, ndlp); | 1548 | spin_unlock_irq(shost->host_lock); |
1549 | lpfc_disc_set_adisc(vport, ndlp); | ||
1410 | 1550 | ||
1411 | return ndlp->nlp_state; | 1551 | return ndlp->nlp_state; |
1412 | } | 1552 | } |
1413 | 1553 | ||
1414 | static uint32_t | 1554 | static uint32_t |
1415 | lpfc_rcv_plogi_mapped_node(struct lpfc_hba * phba, | 1555 | lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1416 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1556 | void *arg, uint32_t evt) |
1417 | { | 1557 | { |
1418 | struct lpfc_iocbq *cmdiocb; | 1558 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1419 | |||
1420 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1421 | 1559 | ||
1422 | lpfc_rcv_plogi(phba, ndlp, cmdiocb); | 1560 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); |
1423 | return ndlp->nlp_state; | 1561 | return ndlp->nlp_state; |
1424 | } | 1562 | } |
1425 | 1563 | ||
1426 | static uint32_t | 1564 | static uint32_t |
1427 | lpfc_rcv_prli_mapped_node(struct lpfc_hba * phba, | 1565 | lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1428 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1566 | void *arg, uint32_t evt) |
1429 | { | 1567 | { |
1430 | struct lpfc_iocbq *cmdiocb; | 1568 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1431 | 1569 | ||
1432 | cmdiocb = (struct lpfc_iocbq *) arg; | 1570 | lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp); |
1433 | |||
1434 | lpfc_els_rsp_prli_acc(phba, cmdiocb, ndlp); | ||
1435 | return ndlp->nlp_state; | 1571 | return ndlp->nlp_state; |
1436 | } | 1572 | } |
1437 | 1573 | ||
1438 | static uint32_t | 1574 | static uint32_t |
1439 | lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba, | 1575 | lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1440 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1576 | void *arg, uint32_t evt) |
1441 | { | 1577 | { |
1442 | struct lpfc_iocbq *cmdiocb; | 1578 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1443 | 1579 | ||
1444 | cmdiocb = (struct lpfc_iocbq *) arg; | 1580 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
1445 | |||
1446 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | ||
1447 | return ndlp->nlp_state; | 1581 | return ndlp->nlp_state; |
1448 | } | 1582 | } |
1449 | 1583 | ||
1450 | static uint32_t | 1584 | static uint32_t |
1451 | lpfc_rcv_padisc_mapped_node(struct lpfc_hba * phba, | 1585 | lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport, |
1452 | struct lpfc_nodelist * ndlp, void *arg, | 1586 | struct lpfc_nodelist *ndlp, |
1453 | uint32_t evt) | 1587 | void *arg, uint32_t evt) |
1454 | { | 1588 | { |
1455 | struct lpfc_iocbq *cmdiocb; | 1589 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1456 | |||
1457 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1458 | 1590 | ||
1459 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | 1591 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1460 | return ndlp->nlp_state; | 1592 | return ndlp->nlp_state; |
1461 | } | 1593 | } |
1462 | 1594 | ||
1463 | static uint32_t | 1595 | static uint32_t |
1464 | lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba, | 1596 | lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1465 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1597 | void *arg, uint32_t evt) |
1466 | { | 1598 | { |
1467 | struct lpfc_iocbq *cmdiocb; | 1599 | struct lpfc_hba *phba = vport->phba; |
1468 | 1600 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | |
1469 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1470 | 1601 | ||
1471 | /* flush the target */ | 1602 | /* flush the target */ |
1472 | spin_lock_irq(phba->host->host_lock); | ||
1473 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], | 1603 | lpfc_sli_abort_iocb(phba, &phba->sli.ring[phba->sli.fcp_ring], |
1474 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); | 1604 | ndlp->nlp_sid, 0, 0, LPFC_CTX_TGT); |
1475 | spin_unlock_irq(phba->host->host_lock); | ||
1476 | 1605 | ||
1477 | /* Treat like rcv logo */ | 1606 | /* Treat like rcv logo */ |
1478 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO); | 1607 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO); |
1479 | return ndlp->nlp_state; | 1608 | return ndlp->nlp_state; |
1480 | } | 1609 | } |
1481 | 1610 | ||
1482 | static uint32_t | 1611 | static uint32_t |
1483 | lpfc_device_recov_mapped_node(struct lpfc_hba * phba, | 1612 | lpfc_device_recov_mapped_node(struct lpfc_vport *vport, |
1484 | struct lpfc_nodelist * ndlp, void *arg, | 1613 | struct lpfc_nodelist *ndlp, |
1485 | uint32_t evt) | 1614 | void *arg, |
1615 | uint32_t evt) | ||
1486 | { | 1616 | { |
1617 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1618 | |||
1487 | ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE; | 1619 | ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE; |
1488 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1620 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1489 | spin_lock_irq(phba->host->host_lock); | 1621 | spin_lock_irq(shost->host_lock); |
1490 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1622 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1491 | spin_unlock_irq(phba->host->host_lock); | 1623 | spin_unlock_irq(shost->host_lock); |
1492 | lpfc_disc_set_adisc(phba, ndlp); | 1624 | lpfc_disc_set_adisc(vport, ndlp); |
1493 | return ndlp->nlp_state; | 1625 | return ndlp->nlp_state; |
1494 | } | 1626 | } |
1495 | 1627 | ||
1496 | static uint32_t | 1628 | static uint32_t |
1497 | lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba, | 1629 | lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1498 | struct lpfc_nodelist * ndlp, void *arg, | 1630 | void *arg, uint32_t evt) |
1499 | uint32_t evt) | ||
1500 | { | 1631 | { |
1501 | struct lpfc_iocbq *cmdiocb; | 1632 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1502 | 1633 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | |
1503 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1504 | 1634 | ||
1505 | /* Ignore PLOGI if we have an outstanding LOGO */ | 1635 | /* Ignore PLOGI if we have an outstanding LOGO */ |
1506 | if (ndlp->nlp_flag & NLP_LOGO_SND) { | 1636 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) { |
1507 | return ndlp->nlp_state; | 1637 | return ndlp->nlp_state; |
1508 | } | 1638 | } |
1509 | 1639 | ||
1510 | if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) { | 1640 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
1511 | spin_lock_irq(phba->host->host_lock); | 1641 | spin_lock_irq(shost->host_lock); |
1512 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1642 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1513 | spin_unlock_irq(phba->host->host_lock); | 1643 | spin_unlock_irq(shost->host_lock); |
1514 | return ndlp->nlp_state; | 1644 | return ndlp->nlp_state; |
1515 | } | 1645 | } |
1516 | 1646 | ||
1517 | /* send PLOGI immediately, move to PLOGI issue state */ | 1647 | /* send PLOGI immediately, move to PLOGI issue state */ |
1518 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1648 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { |
1519 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1649 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1520 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 1650 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1521 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 1651 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1522 | } | 1652 | } |
1523 | 1653 | ||
1524 | return ndlp->nlp_state; | 1654 | return ndlp->nlp_state; |
1525 | } | 1655 | } |
1526 | 1656 | ||
1527 | static uint32_t | 1657 | static uint32_t |
1528 | lpfc_rcv_prli_npr_node(struct lpfc_hba * phba, | 1658 | lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1529 | struct lpfc_nodelist * ndlp, void *arg, | 1659 | void *arg, uint32_t evt) |
1530 | uint32_t evt) | ||
1531 | { | 1660 | { |
1532 | struct lpfc_iocbq *cmdiocb; | 1661 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1533 | struct ls_rjt stat; | 1662 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1534 | 1663 | struct ls_rjt stat; | |
1535 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1536 | 1664 | ||
1537 | memset(&stat, 0, sizeof (struct ls_rjt)); | 1665 | memset(&stat, 0, sizeof (struct ls_rjt)); |
1538 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 1666 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
1539 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 1667 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
1540 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 1668 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
1541 | 1669 | ||
1542 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1670 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { |
1543 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 1671 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
1544 | spin_lock_irq(phba->host->host_lock); | 1672 | spin_lock_irq(shost->host_lock); |
1545 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1673 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1546 | spin_unlock_irq(phba->host->host_lock); | ||
1547 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1674 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1548 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); | 1675 | spin_unlock_irq(shost->host_lock); |
1549 | lpfc_issue_els_adisc(phba, ndlp, 0); | 1676 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
1677 | lpfc_issue_els_adisc(vport, ndlp, 0); | ||
1550 | } else { | 1678 | } else { |
1551 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1679 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1552 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 1680 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1553 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 1681 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1554 | } | 1682 | } |
1555 | } | 1683 | } |
1556 | return ndlp->nlp_state; | 1684 | return ndlp->nlp_state; |
1557 | } | 1685 | } |
1558 | 1686 | ||
1559 | static uint32_t | 1687 | static uint32_t |
1560 | lpfc_rcv_logo_npr_node(struct lpfc_hba * phba, | 1688 | lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1561 | struct lpfc_nodelist * ndlp, void *arg, | 1689 | void *arg, uint32_t evt) |
1562 | uint32_t evt) | ||
1563 | { | 1690 | { |
1564 | struct lpfc_iocbq *cmdiocb; | 1691 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1565 | 1692 | ||
1566 | cmdiocb = (struct lpfc_iocbq *) arg; | 1693 | lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO); |
1567 | |||
1568 | lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO); | ||
1569 | return ndlp->nlp_state; | 1694 | return ndlp->nlp_state; |
1570 | } | 1695 | } |
1571 | 1696 | ||
1572 | static uint32_t | 1697 | static uint32_t |
1573 | lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, | 1698 | lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1574 | struct lpfc_nodelist * ndlp, void *arg, | 1699 | void *arg, uint32_t evt) |
1575 | uint32_t evt) | ||
1576 | { | 1700 | { |
1577 | struct lpfc_iocbq *cmdiocb; | 1701 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1578 | |||
1579 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1580 | 1702 | ||
1581 | lpfc_rcv_padisc(phba, ndlp, cmdiocb); | 1703 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1582 | 1704 | ||
1583 | /* | 1705 | /* |
1584 | * Do not start discovery if discovery is about to start | 1706 | * Do not start discovery if discovery is about to start |
@@ -1586,53 +1708,52 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, | |||
1586 | * here will affect the counting of discovery threads. | 1708 | * here will affect the counting of discovery threads. |
1587 | */ | 1709 | */ |
1588 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && | 1710 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && |
1589 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){ | 1711 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
1590 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 1712 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
1713 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | ||
1591 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1714 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1592 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); | 1715 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
1593 | lpfc_issue_els_adisc(phba, ndlp, 0); | 1716 | lpfc_issue_els_adisc(vport, ndlp, 0); |
1594 | } else { | 1717 | } else { |
1595 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1718 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1596 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 1719 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1597 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 1720 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1598 | } | 1721 | } |
1599 | } | 1722 | } |
1600 | return ndlp->nlp_state; | 1723 | return ndlp->nlp_state; |
1601 | } | 1724 | } |
1602 | 1725 | ||
1603 | static uint32_t | 1726 | static uint32_t |
1604 | lpfc_rcv_prlo_npr_node(struct lpfc_hba * phba, | 1727 | lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1605 | struct lpfc_nodelist * ndlp, void *arg, | 1728 | void *arg, uint32_t evt) |
1606 | uint32_t evt) | ||
1607 | { | 1729 | { |
1608 | struct lpfc_iocbq *cmdiocb; | 1730 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1609 | 1731 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | |
1610 | cmdiocb = (struct lpfc_iocbq *) arg; | ||
1611 | 1732 | ||
1612 | spin_lock_irq(phba->host->host_lock); | 1733 | spin_lock_irq(shost->host_lock); |
1613 | ndlp->nlp_flag |= NLP_LOGO_ACC; | 1734 | ndlp->nlp_flag |= NLP_LOGO_ACC; |
1614 | spin_unlock_irq(phba->host->host_lock); | 1735 | spin_unlock_irq(shost->host_lock); |
1615 | 1736 | ||
1616 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 1737 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
1617 | 1738 | ||
1618 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1739 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { |
1619 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 1740 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
1620 | spin_lock_irq(phba->host->host_lock); | 1741 | spin_lock_irq(shost->host_lock); |
1621 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1742 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
1622 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1743 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1623 | spin_unlock_irq(phba->host->host_lock); | 1744 | spin_unlock_irq(shost->host_lock); |
1624 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; | 1745 | ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; |
1625 | } else { | 1746 | } else { |
1626 | spin_lock_irq(phba->host->host_lock); | 1747 | spin_lock_irq(shost->host_lock); |
1627 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1748 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
1628 | spin_unlock_irq(phba->host->host_lock); | 1749 | spin_unlock_irq(shost->host_lock); |
1629 | } | 1750 | } |
1630 | return ndlp->nlp_state; | 1751 | return ndlp->nlp_state; |
1631 | } | 1752 | } |
1632 | 1753 | ||
1633 | static uint32_t | 1754 | static uint32_t |
1634 | lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba, | 1755 | lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1635 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1756 | void *arg, uint32_t evt) |
1636 | { | 1757 | { |
1637 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1758 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
1638 | IOCB_t *irsp; | 1759 | IOCB_t *irsp; |
@@ -1642,15 +1763,15 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba, | |||
1642 | 1763 | ||
1643 | irsp = &rspiocb->iocb; | 1764 | irsp = &rspiocb->iocb; |
1644 | if (irsp->ulpStatus) { | 1765 | if (irsp->ulpStatus) { |
1645 | lpfc_drop_node(phba, ndlp); | 1766 | lpfc_drop_node(vport, ndlp); |
1646 | return NLP_STE_FREED_NODE; | 1767 | return NLP_STE_FREED_NODE; |
1647 | } | 1768 | } |
1648 | return ndlp->nlp_state; | 1769 | return ndlp->nlp_state; |
1649 | } | 1770 | } |
1650 | 1771 | ||
1651 | static uint32_t | 1772 | static uint32_t |
1652 | lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba, | 1773 | lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1653 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1774 | void *arg, uint32_t evt) |
1654 | { | 1775 | { |
1655 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1776 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
1656 | IOCB_t *irsp; | 1777 | IOCB_t *irsp; |
@@ -1660,25 +1781,24 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba, | |||
1660 | 1781 | ||
1661 | irsp = &rspiocb->iocb; | 1782 | irsp = &rspiocb->iocb; |
1662 | if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { | 1783 | if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { |
1663 | lpfc_drop_node(phba, ndlp); | 1784 | lpfc_drop_node(vport, ndlp); |
1664 | return NLP_STE_FREED_NODE; | 1785 | return NLP_STE_FREED_NODE; |
1665 | } | 1786 | } |
1666 | return ndlp->nlp_state; | 1787 | return ndlp->nlp_state; |
1667 | } | 1788 | } |
1668 | 1789 | ||
1669 | static uint32_t | 1790 | static uint32_t |
1670 | lpfc_cmpl_logo_npr_node(struct lpfc_hba * phba, | 1791 | lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1671 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 1792 | void *arg, uint32_t evt) |
1672 | { | 1793 | { |
1673 | lpfc_unreg_rpi(phba, ndlp); | 1794 | lpfc_unreg_rpi(vport, ndlp); |
1674 | /* This routine does nothing, just return the current state */ | 1795 | /* This routine does nothing, just return the current state */ |
1675 | return ndlp->nlp_state; | 1796 | return ndlp->nlp_state; |
1676 | } | 1797 | } |
1677 | 1798 | ||
1678 | static uint32_t | 1799 | static uint32_t |
1679 | lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba, | 1800 | lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1680 | struct lpfc_nodelist * ndlp, void *arg, | 1801 | void *arg, uint32_t evt) |
1681 | uint32_t evt) | ||
1682 | { | 1802 | { |
1683 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 1803 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
1684 | IOCB_t *irsp; | 1804 | IOCB_t *irsp; |
@@ -1688,28 +1808,25 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba, | |||
1688 | 1808 | ||
1689 | irsp = &rspiocb->iocb; | 1809 | irsp = &rspiocb->iocb; |
1690 | if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { | 1810 | if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) { |
1691 | lpfc_drop_node(phba, ndlp); | 1811 | lpfc_drop_node(vport, ndlp); |
1692 | return NLP_STE_FREED_NODE; | 1812 | return NLP_STE_FREED_NODE; |
1693 | } | 1813 | } |
1694 | return ndlp->nlp_state; | 1814 | return ndlp->nlp_state; |
1695 | } | 1815 | } |
1696 | 1816 | ||
1697 | static uint32_t | 1817 | static uint32_t |
1698 | lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba, | 1818 | lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport, |
1699 | struct lpfc_nodelist * ndlp, void *arg, | 1819 | struct lpfc_nodelist *ndlp, |
1700 | uint32_t evt) | 1820 | void *arg, uint32_t evt) |
1701 | { | 1821 | { |
1702 | LPFC_MBOXQ_t *pmb; | 1822 | LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; |
1703 | MAILBOX_t *mb; | 1823 | MAILBOX_t *mb = &pmb->mb; |
1704 | |||
1705 | pmb = (LPFC_MBOXQ_t *) arg; | ||
1706 | mb = &pmb->mb; | ||
1707 | 1824 | ||
1708 | if (!mb->mbxStatus) | 1825 | if (!mb->mbxStatus) |
1709 | ndlp->nlp_rpi = mb->un.varWords[0]; | 1826 | ndlp->nlp_rpi = mb->un.varWords[0]; |
1710 | else { | 1827 | else { |
1711 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { | 1828 | if (ndlp->nlp_flag & NLP_NODEV_REMOVE) { |
1712 | lpfc_drop_node(phba, ndlp); | 1829 | lpfc_drop_node(vport, ndlp); |
1713 | return NLP_STE_FREED_NODE; | 1830 | return NLP_STE_FREED_NODE; |
1714 | } | 1831 | } |
1715 | } | 1832 | } |
@@ -1717,28 +1834,38 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba, | |||
1717 | } | 1834 | } |
1718 | 1835 | ||
1719 | static uint32_t | 1836 | static uint32_t |
1720 | lpfc_device_rm_npr_node(struct lpfc_hba * phba, | 1837 | lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1721 | struct lpfc_nodelist * ndlp, void *arg, | 1838 | void *arg, uint32_t evt) |
1722 | uint32_t evt) | ||
1723 | { | 1839 | { |
1840 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1841 | |||
1724 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | 1842 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { |
1843 | spin_lock_irq(shost->host_lock); | ||
1725 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; | 1844 | ndlp->nlp_flag |= NLP_NODEV_REMOVE; |
1845 | spin_unlock_irq(shost->host_lock); | ||
1726 | return ndlp->nlp_state; | 1846 | return ndlp->nlp_state; |
1727 | } | 1847 | } |
1728 | lpfc_drop_node(phba, ndlp); | 1848 | lpfc_drop_node(vport, ndlp); |
1729 | return NLP_STE_FREED_NODE; | 1849 | return NLP_STE_FREED_NODE; |
1730 | } | 1850 | } |
1731 | 1851 | ||
1732 | static uint32_t | 1852 | static uint32_t |
1733 | lpfc_device_recov_npr_node(struct lpfc_hba * phba, | 1853 | lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1734 | struct lpfc_nodelist * ndlp, void *arg, | 1854 | void *arg, uint32_t evt) |
1735 | uint32_t evt) | ||
1736 | { | 1855 | { |
1737 | spin_lock_irq(phba->host->host_lock); | 1856 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1857 | |||
1858 | /* Don't do anything that will mess up processing of the | ||
1859 | * previous RSCN. | ||
1860 | */ | ||
1861 | if (vport->fc_flag & FC_RSCN_DEFERRED) | ||
1862 | return ndlp->nlp_state; | ||
1863 | |||
1864 | spin_lock_irq(shost->host_lock); | ||
1738 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1865 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1739 | spin_unlock_irq(phba->host->host_lock); | 1866 | spin_unlock_irq(shost->host_lock); |
1740 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 1867 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { |
1741 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 1868 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1742 | } | 1869 | } |
1743 | return ndlp->nlp_state; | 1870 | return ndlp->nlp_state; |
1744 | } | 1871 | } |
@@ -1801,7 +1928,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba, | |||
1801 | */ | 1928 | */ |
1802 | 1929 | ||
1803 | static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | 1930 | static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) |
1804 | (struct lpfc_hba *, struct lpfc_nodelist *, void *, uint32_t) = { | 1931 | (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = { |
1805 | /* Action routine Event Current State */ | 1932 | /* Action routine Event Current State */ |
1806 | lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */ | 1933 | lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */ |
1807 | lpfc_rcv_els_unused_node, /* RCV_PRLI */ | 1934 | lpfc_rcv_els_unused_node, /* RCV_PRLI */ |
@@ -1818,7 +1945,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1818 | lpfc_disc_illegal, /* DEVICE_RECOVERY */ | 1945 | lpfc_disc_illegal, /* DEVICE_RECOVERY */ |
1819 | 1946 | ||
1820 | lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ | 1947 | lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */ |
1821 | lpfc_rcv_els_plogi_issue, /* RCV_PRLI */ | 1948 | lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */ |
1822 | lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */ | 1949 | lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */ |
1823 | lpfc_rcv_els_plogi_issue, /* RCV_ADISC */ | 1950 | lpfc_rcv_els_plogi_issue, /* RCV_ADISC */ |
1824 | lpfc_rcv_els_plogi_issue, /* RCV_PDISC */ | 1951 | lpfc_rcv_els_plogi_issue, /* RCV_PDISC */ |
@@ -1917,35 +2044,41 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT]) | |||
1917 | }; | 2044 | }; |
1918 | 2045 | ||
1919 | int | 2046 | int |
1920 | lpfc_disc_state_machine(struct lpfc_hba * phba, | 2047 | lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1921 | struct lpfc_nodelist * ndlp, void *arg, uint32_t evt) | 2048 | void *arg, uint32_t evt) |
1922 | { | 2049 | { |
2050 | struct lpfc_hba *phba = vport->phba; | ||
1923 | uint32_t cur_state, rc; | 2051 | uint32_t cur_state, rc; |
1924 | uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *, | 2052 | uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *, |
1925 | uint32_t); | 2053 | uint32_t); |
1926 | 2054 | ||
1927 | lpfc_nlp_get(ndlp); | 2055 | lpfc_nlp_get(ndlp); |
1928 | cur_state = ndlp->nlp_state; | 2056 | cur_state = ndlp->nlp_state; |
1929 | 2057 | ||
1930 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ | 2058 | /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */ |
1931 | lpfc_printf_log(phba, | 2059 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
1932 | KERN_INFO, | 2060 | "%d (%d):0211 DSM in event x%x on NPort x%x in " |
1933 | LOG_DISCOVERY, | 2061 | "state %d Data: x%x\n", |
1934 | "%d:0211 DSM in event x%x on NPort x%x in state %d " | 2062 | phba->brd_no, vport->vpi, |
1935 | "Data: x%x\n", | ||
1936 | phba->brd_no, | ||
1937 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); | 2063 | evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); |
1938 | 2064 | ||
2065 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, | ||
2066 | "DSM in: evt:%d ste:%d did:x%x", | ||
2067 | evt, cur_state, ndlp->nlp_DID); | ||
2068 | |||
1939 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; | 2069 | func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; |
1940 | rc = (func) (phba, ndlp, arg, evt); | 2070 | rc = (func) (vport, ndlp, arg, evt); |
1941 | 2071 | ||
1942 | /* DSM out state <rc> on NPort <nlp_DID> */ | 2072 | /* DSM out state <rc> on NPort <nlp_DID> */ |
1943 | lpfc_printf_log(phba, | 2073 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
1944 | KERN_INFO, | 2074 | "%d (%d):0212 DSM out state %d on NPort x%x " |
1945 | LOG_DISCOVERY, | 2075 | "Data: x%x\n", |
1946 | "%d:0212 DSM out state %d on NPort x%x Data: x%x\n", | 2076 | phba->brd_no, vport->vpi, |
1947 | phba->brd_no, | 2077 | rc, ndlp->nlp_DID, ndlp->nlp_flag); |
1948 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | 2078 | |
2079 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM, | ||
2080 | "DSM out: ste:%d did:x%x flg:x%x", | ||
2081 | rc, ndlp->nlp_DID, ndlp->nlp_flag); | ||
1949 | 2082 | ||
1950 | lpfc_nlp_put(ndlp); | 2083 | lpfc_nlp_put(ndlp); |
1951 | 2084 | ||