diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 1431 |
1 files changed, 716 insertions, 715 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 638b3cd677bd..0af33bead302 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -41,23 +41,20 @@ static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *, | |||
41 | static int lpfc_max_els_tries = 3; | 41 | static int lpfc_max_els_tries = 3; |
42 | 42 | ||
43 | static int | 43 | static int |
44 | lpfc_els_chk_latt(struct lpfc_hba * phba) | 44 | lpfc_els_chk_latt(struct lpfc_vport *vport) |
45 | { | 45 | { |
46 | struct lpfc_sli *psli; | 46 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
47 | struct lpfc_hba *phba = vport->phba; | ||
47 | LPFC_MBOXQ_t *mbox; | 48 | LPFC_MBOXQ_t *mbox; |
48 | uint32_t ha_copy; | 49 | uint32_t ha_copy; |
49 | int rc; | 50 | int rc; |
50 | 51 | ||
51 | psli = &phba->sli; | 52 | if (vport->port_state >= LPFC_VPORT_READY || |
52 | 53 | phba->link_state == LPFC_LINK_DOWN) | |
53 | if ((phba->hba_state >= LPFC_HBA_READY) || | ||
54 | (phba->hba_state == LPFC_LINK_DOWN)) | ||
55 | return 0; | 54 | return 0; |
56 | 55 | ||
57 | /* Read the HBA Host Attention Register */ | 56 | /* Read the HBA Host Attention Register */ |
58 | spin_lock_irq(phba->host->host_lock); | ||
59 | ha_copy = readl(phba->HAregaddr); | 57 | ha_copy = readl(phba->HAregaddr); |
60 | spin_unlock_irq(phba->host->host_lock); | ||
61 | 58 | ||
62 | if (!(ha_copy & HA_LATT)) | 59 | if (!(ha_copy & HA_LATT)) |
63 | return 0; | 60 | return 0; |
@@ -66,7 +63,7 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) | |||
66 | lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY, | 63 | lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY, |
67 | "%d:0237 Pending Link Event during " | 64 | "%d:0237 Pending Link Event during " |
68 | "Discovery: State x%x\n", | 65 | "Discovery: State x%x\n", |
69 | phba->brd_no, phba->hba_state); | 66 | phba->brd_no, phba->pport->port_state); |
70 | 67 | ||
71 | /* CLEAR_LA should re-enable link attention events and | 68 | /* CLEAR_LA should re-enable link attention events and |
72 | * we should then imediately take a LATT event. The | 69 | * we should then imediately take a LATT event. The |
@@ -74,20 +71,23 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) | |||
74 | * will cleanup any left over in-progress discovery | 71 | * will cleanup any left over in-progress discovery |
75 | * events. | 72 | * events. |
76 | */ | 73 | */ |
77 | spin_lock_irq(phba->host->host_lock); | 74 | spin_lock_irq(shost->host_lock); |
78 | phba->fc_flag |= FC_ABORT_DISCOVERY; | 75 | vport->fc_flag |= FC_ABORT_DISCOVERY; |
79 | spin_unlock_irq(phba->host->host_lock); | 76 | spin_unlock_irq(shost->host_lock); |
80 | 77 | ||
81 | if (phba->hba_state != LPFC_CLEAR_LA) { | 78 | if (phba->link_state != LPFC_CLEAR_LA) { |
82 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { | 79 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { |
83 | phba->hba_state = LPFC_CLEAR_LA; | 80 | phba->link_state = LPFC_CLEAR_LA; |
84 | lpfc_clear_la(phba, mbox); | 81 | lpfc_clear_la(phba, mbox); |
85 | mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; | 82 | mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la; |
86 | rc = lpfc_sli_issue_mbox (phba, mbox, | 83 | mbox->vport = vport; |
87 | (MBX_NOWAIT | MBX_STOP_IOCB)); | 84 | printk(KERN_ERR "%s (%d): do clear_la\n", |
85 | __FUNCTION__, __LINE__); | ||
86 | rc = lpfc_sli_issue_mbox(phba, mbox, | ||
87 | (MBX_NOWAIT | MBX_STOP_IOCB)); | ||
88 | if (rc == MBX_NOT_FINISHED) { | 88 | if (rc == MBX_NOT_FINISHED) { |
89 | mempool_free(mbox, phba->mbox_mem_pool); | 89 | mempool_free(mbox, phba->mbox_mem_pool); |
90 | phba->hba_state = LPFC_HBA_ERROR; | 90 | phba->link_state = LPFC_HBA_ERROR; |
91 | } | 91 | } |
92 | } | 92 | } |
93 | } | 93 | } |
@@ -97,25 +97,23 @@ lpfc_els_chk_latt(struct lpfc_hba * phba) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | static struct lpfc_iocbq * | 99 | static struct lpfc_iocbq * |
100 | lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | 100 | lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, |
101 | uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp, | 101 | uint16_t cmdSize, uint8_t retry, |
102 | uint32_t did, uint32_t elscmd) | 102 | struct lpfc_nodelist *ndlp, uint32_t did, |
103 | uint32_t elscmd) | ||
103 | { | 104 | { |
104 | struct lpfc_sli_ring *pring; | 105 | struct lpfc_hba *phba = vport->phba; |
105 | struct lpfc_iocbq *elsiocb; | 106 | struct lpfc_iocbq *elsiocb; |
106 | struct lpfc_dmabuf *pcmd, *prsp, *pbuflist; | 107 | struct lpfc_dmabuf *pcmd, *prsp, *pbuflist; |
107 | struct ulp_bde64 *bpl; | 108 | struct ulp_bde64 *bpl; |
108 | IOCB_t *icmd; | 109 | IOCB_t *icmd; |
109 | 110 | ||
110 | pring = &phba->sli.ring[LPFC_ELS_RING]; | ||
111 | 111 | ||
112 | if (phba->hba_state < LPFC_LINK_UP) | 112 | if (!lpfc_is_link_up(phba)) |
113 | return NULL; | 113 | return NULL; |
114 | 114 | ||
115 | /* Allocate buffer for command iocb */ | 115 | /* Allocate buffer for command iocb */ |
116 | spin_lock_irq(phba->host->host_lock); | ||
117 | elsiocb = lpfc_sli_get_iocbq(phba); | 116 | elsiocb = lpfc_sli_get_iocbq(phba); |
118 | spin_unlock_irq(phba->host->host_lock); | ||
119 | 117 | ||
120 | if (elsiocb == NULL) | 118 | if (elsiocb == NULL) |
121 | return NULL; | 119 | return NULL; |
@@ -128,9 +126,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
128 | MEM_PRI, &(pcmd->phys))) == 0)) { | 126 | MEM_PRI, &(pcmd->phys))) == 0)) { |
129 | kfree(pcmd); | 127 | kfree(pcmd); |
130 | 128 | ||
131 | spin_lock_irq(phba->host->host_lock); | ||
132 | lpfc_sli_release_iocbq(phba, elsiocb); | 129 | lpfc_sli_release_iocbq(phba, elsiocb); |
133 | spin_unlock_irq(phba->host->host_lock); | ||
134 | return NULL; | 130 | return NULL; |
135 | } | 131 | } |
136 | 132 | ||
@@ -146,9 +142,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
146 | kfree(prsp); | 142 | kfree(prsp); |
147 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 143 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
148 | kfree(pcmd); | 144 | kfree(pcmd); |
149 | spin_lock_irq(phba->host->host_lock); | ||
150 | lpfc_sli_release_iocbq(phba, elsiocb); | 145 | lpfc_sli_release_iocbq(phba, elsiocb); |
151 | spin_unlock_irq(phba->host->host_lock); | ||
152 | return NULL; | 146 | return NULL; |
153 | } | 147 | } |
154 | INIT_LIST_HEAD(&prsp->list); | 148 | INIT_LIST_HEAD(&prsp->list); |
@@ -162,9 +156,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
162 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, | 156 | pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, |
163 | &pbuflist->phys); | 157 | &pbuflist->phys); |
164 | if (pbuflist == 0 || pbuflist->virt == 0) { | 158 | if (pbuflist == 0 || pbuflist->virt == 0) { |
165 | spin_lock_irq(phba->host->host_lock); | ||
166 | lpfc_sli_release_iocbq(phba, elsiocb); | 159 | lpfc_sli_release_iocbq(phba, elsiocb); |
167 | spin_unlock_irq(phba->host->host_lock); | ||
168 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); | 160 | lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); |
169 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); | 161 | lpfc_mbuf_free(phba, prsp->virt, prsp->phys); |
170 | kfree(pcmd); | 162 | kfree(pcmd); |
@@ -178,9 +170,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
178 | icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); | 170 | icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); |
179 | icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys); | 171 | icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys); |
180 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; | 172 | icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL; |
173 | icmd->un.elsreq64.remoteID = did; /* DID */ | ||
181 | if (expectRsp) { | 174 | if (expectRsp) { |
182 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); | 175 | icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64)); |
183 | icmd->un.elsreq64.remoteID = did; /* DID */ | ||
184 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; | 176 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; |
185 | icmd->ulpTimeout = phba->fc_ratov * 2; | 177 | icmd->ulpTimeout = phba->fc_ratov * 2; |
186 | } else { | 178 | } else { |
@@ -213,6 +205,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
213 | elsiocb->context2 = pcmd; | 205 | elsiocb->context2 = pcmd; |
214 | elsiocb->context3 = pbuflist; | 206 | elsiocb->context3 = pbuflist; |
215 | elsiocb->retry = retry; | 207 | elsiocb->retry = retry; |
208 | elsiocb->vport = vport; | ||
216 | elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; | 209 | elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT; |
217 | 210 | ||
218 | if (prsp) { | 211 | if (prsp) { |
@@ -223,9 +216,9 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
223 | /* Xmit ELS command <elsCmd> to remote NPORT <did> */ | 216 | /* Xmit ELS command <elsCmd> to remote NPORT <did> */ |
224 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 217 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
225 | "%d:0116 Xmit ELS command x%x to remote " | 218 | "%d:0116 Xmit ELS command x%x to remote " |
226 | "NPORT x%x I/O tag: x%x, HBA state: x%x\n", | 219 | "NPORT x%x I/O tag: x%x, port state: x%x\n", |
227 | phba->brd_no, elscmd, | 220 | phba->brd_no, elscmd, did, |
228 | did, elsiocb->iotag, phba->hba_state); | 221 | elsiocb->iotag, vport->port_state); |
229 | } else { | 222 | } else { |
230 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ | 223 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ |
231 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 224 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -240,16 +233,18 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp, | |||
240 | 233 | ||
241 | 234 | ||
242 | static int | 235 | static int |
243 | lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 236 | lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
244 | struct serv_parm *sp, IOCB_t *irsp) | 237 | struct serv_parm *sp, IOCB_t *irsp) |
245 | { | 238 | { |
239 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
240 | struct lpfc_hba *phba = vport->phba; | ||
246 | LPFC_MBOXQ_t *mbox; | 241 | LPFC_MBOXQ_t *mbox; |
247 | struct lpfc_dmabuf *mp; | 242 | struct lpfc_dmabuf *mp; |
248 | int rc; | 243 | int rc; |
249 | 244 | ||
250 | spin_lock_irq(phba->host->host_lock); | 245 | spin_lock_irq(shost->host_lock); |
251 | phba->fc_flag |= FC_FABRIC; | 246 | vport->fc_flag |= FC_FABRIC; |
252 | spin_unlock_irq(phba->host->host_lock); | 247 | spin_unlock_irq(shost->host_lock); |
253 | 248 | ||
254 | phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov); | 249 | phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov); |
255 | if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */ | 250 | if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */ |
@@ -258,18 +253,18 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
258 | phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000; | 253 | phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000; |
259 | 254 | ||
260 | if (phba->fc_topology == TOPOLOGY_LOOP) { | 255 | if (phba->fc_topology == TOPOLOGY_LOOP) { |
261 | spin_lock_irq(phba->host->host_lock); | 256 | spin_lock_irq(shost->host_lock); |
262 | phba->fc_flag |= FC_PUBLIC_LOOP; | 257 | vport->fc_flag |= FC_PUBLIC_LOOP; |
263 | spin_unlock_irq(phba->host->host_lock); | 258 | spin_unlock_irq(shost->host_lock); |
264 | } else { | 259 | } else { |
265 | /* | 260 | /* |
266 | * If we are a N-port connected to a Fabric, fixup sparam's so | 261 | * If we are a N-port connected to a Fabric, fixup sparam's so |
267 | * logins to devices on remote loops work. | 262 | * logins to devices on remote loops work. |
268 | */ | 263 | */ |
269 | phba->fc_sparam.cmn.altBbCredit = 1; | 264 | vport->fc_sparam.cmn.altBbCredit = 1; |
270 | } | 265 | } |
271 | 266 | ||
272 | phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; | 267 | vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID; |
273 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name)); | 268 | memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name)); |
274 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); | 269 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name)); |
275 | ndlp->nlp_class_sup = 0; | 270 | ndlp->nlp_class_sup = 0; |
@@ -285,11 +280,13 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
285 | sp->cmn.bbRcvSizeLsb; | 280 | sp->cmn.bbRcvSizeLsb; |
286 | memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); | 281 | memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); |
287 | 282 | ||
283 | ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID; | ||
284 | |||
288 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 285 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
289 | if (!mbox) | 286 | if (!mbox) |
290 | goto fail; | 287 | goto fail; |
291 | 288 | ||
292 | phba->hba_state = LPFC_FABRIC_CFG_LINK; | 289 | vport->port_state = LPFC_FABRIC_CFG_LINK; |
293 | lpfc_config_link(phba, mbox); | 290 | lpfc_config_link(phba, mbox); |
294 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 291 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
295 | 292 | ||
@@ -300,11 +297,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
300 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 297 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
301 | if (!mbox) | 298 | if (!mbox) |
302 | goto fail; | 299 | goto fail; |
303 | 300 | rc = lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0); | |
304 | if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0)) | 301 | if (rc) |
305 | goto fail_free_mbox; | 302 | goto fail_free_mbox; |
306 | 303 | ||
307 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; | 304 | mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login; |
305 | mbox->vport = vport; | ||
308 | mbox->context2 = lpfc_nlp_get(ndlp); | 306 | mbox->context2 = lpfc_nlp_get(ndlp); |
309 | 307 | ||
310 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); | 308 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); |
@@ -328,25 +326,27 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
328 | * We FLOGIed into an NPort, initiate pt2pt protocol | 326 | * We FLOGIed into an NPort, initiate pt2pt protocol |
329 | */ | 327 | */ |
330 | static int | 328 | static int |
331 | lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | 329 | lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
332 | struct serv_parm *sp) | 330 | struct serv_parm *sp) |
333 | { | 331 | { |
332 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
333 | struct lpfc_hba *phba = vport->phba; | ||
334 | LPFC_MBOXQ_t *mbox; | 334 | LPFC_MBOXQ_t *mbox; |
335 | int rc; | 335 | int rc; |
336 | 336 | ||
337 | spin_lock_irq(phba->host->host_lock); | 337 | spin_lock_irq(shost->host_lock); |
338 | phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 338 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
339 | spin_unlock_irq(phba->host->host_lock); | 339 | spin_unlock_irq(shost->host_lock); |
340 | 340 | ||
341 | phba->fc_edtov = FF_DEF_EDTOV; | 341 | phba->fc_edtov = FF_DEF_EDTOV; |
342 | phba->fc_ratov = FF_DEF_RATOV; | 342 | phba->fc_ratov = FF_DEF_RATOV; |
343 | rc = memcmp(&phba->fc_portname, &sp->portName, | 343 | rc = memcmp(&vport->fc_portname, &sp->portName, |
344 | sizeof(struct lpfc_name)); | 344 | sizeof(struct lpfc_name)); |
345 | if (rc >= 0) { | 345 | if (rc >= 0) { |
346 | /* This side will initiate the PLOGI */ | 346 | /* This side will initiate the PLOGI */ |
347 | spin_lock_irq(phba->host->host_lock); | 347 | spin_lock_irq(shost->host_lock); |
348 | phba->fc_flag |= FC_PT2PT_PLOGI; | 348 | vport->fc_flag |= FC_PT2PT_PLOGI; |
349 | spin_unlock_irq(phba->host->host_lock); | 349 | spin_unlock_irq(shost->host_lock); |
350 | 350 | ||
351 | /* | 351 | /* |
352 | * N_Port ID cannot be 0, set our to LocalID the other | 352 | * N_Port ID cannot be 0, set our to LocalID the other |
@@ -355,7 +355,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
355 | 355 | ||
356 | /* not equal */ | 356 | /* not equal */ |
357 | if (rc) | 357 | if (rc) |
358 | phba->fc_myDID = PT2PT_LocalID; | 358 | vport->fc_myDID = PT2PT_LocalID; |
359 | 359 | ||
360 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 360 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
361 | if (!mbox) | 361 | if (!mbox) |
@@ -372,7 +372,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
372 | } | 372 | } |
373 | lpfc_nlp_put(ndlp); | 373 | lpfc_nlp_put(ndlp); |
374 | 374 | ||
375 | ndlp = lpfc_findnode_did(phba, PT2PT_RemoteID); | 375 | ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID); |
376 | if (!ndlp) { | 376 | if (!ndlp) { |
377 | /* | 377 | /* |
378 | * Cannot find existing Fabric ndlp, so allocate a | 378 | * Cannot find existing Fabric ndlp, so allocate a |
@@ -382,26 +382,28 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
382 | if (!ndlp) | 382 | if (!ndlp) |
383 | goto fail; | 383 | goto fail; |
384 | 384 | ||
385 | lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID); | 385 | lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID); |
386 | } | 386 | } |
387 | 387 | ||
388 | memcpy(&ndlp->nlp_portname, &sp->portName, | 388 | memcpy(&ndlp->nlp_portname, &sp->portName, |
389 | sizeof(struct lpfc_name)); | 389 | sizeof(struct lpfc_name)); |
390 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, | 390 | memcpy(&ndlp->nlp_nodename, &sp->nodeName, |
391 | sizeof(struct lpfc_name)); | 391 | sizeof(struct lpfc_name)); |
392 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 392 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
393 | spin_lock_irq(shost->host_lock); | ||
393 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 394 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
395 | spin_unlock_irq(shost->host_lock); | ||
394 | } else { | 396 | } else { |
395 | /* This side will wait for the PLOGI */ | 397 | /* This side will wait for the PLOGI */ |
396 | lpfc_nlp_put(ndlp); | 398 | lpfc_nlp_put(ndlp); |
397 | } | 399 | } |
398 | 400 | ||
399 | spin_lock_irq(phba->host->host_lock); | 401 | spin_lock_irq(shost->host_lock); |
400 | phba->fc_flag |= FC_PT2PT; | 402 | vport->fc_flag |= FC_PT2PT; |
401 | spin_unlock_irq(phba->host->host_lock); | 403 | spin_unlock_irq(shost->host_lock); |
402 | 404 | ||
403 | /* Start discovery - this should just do CLEAR_LA */ | 405 | /* Start discovery - this should just do CLEAR_LA */ |
404 | lpfc_disc_start(phba); | 406 | lpfc_disc_start(vport); |
405 | return 0; | 407 | return 0; |
406 | fail: | 408 | fail: |
407 | return -ENXIO; | 409 | return -ENXIO; |
@@ -411,6 +413,8 @@ static void | |||
411 | lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 413 | lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
412 | struct lpfc_iocbq *rspiocb) | 414 | struct lpfc_iocbq *rspiocb) |
413 | { | 415 | { |
416 | struct lpfc_vport *vport = cmdiocb->vport; | ||
417 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
414 | IOCB_t *irsp = &rspiocb->iocb; | 418 | IOCB_t *irsp = &rspiocb->iocb; |
415 | struct lpfc_nodelist *ndlp = cmdiocb->context1; | 419 | struct lpfc_nodelist *ndlp = cmdiocb->context1; |
416 | struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp; | 420 | struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp; |
@@ -418,21 +422,20 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
418 | int rc; | 422 | int rc; |
419 | 423 | ||
420 | /* Check to see if link went down during discovery */ | 424 | /* Check to see if link went down during discovery */ |
421 | if (lpfc_els_chk_latt(phba)) { | 425 | if (lpfc_els_chk_latt(vport)) { |
422 | lpfc_nlp_put(ndlp); | 426 | lpfc_nlp_put(ndlp); |
423 | goto out; | 427 | goto out; |
424 | } | 428 | } |
425 | 429 | ||
426 | if (irsp->ulpStatus) { | 430 | if (irsp->ulpStatus) { |
427 | /* Check for retry */ | 431 | /* Check for retry */ |
428 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { | 432 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
429 | /* ELS command is being retried */ | ||
430 | goto out; | 433 | goto out; |
431 | } | 434 | |
432 | /* FLOGI failed, so there is no fabric */ | 435 | /* FLOGI failed, so there is no fabric */ |
433 | spin_lock_irq(phba->host->host_lock); | 436 | spin_lock_irq(shost->host_lock); |
434 | phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 437 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
435 | spin_unlock_irq(phba->host->host_lock); | 438 | spin_unlock_irq(shost->host_lock); |
436 | 439 | ||
437 | /* If private loop, then allow max outstanding els to be | 440 | /* If private loop, then allow max outstanding els to be |
438 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no | 441 | * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no |
@@ -469,15 +472,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
469 | irsp->un.ulpWord[4], sp->cmn.e_d_tov, | 472 | irsp->un.ulpWord[4], sp->cmn.e_d_tov, |
470 | sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution); | 473 | sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution); |
471 | 474 | ||
472 | if (phba->hba_state == LPFC_FLOGI) { | 475 | if (vport->port_state == LPFC_FLOGI) { |
473 | /* | 476 | /* |
474 | * If Common Service Parameters indicate Nport | 477 | * If Common Service Parameters indicate Nport |
475 | * we are point to point, if Fport we are Fabric. | 478 | * we are point to point, if Fport we are Fabric. |
476 | */ | 479 | */ |
477 | if (sp->cmn.fPort) | 480 | if (sp->cmn.fPort) |
478 | rc = lpfc_cmpl_els_flogi_fabric(phba, ndlp, sp, irsp); | 481 | rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp); |
479 | else | 482 | else |
480 | rc = lpfc_cmpl_els_flogi_nport(phba, ndlp, sp); | 483 | rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); |
481 | 484 | ||
482 | if (!rc) | 485 | if (!rc) |
483 | goto out; | 486 | goto out; |
@@ -490,10 +493,10 @@ flogifail: | |||
490 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && | 493 | (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED && |
491 | irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) { | 494 | irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) { |
492 | /* FLOGI failed, so just use loop map to make discovery list */ | 495 | /* FLOGI failed, so just use loop map to make discovery list */ |
493 | lpfc_disc_list_loopmap(phba); | 496 | lpfc_disc_list_loopmap(vport); |
494 | 497 | ||
495 | /* Start discovery */ | 498 | /* Start discovery */ |
496 | lpfc_disc_start(phba); | 499 | lpfc_disc_start(vport); |
497 | } | 500 | } |
498 | 501 | ||
499 | out: | 502 | out: |
@@ -501,9 +504,10 @@ out: | |||
501 | } | 504 | } |
502 | 505 | ||
503 | static int | 506 | static int |
504 | lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 507 | lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
505 | uint8_t retry) | 508 | uint8_t retry) |
506 | { | 509 | { |
510 | struct lpfc_hba *phba = vport->phba; | ||
507 | struct serv_parm *sp; | 511 | struct serv_parm *sp; |
508 | IOCB_t *icmd; | 512 | IOCB_t *icmd; |
509 | struct lpfc_iocbq *elsiocb; | 513 | struct lpfc_iocbq *elsiocb; |
@@ -516,8 +520,8 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
516 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 520 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
517 | 521 | ||
518 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); | 522 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); |
519 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 523 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
520 | ndlp->nlp_DID, ELS_CMD_FLOGI); | 524 | ndlp->nlp_DID, ELS_CMD_FLOGI); |
521 | if (!elsiocb) | 525 | if (!elsiocb) |
522 | return 1; | 526 | return 1; |
523 | 527 | ||
@@ -527,7 +531,7 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
527 | /* For FLOGI request, remainder of payload is service parameters */ | 531 | /* For FLOGI request, remainder of payload is service parameters */ |
528 | *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI; | 532 | *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI; |
529 | pcmd += sizeof (uint32_t); | 533 | pcmd += sizeof (uint32_t); |
530 | memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); | 534 | memcpy(pcmd, &vport->fc_sparam, sizeof (struct serv_parm)); |
531 | sp = (struct serv_parm *) pcmd; | 535 | sp = (struct serv_parm *) pcmd; |
532 | 536 | ||
533 | /* Setup CSPs accordingly for Fabric */ | 537 | /* Setup CSPs accordingly for Fabric */ |
@@ -543,14 +547,12 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
543 | 547 | ||
544 | tmo = phba->fc_ratov; | 548 | tmo = phba->fc_ratov; |
545 | phba->fc_ratov = LPFC_DISC_FLOGI_TMO; | 549 | phba->fc_ratov = LPFC_DISC_FLOGI_TMO; |
546 | lpfc_set_disctmo(phba); | 550 | lpfc_set_disctmo(vport); |
547 | phba->fc_ratov = tmo; | 551 | phba->fc_ratov = tmo; |
548 | 552 | ||
549 | phba->fc_stat.elsXmitFLOGI++; | 553 | phba->fc_stat.elsXmitFLOGI++; |
550 | elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; | 554 | elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi; |
551 | spin_lock_irq(phba->host->host_lock); | ||
552 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 555 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
553 | spin_unlock_irq(phba->host->host_lock); | ||
554 | if (rc == IOCB_ERROR) { | 556 | if (rc == IOCB_ERROR) { |
555 | lpfc_els_free_iocb(phba, elsiocb); | 557 | lpfc_els_free_iocb(phba, elsiocb); |
556 | return 1; | 558 | return 1; |
@@ -559,7 +561,7 @@ lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
559 | } | 561 | } |
560 | 562 | ||
561 | int | 563 | int |
562 | lpfc_els_abort_flogi(struct lpfc_hba * phba) | 564 | lpfc_els_abort_flogi(struct lpfc_hba *phba) |
563 | { | 565 | { |
564 | struct lpfc_sli_ring *pring; | 566 | struct lpfc_sli_ring *pring; |
565 | struct lpfc_iocbq *iocb, *next_iocb; | 567 | struct lpfc_iocbq *iocb, *next_iocb; |
@@ -577,62 +579,65 @@ lpfc_els_abort_flogi(struct lpfc_hba * phba) | |||
577 | * Check the txcmplq for an iocb that matches the nport the driver is | 579 | * Check the txcmplq for an iocb that matches the nport the driver is |
578 | * searching for. | 580 | * searching for. |
579 | */ | 581 | */ |
580 | spin_lock_irq(phba->host->host_lock); | 582 | spin_lock_irq(&phba->hbalock); |
581 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { | 583 | list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { |
582 | icmd = &iocb->iocb; | 584 | icmd = &iocb->iocb; |
583 | if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { | 585 | if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR && |
586 | icmd->un.elsreq64.bdl.ulpIoTag32) { | ||
584 | ndlp = (struct lpfc_nodelist *)(iocb->context1); | 587 | ndlp = (struct lpfc_nodelist *)(iocb->context1); |
585 | if (ndlp && (ndlp->nlp_DID == Fabric_DID)) | 588 | if (ndlp && (ndlp->nlp_DID == Fabric_DID)) |
586 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); | 589 | lpfc_sli_issue_abort_iotag(phba, pring, iocb); |
587 | } | 590 | } |
588 | } | 591 | } |
589 | spin_unlock_irq(phba->host->host_lock); | 592 | spin_unlock_irq(&phba->hbalock); |
590 | 593 | ||
591 | return 0; | 594 | return 0; |
592 | } | 595 | } |
593 | 596 | ||
594 | int | 597 | int |
595 | lpfc_initial_flogi(struct lpfc_hba *phba) | 598 | lpfc_initial_flogi(struct lpfc_vport *vport) |
596 | { | 599 | { |
600 | struct lpfc_hba *phba = vport->phba; | ||
597 | struct lpfc_nodelist *ndlp; | 601 | struct lpfc_nodelist *ndlp; |
598 | 602 | ||
599 | /* First look for the Fabric ndlp */ | 603 | /* First look for the Fabric ndlp */ |
600 | ndlp = lpfc_findnode_did(phba, Fabric_DID); | 604 | ndlp = lpfc_findnode_did(vport, Fabric_DID); |
601 | if (!ndlp) { | 605 | if (!ndlp) { |
602 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 606 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
603 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 607 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
604 | if (!ndlp) | 608 | if (!ndlp) |
605 | return 0; | 609 | return 0; |
606 | lpfc_nlp_init(phba, ndlp, Fabric_DID); | 610 | lpfc_nlp_init(vport, ndlp, Fabric_DID); |
607 | } else { | 611 | } else { |
608 | lpfc_dequeue_node(phba, ndlp); | 612 | lpfc_dequeue_node(vport, ndlp); |
609 | } | 613 | } |
610 | if (lpfc_issue_els_flogi(phba, ndlp, 0)) { | 614 | if (lpfc_issue_els_flogi(vport, ndlp, 0)) { |
611 | lpfc_nlp_put(ndlp); | 615 | lpfc_nlp_put(ndlp); |
612 | } | 616 | } |
613 | return 1; | 617 | return 1; |
614 | } | 618 | } |
615 | 619 | ||
616 | static void | 620 | static void |
617 | lpfc_more_plogi(struct lpfc_hba * phba) | 621 | lpfc_more_plogi(struct lpfc_vport *vport) |
618 | { | 622 | { |
619 | int sentplogi; | 623 | int sentplogi; |
624 | struct lpfc_hba *phba = vport->phba; | ||
620 | 625 | ||
621 | if (phba->num_disc_nodes) | 626 | if (vport->num_disc_nodes) |
622 | phba->num_disc_nodes--; | 627 | vport->num_disc_nodes--; |
623 | 628 | ||
624 | /* Continue discovery with <num_disc_nodes> PLOGIs to go */ | 629 | /* Continue discovery with <num_disc_nodes> PLOGIs to go */ |
625 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 630 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
626 | "%d:0232 Continue discovery with %d PLOGIs to go " | 631 | "%d:0232 Continue discovery with %d PLOGIs to go " |
627 | "Data: x%x x%x x%x\n", | 632 | "Data: x%x x%x x%x\n", |
628 | phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt, | 633 | phba->brd_no, vport->num_disc_nodes, |
629 | phba->fc_flag, phba->hba_state); | 634 | vport->fc_plogi_cnt, vport->fc_flag, vport->port_state); |
630 | 635 | ||
631 | /* Check to see if there are more PLOGIs to be sent */ | 636 | /* Check to see if there are more PLOGIs to be sent */ |
632 | if (phba->fc_flag & FC_NLP_MORE) { | 637 | if (vport->fc_flag & FC_NLP_MORE) |
633 | /* go thru NPR list and issue any remaining ELS PLOGIs */ | 638 | /* go thru NPR nodes and issue any remaining ELS PLOGIs */ |
634 | sentplogi = lpfc_els_disc_plogi(phba); | 639 | sentplogi = lpfc_els_disc_plogi(vport); |
635 | } | 640 | |
636 | return; | 641 | return; |
637 | } | 642 | } |
638 | 643 | ||
@@ -640,6 +645,7 @@ static struct lpfc_nodelist * | |||
640 | lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, | 645 | lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, |
641 | struct lpfc_nodelist *ndlp) | 646 | struct lpfc_nodelist *ndlp) |
642 | { | 647 | { |
648 | struct lpfc_vport *vport = ndlp->vport; | ||
643 | struct lpfc_nodelist *new_ndlp; | 649 | struct lpfc_nodelist *new_ndlp; |
644 | uint32_t *lp; | 650 | uint32_t *lp; |
645 | struct serv_parm *sp; | 651 | struct serv_parm *sp; |
@@ -659,43 +665,45 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, struct lpfc_dmabuf *prsp, | |||
659 | /* Now we find out if the NPort we are logging into, matches the WWPN | 665 | /* Now we find out if the NPort we are logging into, matches the WWPN |
660 | * we have for that ndlp. If not, we have some work to do. | 666 | * we have for that ndlp. If not, we have some work to do. |
661 | */ | 667 | */ |
662 | new_ndlp = lpfc_findnode_wwpn(phba, &sp->portName); | 668 | new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName); |
663 | 669 | ||
664 | if (new_ndlp == ndlp) | 670 | if (new_ndlp == ndlp) |
665 | return ndlp; | 671 | return ndlp; |
666 | 672 | ||
667 | if (!new_ndlp) { | 673 | if (!new_ndlp) { |
668 | rc = | 674 | rc = memcmp(&ndlp->nlp_portname, name, |
669 | memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)); | 675 | sizeof(struct lpfc_name)); |
670 | if (!rc) | 676 | if (!rc) |
671 | return ndlp; | 677 | return ndlp; |
672 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); | 678 | new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC); |
673 | if (!new_ndlp) | 679 | if (!new_ndlp) |
674 | return ndlp; | 680 | return ndlp; |
675 | 681 | ||
676 | lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID); | 682 | lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID); |
677 | } | 683 | } |
678 | 684 | ||
679 | lpfc_unreg_rpi(phba, new_ndlp); | 685 | lpfc_unreg_rpi(vport, new_ndlp); |
680 | new_ndlp->nlp_DID = ndlp->nlp_DID; | 686 | new_ndlp->nlp_DID = ndlp->nlp_DID; |
681 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; | 687 | new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; |
682 | lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state); | 688 | lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); |
683 | 689 | ||
684 | /* Move this back to NPR list */ | 690 | /* Move this back to NPR state */ |
685 | if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) | 691 | if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) |
686 | lpfc_drop_node(phba, ndlp); | 692 | lpfc_drop_node(vport, ndlp); |
687 | else { | 693 | else { |
688 | lpfc_unreg_rpi(phba, ndlp); | 694 | lpfc_unreg_rpi(vport, ndlp); |
689 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ | 695 | ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */ |
690 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 696 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
691 | } | 697 | } |
692 | return new_ndlp; | 698 | return new_ndlp; |
693 | } | 699 | } |
694 | 700 | ||
695 | static void | 701 | static void |
696 | lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 702 | lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
697 | struct lpfc_iocbq * rspiocb) | 703 | struct lpfc_iocbq *rspiocb) |
698 | { | 704 | { |
705 | struct lpfc_vport *vport = cmdiocb->vport; | ||
706 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
699 | IOCB_t *irsp; | 707 | IOCB_t *irsp; |
700 | struct lpfc_nodelist *ndlp; | 708 | struct lpfc_nodelist *ndlp; |
701 | struct lpfc_dmabuf *prsp; | 709 | struct lpfc_dmabuf *prsp; |
@@ -705,17 +713,17 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
705 | cmdiocb->context_un.rsp_iocb = rspiocb; | 713 | cmdiocb->context_un.rsp_iocb = rspiocb; |
706 | 714 | ||
707 | irsp = &rspiocb->iocb; | 715 | irsp = &rspiocb->iocb; |
708 | ndlp = lpfc_findnode_did(phba, irsp->un.elsreq64.remoteID); | 716 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); |
709 | if (!ndlp) | 717 | if (!ndlp) |
710 | goto out; | 718 | goto out; |
711 | 719 | ||
712 | /* Since ndlp can be freed in the disc state machine, note if this node | 720 | /* Since ndlp can be freed in the disc state machine, note if this node |
713 | * is being used during discovery. | 721 | * is being used during discovery. |
714 | */ | 722 | */ |
723 | spin_lock_irq(shost->host_lock); | ||
715 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | 724 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); |
716 | spin_lock_irq(phba->host->host_lock); | ||
717 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | 725 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; |
718 | spin_unlock_irq(phba->host->host_lock); | 726 | spin_unlock_irq(shost->host_lock); |
719 | rc = 0; | 727 | rc = 0; |
720 | 728 | ||
721 | /* PLOGI completes to NPort <nlp_DID> */ | 729 | /* PLOGI completes to NPort <nlp_DID> */ |
@@ -724,13 +732,13 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
724 | "Data: x%x x%x x%x x%x x%x\n", | 732 | "Data: x%x x%x x%x x%x x%x\n", |
725 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 733 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
726 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, | 734 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, |
727 | phba->num_disc_nodes); | 735 | vport->num_disc_nodes); |
728 | 736 | ||
729 | /* Check to see if link went down during discovery */ | 737 | /* Check to see if link went down during discovery */ |
730 | if (lpfc_els_chk_latt(phba)) { | 738 | if (lpfc_els_chk_latt(vport)) { |
731 | spin_lock_irq(phba->host->host_lock); | 739 | spin_lock_irq(shost->host_lock); |
732 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 740 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
733 | spin_unlock_irq(phba->host->host_lock); | 741 | spin_unlock_irq(shost->host_lock); |
734 | goto out; | 742 | goto out; |
735 | } | 743 | } |
736 | 744 | ||
@@ -743,9 +751,9 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
743 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { | 751 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { |
744 | /* ELS command is being retried */ | 752 | /* ELS command is being retried */ |
745 | if (disc) { | 753 | if (disc) { |
746 | spin_lock_irq(phba->host->host_lock); | 754 | spin_lock_irq(shost->host_lock); |
747 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 755 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
748 | spin_unlock_irq(phba->host->host_lock); | 756 | spin_unlock_irq(shost->host_lock); |
749 | } | 757 | } |
750 | goto out; | 758 | goto out; |
751 | } | 759 | } |
@@ -758,7 +766,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
758 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 766 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
759 | rc = NLP_STE_FREED_NODE; | 767 | rc = NLP_STE_FREED_NODE; |
760 | } else { | 768 | } else { |
761 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 769 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
762 | NLP_EVT_CMPL_PLOGI); | 770 | NLP_EVT_CMPL_PLOGI); |
763 | } | 771 | } |
764 | } else { | 772 | } else { |
@@ -767,32 +775,32 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
767 | cmdiocb->context2)->list.next, | 775 | cmdiocb->context2)->list.next, |
768 | struct lpfc_dmabuf, list); | 776 | struct lpfc_dmabuf, list); |
769 | ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp); | 777 | ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp); |
770 | rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 778 | rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
771 | NLP_EVT_CMPL_PLOGI); | 779 | NLP_EVT_CMPL_PLOGI); |
772 | } | 780 | } |
773 | 781 | ||
774 | if (disc && phba->num_disc_nodes) { | 782 | if (disc && vport->num_disc_nodes) { |
775 | /* Check to see if there are more PLOGIs to be sent */ | 783 | /* Check to see if there are more PLOGIs to be sent */ |
776 | lpfc_more_plogi(phba); | 784 | lpfc_more_plogi(vport); |
777 | 785 | ||
778 | if (phba->num_disc_nodes == 0) { | 786 | if (vport->num_disc_nodes == 0) { |
779 | spin_lock_irq(phba->host->host_lock); | 787 | spin_lock_irq(shost->host_lock); |
780 | phba->fc_flag &= ~FC_NDISC_ACTIVE; | 788 | vport->fc_flag &= ~FC_NDISC_ACTIVE; |
781 | spin_unlock_irq(phba->host->host_lock); | 789 | spin_unlock_irq(shost->host_lock); |
782 | 790 | ||
783 | lpfc_can_disctmo(phba); | 791 | lpfc_can_disctmo(vport); |
784 | if (phba->fc_flag & FC_RSCN_MODE) { | 792 | if (vport->fc_flag & FC_RSCN_MODE) { |
785 | /* | 793 | /* |
786 | * Check to see if more RSCNs came in while | 794 | * Check to see if more RSCNs came in while |
787 | * we were processing this one. | 795 | * we were processing this one. |
788 | */ | 796 | */ |
789 | if ((phba->fc_rscn_id_cnt == 0) && | 797 | if ((vport->fc_rscn_id_cnt == 0) && |
790 | (!(phba->fc_flag & FC_RSCN_DISCOVERY))) { | 798 | (!(vport->fc_flag & FC_RSCN_DISCOVERY))) { |
791 | spin_lock_irq(phba->host->host_lock); | 799 | spin_lock_irq(shost->host_lock); |
792 | phba->fc_flag &= ~FC_RSCN_MODE; | 800 | vport->fc_flag &= ~FC_RSCN_MODE; |
793 | spin_unlock_irq(phba->host->host_lock); | 801 | spin_unlock_irq(shost->host_lock); |
794 | } else { | 802 | } else { |
795 | lpfc_els_handle_rscn(phba); | 803 | lpfc_els_handle_rscn(vport); |
796 | } | 804 | } |
797 | } | 805 | } |
798 | } | 806 | } |
@@ -804,8 +812,9 @@ out: | |||
804 | } | 812 | } |
805 | 813 | ||
806 | int | 814 | int |
807 | lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) | 815 | lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) |
808 | { | 816 | { |
817 | struct lpfc_hba *phba = vport->phba; | ||
809 | struct serv_parm *sp; | 818 | struct serv_parm *sp; |
810 | IOCB_t *icmd; | 819 | IOCB_t *icmd; |
811 | struct lpfc_iocbq *elsiocb; | 820 | struct lpfc_iocbq *elsiocb; |
@@ -818,8 +827,8 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) | |||
818 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 827 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
819 | 828 | ||
820 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); | 829 | cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm)); |
821 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did, | 830 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did, |
822 | ELS_CMD_PLOGI); | 831 | ELS_CMD_PLOGI); |
823 | if (!elsiocb) | 832 | if (!elsiocb) |
824 | return 1; | 833 | return 1; |
825 | 834 | ||
@@ -829,7 +838,7 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) | |||
829 | /* For PLOGI request, remainder of payload is service parameters */ | 838 | /* For PLOGI request, remainder of payload is service parameters */ |
830 | *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI; | 839 | *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI; |
831 | pcmd += sizeof (uint32_t); | 840 | pcmd += sizeof (uint32_t); |
832 | memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); | 841 | memcpy(pcmd, &vport->fc_sparam, sizeof (struct serv_parm)); |
833 | sp = (struct serv_parm *) pcmd; | 842 | sp = (struct serv_parm *) pcmd; |
834 | 843 | ||
835 | if (sp->cmn.fcphLow < FC_PH_4_3) | 844 | if (sp->cmn.fcphLow < FC_PH_4_3) |
@@ -840,20 +849,19 @@ lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry) | |||
840 | 849 | ||
841 | phba->fc_stat.elsXmitPLOGI++; | 850 | phba->fc_stat.elsXmitPLOGI++; |
842 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; | 851 | elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; |
843 | spin_lock_irq(phba->host->host_lock); | ||
844 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 852 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
845 | spin_unlock_irq(phba->host->host_lock); | ||
846 | lpfc_els_free_iocb(phba, elsiocb); | 853 | lpfc_els_free_iocb(phba, elsiocb); |
847 | return 1; | 854 | return 1; |
848 | } | 855 | } |
849 | spin_unlock_irq(phba->host->host_lock); | ||
850 | return 0; | 856 | return 0; |
851 | } | 857 | } |
852 | 858 | ||
853 | static void | 859 | static void |
854 | lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 860 | lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
855 | struct lpfc_iocbq * rspiocb) | 861 | struct lpfc_iocbq *rspiocb) |
856 | { | 862 | { |
863 | struct lpfc_vport *vport = cmdiocb->vport; | ||
864 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
857 | IOCB_t *irsp; | 865 | IOCB_t *irsp; |
858 | struct lpfc_sli *psli; | 866 | struct lpfc_sli *psli; |
859 | struct lpfc_nodelist *ndlp; | 867 | struct lpfc_nodelist *ndlp; |
@@ -864,9 +872,9 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
864 | 872 | ||
865 | irsp = &(rspiocb->iocb); | 873 | irsp = &(rspiocb->iocb); |
866 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 874 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
867 | spin_lock_irq(phba->host->host_lock); | 875 | spin_lock_irq(shost->host_lock); |
868 | ndlp->nlp_flag &= ~NLP_PRLI_SND; | 876 | ndlp->nlp_flag &= ~NLP_PRLI_SND; |
869 | spin_unlock_irq(phba->host->host_lock); | 877 | spin_unlock_irq(shost->host_lock); |
870 | 878 | ||
871 | /* PRLI completes to NPort <nlp_DID> */ | 879 | /* PRLI completes to NPort <nlp_DID> */ |
872 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 880 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -874,11 +882,11 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
874 | "Data: x%x x%x x%x x%x\n", | 882 | "Data: x%x x%x x%x x%x\n", |
875 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 883 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
876 | irsp->un.ulpWord[4], irsp->ulpTimeout, | 884 | irsp->un.ulpWord[4], irsp->ulpTimeout, |
877 | phba->num_disc_nodes); | 885 | vport->num_disc_nodes); |
878 | 886 | ||
879 | phba->fc_prli_sent--; | 887 | vport->fc_prli_sent--; |
880 | /* Check to see if link went down during discovery */ | 888 | /* Check to see if link went down during discovery */ |
881 | if (lpfc_els_chk_latt(phba)) | 889 | if (lpfc_els_chk_latt(vport)) |
882 | goto out; | 890 | goto out; |
883 | 891 | ||
884 | if (irsp->ulpStatus) { | 892 | if (irsp->ulpStatus) { |
@@ -895,12 +903,13 @@ lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
895 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 903 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
896 | goto out; | 904 | goto out; |
897 | } else { | 905 | } else { |
898 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 906 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
899 | NLP_EVT_CMPL_PRLI); | 907 | NLP_EVT_CMPL_PRLI); |
900 | } | 908 | } |
901 | } else { | 909 | } else { |
902 | /* Good status, call state machine */ | 910 | /* Good status, call state machine */ |
903 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI); | 911 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
912 | NLP_EVT_CMPL_PRLI); | ||
904 | } | 913 | } |
905 | 914 | ||
906 | out: | 915 | out: |
@@ -909,9 +918,11 @@ out: | |||
909 | } | 918 | } |
910 | 919 | ||
911 | int | 920 | int |
912 | lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 921 | lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
913 | uint8_t retry) | 922 | uint8_t retry) |
914 | { | 923 | { |
924 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
925 | struct lpfc_hba *phba = vport->phba; | ||
915 | PRLI *npr; | 926 | PRLI *npr; |
916 | IOCB_t *icmd; | 927 | IOCB_t *icmd; |
917 | struct lpfc_iocbq *elsiocb; | 928 | struct lpfc_iocbq *elsiocb; |
@@ -924,8 +935,8 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
924 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 935 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
925 | 936 | ||
926 | cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); | 937 | cmdsize = (sizeof (uint32_t) + sizeof (PRLI)); |
927 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 938 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
928 | ndlp->nlp_DID, ELS_CMD_PRLI); | 939 | ndlp->nlp_DID, ELS_CMD_PRLI); |
929 | if (!elsiocb) | 940 | if (!elsiocb) |
930 | return 1; | 941 | return 1; |
931 | 942 | ||
@@ -957,79 +968,80 @@ lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
957 | 968 | ||
958 | phba->fc_stat.elsXmitPRLI++; | 969 | phba->fc_stat.elsXmitPRLI++; |
959 | elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; | 970 | elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; |
960 | spin_lock_irq(phba->host->host_lock); | 971 | spin_lock_irq(shost->host_lock); |
961 | ndlp->nlp_flag |= NLP_PRLI_SND; | 972 | ndlp->nlp_flag |= NLP_PRLI_SND; |
973 | spin_unlock_irq(shost->host_lock); | ||
962 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 974 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
975 | spin_lock_irq(shost->host_lock); | ||
963 | ndlp->nlp_flag &= ~NLP_PRLI_SND; | 976 | ndlp->nlp_flag &= ~NLP_PRLI_SND; |
964 | spin_unlock_irq(phba->host->host_lock); | 977 | spin_unlock_irq(shost->host_lock); |
965 | lpfc_els_free_iocb(phba, elsiocb); | 978 | lpfc_els_free_iocb(phba, elsiocb); |
966 | return 1; | 979 | return 1; |
967 | } | 980 | } |
968 | spin_unlock_irq(phba->host->host_lock); | 981 | vport->fc_prli_sent++; |
969 | phba->fc_prli_sent++; | ||
970 | return 0; | 982 | return 0; |
971 | } | 983 | } |
972 | 984 | ||
973 | static void | 985 | static void |
974 | lpfc_more_adisc(struct lpfc_hba * phba) | 986 | lpfc_more_adisc(struct lpfc_vport *vport) |
975 | { | 987 | { |
976 | int sentadisc; | 988 | int sentadisc; |
989 | struct lpfc_hba *phba = vport->phba; | ||
977 | 990 | ||
978 | if (phba->num_disc_nodes) | 991 | if (vport->num_disc_nodes) |
979 | phba->num_disc_nodes--; | 992 | vport->num_disc_nodes--; |
980 | 993 | ||
981 | /* Continue discovery with <num_disc_nodes> ADISCs to go */ | 994 | /* Continue discovery with <num_disc_nodes> ADISCs to go */ |
982 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 995 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
983 | "%d:0210 Continue discovery with %d ADISCs to go " | 996 | "%d:0210 Continue discovery with %d ADISCs to go " |
984 | "Data: x%x x%x x%x\n", | 997 | "Data: x%x x%x x%x\n", |
985 | phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt, | 998 | phba->brd_no, vport->num_disc_nodes, |
986 | phba->fc_flag, phba->hba_state); | 999 | vport->fc_adisc_cnt, vport->fc_flag, vport->port_state); |
987 | 1000 | ||
988 | /* Check to see if there are more ADISCs to be sent */ | 1001 | /* Check to see if there are more ADISCs to be sent */ |
989 | if (phba->fc_flag & FC_NLP_MORE) { | 1002 | if (vport->fc_flag & FC_NLP_MORE) { |
990 | lpfc_set_disctmo(phba); | 1003 | lpfc_set_disctmo(vport); |
991 | 1004 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ | |
992 | /* go thru NPR list and issue any remaining ELS ADISCs */ | 1005 | sentadisc = lpfc_els_disc_adisc(vport); |
993 | sentadisc = lpfc_els_disc_adisc(phba); | ||
994 | } | 1006 | } |
995 | return; | 1007 | return; |
996 | } | 1008 | } |
997 | 1009 | ||
998 | static void | 1010 | static void |
999 | lpfc_rscn_disc(struct lpfc_hba * phba) | 1011 | lpfc_rscn_disc(struct lpfc_vport *vport) |
1000 | { | 1012 | { |
1013 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1014 | |||
1001 | /* RSCN discovery */ | 1015 | /* RSCN discovery */ |
1002 | /* go thru NPR list and issue ELS PLOGIs */ | 1016 | /* go thru NPR nodes and issue ELS PLOGIs */ |
1003 | if (phba->fc_npr_cnt) { | 1017 | if (vport->fc_npr_cnt) |
1004 | if (lpfc_els_disc_plogi(phba)) | 1018 | if (lpfc_els_disc_plogi(vport)) |
1005 | return; | 1019 | return; |
1006 | } | 1020 | |
1007 | if (phba->fc_flag & FC_RSCN_MODE) { | 1021 | if (vport->fc_flag & FC_RSCN_MODE) { |
1008 | /* Check to see if more RSCNs came in while we were | 1022 | /* Check to see if more RSCNs came in while we were |
1009 | * processing this one. | 1023 | * processing this one. |
1010 | */ | 1024 | */ |
1011 | if ((phba->fc_rscn_id_cnt == 0) && | 1025 | if ((vport->fc_rscn_id_cnt == 0) && |
1012 | (!(phba->fc_flag & FC_RSCN_DISCOVERY))) { | 1026 | (!(vport->fc_flag & FC_RSCN_DISCOVERY))) { |
1013 | spin_lock_irq(phba->host->host_lock); | 1027 | spin_lock_irq(shost->host_lock); |
1014 | phba->fc_flag &= ~FC_RSCN_MODE; | 1028 | vport->fc_flag &= ~FC_RSCN_MODE; |
1015 | spin_unlock_irq(phba->host->host_lock); | 1029 | spin_unlock_irq(shost->host_lock); |
1016 | } else { | 1030 | } else { |
1017 | lpfc_els_handle_rscn(phba); | 1031 | lpfc_els_handle_rscn(vport); |
1018 | } | 1032 | } |
1019 | } | 1033 | } |
1020 | } | 1034 | } |
1021 | 1035 | ||
1022 | static void | 1036 | static void |
1023 | lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1037 | lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1024 | struct lpfc_iocbq * rspiocb) | 1038 | struct lpfc_iocbq *rspiocb) |
1025 | { | 1039 | { |
1040 | struct lpfc_vport *vport = cmdiocb->vport; | ||
1041 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1026 | IOCB_t *irsp; | 1042 | IOCB_t *irsp; |
1027 | struct lpfc_sli *psli; | ||
1028 | struct lpfc_nodelist *ndlp; | 1043 | struct lpfc_nodelist *ndlp; |
1029 | LPFC_MBOXQ_t *mbox; | 1044 | int disc; |
1030 | int disc, rc; | ||
1031 | |||
1032 | psli = &phba->sli; | ||
1033 | 1045 | ||
1034 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 1046 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
1035 | cmdiocb->context_un.rsp_iocb = rspiocb; | 1047 | cmdiocb->context_un.rsp_iocb = rspiocb; |
@@ -1040,10 +1052,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1040 | /* Since ndlp can be freed in the disc state machine, note if this node | 1052 | /* Since ndlp can be freed in the disc state machine, note if this node |
1041 | * is being used during discovery. | 1053 | * is being used during discovery. |
1042 | */ | 1054 | */ |
1055 | spin_lock_irq(shost->host_lock); | ||
1043 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); | 1056 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); |
1044 | spin_lock_irq(phba->host->host_lock); | ||
1045 | ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); | 1057 | ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); |
1046 | spin_unlock_irq(phba->host->host_lock); | 1058 | spin_unlock_irq(shost->host_lock); |
1047 | 1059 | ||
1048 | /* ADISC completes to NPort <nlp_DID> */ | 1060 | /* ADISC completes to NPort <nlp_DID> */ |
1049 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1061 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -1051,13 +1063,13 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1051 | "Data: x%x x%x x%x x%x x%x\n", | 1063 | "Data: x%x x%x x%x x%x x%x\n", |
1052 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 1064 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
1053 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, | 1065 | irsp->un.ulpWord[4], irsp->ulpTimeout, disc, |
1054 | phba->num_disc_nodes); | 1066 | vport->num_disc_nodes); |
1055 | 1067 | ||
1056 | /* Check to see if link went down during discovery */ | 1068 | /* Check to see if link went down during discovery */ |
1057 | if (lpfc_els_chk_latt(phba)) { | 1069 | if (lpfc_els_chk_latt(vport)) { |
1058 | spin_lock_irq(phba->host->host_lock); | 1070 | spin_lock_irq(shost->host_lock); |
1059 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1071 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
1060 | spin_unlock_irq(phba->host->host_lock); | 1072 | spin_unlock_irq(shost->host_lock); |
1061 | goto out; | 1073 | goto out; |
1062 | } | 1074 | } |
1063 | 1075 | ||
@@ -1066,10 +1078,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1066 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { | 1078 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { |
1067 | /* ELS command is being retried */ | 1079 | /* ELS command is being retried */ |
1068 | if (disc) { | 1080 | if (disc) { |
1069 | spin_lock_irq(phba->host->host_lock); | 1081 | spin_lock_irq(shost->host_lock); |
1070 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; | 1082 | ndlp->nlp_flag |= NLP_NPR_2B_DISC; |
1071 | spin_unlock_irq(phba->host->host_lock); | 1083 | spin_unlock_irq(shost->host_lock); |
1072 | lpfc_set_disctmo(phba); | 1084 | lpfc_set_disctmo(vport); |
1073 | } | 1085 | } |
1074 | goto out; | 1086 | goto out; |
1075 | } | 1087 | } |
@@ -1079,54 +1091,30 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1079 | ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && | 1091 | ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) && |
1080 | (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) && | 1092 | (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) && |
1081 | (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) { | 1093 | (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) { |
1082 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 1094 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1083 | NLP_EVT_CMPL_ADISC); | 1095 | NLP_EVT_CMPL_ADISC); |
1084 | } | 1096 | } |
1085 | } else { | 1097 | } else { |
1086 | /* Good status, call state machine */ | 1098 | /* Good status, call state machine */ |
1087 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 1099 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1088 | NLP_EVT_CMPL_ADISC); | 1100 | NLP_EVT_CMPL_ADISC); |
1089 | } | 1101 | } |
1090 | 1102 | ||
1091 | if (disc && phba->num_disc_nodes) { | 1103 | if (disc && vport->num_disc_nodes) { |
1092 | /* Check to see if there are more ADISCs to be sent */ | 1104 | /* Check to see if there are more ADISCs to be sent */ |
1093 | lpfc_more_adisc(phba); | 1105 | lpfc_more_adisc(vport); |
1094 | 1106 | ||
1095 | /* Check to see if we are done with ADISC authentication */ | 1107 | /* Check to see if we are done with ADISC authentication */ |
1096 | if (phba->num_disc_nodes == 0) { | 1108 | if (vport->num_disc_nodes == 0) { |
1097 | lpfc_can_disctmo(phba); | 1109 | lpfc_can_disctmo(vport); |
1098 | /* If we get here, there is nothing left to wait for */ | 1110 | /* If we get here, there is nothing left to wait for */ |
1099 | if ((phba->hba_state < LPFC_HBA_READY) && | 1111 | if (vport->port_state < LPFC_VPORT_READY && |
1100 | (phba->hba_state != LPFC_CLEAR_LA)) { | 1112 | phba->link_state != LPFC_CLEAR_LA) { |
1101 | /* Link up discovery */ | 1113 | if (vport->port_type == LPFC_PHYSICAL_PORT) { |
1102 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, | 1114 | lpfc_issue_clear_la(phba, vport); |
1103 | GFP_KERNEL))) { | ||
1104 | phba->hba_state = LPFC_CLEAR_LA; | ||
1105 | lpfc_clear_la(phba, mbox); | ||
1106 | mbox->mbox_cmpl = | ||
1107 | lpfc_mbx_cmpl_clear_la; | ||
1108 | rc = lpfc_sli_issue_mbox | ||
1109 | (phba, mbox, | ||
1110 | (MBX_NOWAIT | MBX_STOP_IOCB)); | ||
1111 | if (rc == MBX_NOT_FINISHED) { | ||
1112 | mempool_free(mbox, | ||
1113 | phba->mbox_mem_pool); | ||
1114 | lpfc_disc_flush_list(phba); | ||
1115 | psli->ring[(psli->extra_ring)]. | ||
1116 | flag &= | ||
1117 | ~LPFC_STOP_IOCB_EVENT; | ||
1118 | psli->ring[(psli->fcp_ring)]. | ||
1119 | flag &= | ||
1120 | ~LPFC_STOP_IOCB_EVENT; | ||
1121 | psli->ring[(psli->next_ring)]. | ||
1122 | flag &= | ||
1123 | ~LPFC_STOP_IOCB_EVENT; | ||
1124 | phba->hba_state = | ||
1125 | LPFC_HBA_READY; | ||
1126 | } | ||
1127 | } | 1115 | } |
1128 | } else { | 1116 | } else { |
1129 | lpfc_rscn_disc(phba); | 1117 | lpfc_rscn_disc(vport); |
1130 | } | 1118 | } |
1131 | } | 1119 | } |
1132 | } | 1120 | } |
@@ -1136,23 +1124,22 @@ out: | |||
1136 | } | 1124 | } |
1137 | 1125 | ||
1138 | int | 1126 | int |
1139 | lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 1127 | lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1140 | uint8_t retry) | 1128 | uint8_t retry) |
1141 | { | 1129 | { |
1130 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1131 | struct lpfc_hba *phba = vport->phba; | ||
1142 | ADISC *ap; | 1132 | ADISC *ap; |
1143 | IOCB_t *icmd; | 1133 | IOCB_t *icmd; |
1144 | struct lpfc_iocbq *elsiocb; | 1134 | struct lpfc_iocbq *elsiocb; |
1145 | struct lpfc_sli_ring *pring; | 1135 | struct lpfc_sli *psli = &phba->sli; |
1146 | struct lpfc_sli *psli; | 1136 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
1147 | uint8_t *pcmd; | 1137 | uint8_t *pcmd; |
1148 | uint16_t cmdsize; | 1138 | uint16_t cmdsize; |
1149 | 1139 | ||
1150 | psli = &phba->sli; | ||
1151 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | ||
1152 | |||
1153 | cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); | 1140 | cmdsize = (sizeof (uint32_t) + sizeof (ADISC)); |
1154 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 1141 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1155 | ndlp->nlp_DID, ELS_CMD_ADISC); | 1142 | ndlp->nlp_DID, ELS_CMD_ADISC); |
1156 | if (!elsiocb) | 1143 | if (!elsiocb) |
1157 | return 1; | 1144 | return 1; |
1158 | 1145 | ||
@@ -1166,41 +1153,43 @@ lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1166 | /* Fill in ADISC payload */ | 1153 | /* Fill in ADISC payload */ |
1167 | ap = (ADISC *) pcmd; | 1154 | ap = (ADISC *) pcmd; |
1168 | ap->hardAL_PA = phba->fc_pref_ALPA; | 1155 | ap->hardAL_PA = phba->fc_pref_ALPA; |
1169 | memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name)); | 1156 | memcpy(&ap->portName, &vport->fc_portname, sizeof (struct lpfc_name)); |
1170 | memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); | 1157 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof (struct lpfc_name)); |
1171 | ap->DID = be32_to_cpu(phba->fc_myDID); | 1158 | ap->DID = be32_to_cpu(vport->fc_myDID); |
1172 | 1159 | ||
1173 | phba->fc_stat.elsXmitADISC++; | 1160 | phba->fc_stat.elsXmitADISC++; |
1174 | elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; | 1161 | elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; |
1175 | spin_lock_irq(phba->host->host_lock); | 1162 | spin_lock_irq(shost->host_lock); |
1176 | ndlp->nlp_flag |= NLP_ADISC_SND; | 1163 | ndlp->nlp_flag |= NLP_ADISC_SND; |
1164 | spin_unlock_irq(shost->host_lock); | ||
1177 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1165 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1166 | spin_lock_irq(shost->host_lock); | ||
1178 | ndlp->nlp_flag &= ~NLP_ADISC_SND; | 1167 | ndlp->nlp_flag &= ~NLP_ADISC_SND; |
1179 | spin_unlock_irq(phba->host->host_lock); | 1168 | spin_unlock_irq(shost->host_lock); |
1180 | lpfc_els_free_iocb(phba, elsiocb); | 1169 | lpfc_els_free_iocb(phba, elsiocb); |
1181 | return 1; | 1170 | return 1; |
1182 | } | 1171 | } |
1183 | spin_unlock_irq(phba->host->host_lock); | ||
1184 | return 0; | 1172 | return 0; |
1185 | } | 1173 | } |
1186 | 1174 | ||
1187 | static void | 1175 | static void |
1188 | lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1176 | lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1189 | struct lpfc_iocbq * rspiocb) | 1177 | struct lpfc_iocbq *rspiocb) |
1190 | { | 1178 | { |
1179 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1180 | struct lpfc_vport *vport = ndlp->vport; | ||
1181 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1191 | IOCB_t *irsp; | 1182 | IOCB_t *irsp; |
1192 | struct lpfc_sli *psli; | 1183 | struct lpfc_sli *psli; |
1193 | struct lpfc_nodelist *ndlp; | ||
1194 | 1184 | ||
1195 | psli = &phba->sli; | 1185 | psli = &phba->sli; |
1196 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 1186 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
1197 | cmdiocb->context_un.rsp_iocb = rspiocb; | 1187 | cmdiocb->context_un.rsp_iocb = rspiocb; |
1198 | 1188 | ||
1199 | irsp = &(rspiocb->iocb); | 1189 | irsp = &(rspiocb->iocb); |
1200 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | 1190 | spin_lock_irq(shost->host_lock); |
1201 | spin_lock_irq(phba->host->host_lock); | ||
1202 | ndlp->nlp_flag &= ~NLP_LOGO_SND; | 1191 | ndlp->nlp_flag &= ~NLP_LOGO_SND; |
1203 | spin_unlock_irq(phba->host->host_lock); | 1192 | spin_unlock_irq(shost->host_lock); |
1204 | 1193 | ||
1205 | /* LOGO completes to NPort <nlp_DID> */ | 1194 | /* LOGO completes to NPort <nlp_DID> */ |
1206 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1195 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -1208,18 +1197,17 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1208 | "Data: x%x x%x x%x x%x\n", | 1197 | "Data: x%x x%x x%x x%x\n", |
1209 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, | 1198 | phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus, |
1210 | irsp->un.ulpWord[4], irsp->ulpTimeout, | 1199 | irsp->un.ulpWord[4], irsp->ulpTimeout, |
1211 | phba->num_disc_nodes); | 1200 | vport->num_disc_nodes); |
1212 | 1201 | ||
1213 | /* Check to see if link went down during discovery */ | 1202 | /* Check to see if link went down during discovery */ |
1214 | if (lpfc_els_chk_latt(phba)) | 1203 | if (lpfc_els_chk_latt(vport)) |
1215 | goto out; | 1204 | goto out; |
1216 | 1205 | ||
1217 | if (irsp->ulpStatus) { | 1206 | if (irsp->ulpStatus) { |
1218 | /* Check for retry */ | 1207 | /* Check for retry */ |
1219 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { | 1208 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
1220 | /* ELS command is being retried */ | 1209 | /* ELS command is being retried */ |
1221 | goto out; | 1210 | goto out; |
1222 | } | ||
1223 | /* LOGO failed */ | 1211 | /* LOGO failed */ |
1224 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ | 1212 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
1225 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 1213 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && |
@@ -1228,14 +1216,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1228 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { | 1216 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) { |
1229 | goto out; | 1217 | goto out; |
1230 | } else { | 1218 | } else { |
1231 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, | 1219 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1232 | NLP_EVT_CMPL_LOGO); | 1220 | NLP_EVT_CMPL_LOGO); |
1233 | } | 1221 | } |
1234 | } else { | 1222 | } else { |
1235 | /* Good status, call state machine. | 1223 | /* Good status, call state machine. |
1236 | * This will unregister the rpi if needed. | 1224 | * This will unregister the rpi if needed. |
1237 | */ | 1225 | */ |
1238 | lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); | 1226 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
1227 | NLP_EVT_CMPL_LOGO); | ||
1239 | } | 1228 | } |
1240 | 1229 | ||
1241 | out: | 1230 | out: |
@@ -1244,9 +1233,11 @@ out: | |||
1244 | } | 1233 | } |
1245 | 1234 | ||
1246 | int | 1235 | int |
1247 | lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | 1236 | lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1248 | uint8_t retry) | 1237 | uint8_t retry) |
1249 | { | 1238 | { |
1239 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1240 | struct lpfc_hba *phba = vport->phba; | ||
1250 | IOCB_t *icmd; | 1241 | IOCB_t *icmd; |
1251 | struct lpfc_iocbq *elsiocb; | 1242 | struct lpfc_iocbq *elsiocb; |
1252 | struct lpfc_sli_ring *pring; | 1243 | struct lpfc_sli_ring *pring; |
@@ -1258,8 +1249,8 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1258 | pring = &psli->ring[LPFC_ELS_RING]; | 1249 | pring = &psli->ring[LPFC_ELS_RING]; |
1259 | 1250 | ||
1260 | cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name); | 1251 | cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name); |
1261 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 1252 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
1262 | ndlp->nlp_DID, ELS_CMD_LOGO); | 1253 | ndlp->nlp_DID, ELS_CMD_LOGO); |
1263 | if (!elsiocb) | 1254 | if (!elsiocb) |
1264 | return 1; | 1255 | return 1; |
1265 | 1256 | ||
@@ -1269,28 +1260,30 @@ lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, | |||
1269 | pcmd += sizeof (uint32_t); | 1260 | pcmd += sizeof (uint32_t); |
1270 | 1261 | ||
1271 | /* Fill in LOGO payload */ | 1262 | /* Fill in LOGO payload */ |
1272 | *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID); | 1263 | *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID); |
1273 | pcmd += sizeof (uint32_t); | 1264 | pcmd += sizeof (uint32_t); |
1274 | memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name)); | 1265 | memcpy(pcmd, &vport->fc_portname, sizeof (struct lpfc_name)); |
1275 | 1266 | ||
1276 | phba->fc_stat.elsXmitLOGO++; | 1267 | phba->fc_stat.elsXmitLOGO++; |
1277 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; | 1268 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; |
1278 | spin_lock_irq(phba->host->host_lock); | 1269 | spin_lock_irq(shost->host_lock); |
1279 | ndlp->nlp_flag |= NLP_LOGO_SND; | 1270 | ndlp->nlp_flag |= NLP_LOGO_SND; |
1271 | spin_unlock_irq(shost->host_lock); | ||
1280 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1272 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1273 | spin_lock_irq(shost->host_lock); | ||
1281 | ndlp->nlp_flag &= ~NLP_LOGO_SND; | 1274 | ndlp->nlp_flag &= ~NLP_LOGO_SND; |
1282 | spin_unlock_irq(phba->host->host_lock); | 1275 | spin_unlock_irq(shost->host_lock); |
1283 | lpfc_els_free_iocb(phba, elsiocb); | 1276 | lpfc_els_free_iocb(phba, elsiocb); |
1284 | return 1; | 1277 | return 1; |
1285 | } | 1278 | } |
1286 | spin_unlock_irq(phba->host->host_lock); | ||
1287 | return 0; | 1279 | return 0; |
1288 | } | 1280 | } |
1289 | 1281 | ||
1290 | static void | 1282 | static void |
1291 | lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1283 | lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1292 | struct lpfc_iocbq * rspiocb) | 1284 | struct lpfc_iocbq *rspiocb) |
1293 | { | 1285 | { |
1286 | struct lpfc_vport *vport = cmdiocb->vport; | ||
1294 | IOCB_t *irsp; | 1287 | IOCB_t *irsp; |
1295 | 1288 | ||
1296 | irsp = &rspiocb->iocb; | 1289 | irsp = &rspiocb->iocb; |
@@ -1305,14 +1298,15 @@ lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1305 | irsp->un.ulpWord[4], irsp->ulpTimeout); | 1298 | irsp->un.ulpWord[4], irsp->ulpTimeout); |
1306 | 1299 | ||
1307 | /* Check to see if link went down during discovery */ | 1300 | /* Check to see if link went down during discovery */ |
1308 | lpfc_els_chk_latt(phba); | 1301 | lpfc_els_chk_latt(vport); |
1309 | lpfc_els_free_iocb(phba, cmdiocb); | 1302 | lpfc_els_free_iocb(phba, cmdiocb); |
1310 | return; | 1303 | return; |
1311 | } | 1304 | } |
1312 | 1305 | ||
1313 | int | 1306 | int |
1314 | lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | 1307 | lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) |
1315 | { | 1308 | { |
1309 | struct lpfc_hba *phba = vport->phba; | ||
1316 | IOCB_t *icmd; | 1310 | IOCB_t *icmd; |
1317 | struct lpfc_iocbq *elsiocb; | 1311 | struct lpfc_iocbq *elsiocb; |
1318 | struct lpfc_sli_ring *pring; | 1312 | struct lpfc_sli_ring *pring; |
@@ -1328,10 +1322,11 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1328 | if (!ndlp) | 1322 | if (!ndlp) |
1329 | return 1; | 1323 | return 1; |
1330 | 1324 | ||
1331 | lpfc_nlp_init(phba, ndlp, nportid); | 1325 | lpfc_nlp_init(vport, ndlp, nportid); |
1326 | |||
1327 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | ||
1328 | ndlp->nlp_DID, ELS_CMD_SCR); | ||
1332 | 1329 | ||
1333 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | ||
1334 | ndlp->nlp_DID, ELS_CMD_SCR); | ||
1335 | if (!elsiocb) { | 1330 | if (!elsiocb) { |
1336 | lpfc_nlp_put(ndlp); | 1331 | lpfc_nlp_put(ndlp); |
1337 | return 1; | 1332 | return 1; |
@@ -1349,21 +1344,19 @@ lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1349 | 1344 | ||
1350 | phba->fc_stat.elsXmitSCR++; | 1345 | phba->fc_stat.elsXmitSCR++; |
1351 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1346 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
1352 | spin_lock_irq(phba->host->host_lock); | ||
1353 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1347 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1354 | spin_unlock_irq(phba->host->host_lock); | ||
1355 | lpfc_nlp_put(ndlp); | 1348 | lpfc_nlp_put(ndlp); |
1356 | lpfc_els_free_iocb(phba, elsiocb); | 1349 | lpfc_els_free_iocb(phba, elsiocb); |
1357 | return 1; | 1350 | return 1; |
1358 | } | 1351 | } |
1359 | spin_unlock_irq(phba->host->host_lock); | ||
1360 | lpfc_nlp_put(ndlp); | 1352 | lpfc_nlp_put(ndlp); |
1361 | return 0; | 1353 | return 0; |
1362 | } | 1354 | } |
1363 | 1355 | ||
1364 | static int | 1356 | static int |
1365 | lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | 1357 | lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) |
1366 | { | 1358 | { |
1359 | struct lpfc_hba *phba = vport->phba; | ||
1367 | IOCB_t *icmd; | 1360 | IOCB_t *icmd; |
1368 | struct lpfc_iocbq *elsiocb; | 1361 | struct lpfc_iocbq *elsiocb; |
1369 | struct lpfc_sli_ring *pring; | 1362 | struct lpfc_sli_ring *pring; |
@@ -1381,10 +1374,11 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1381 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 1374 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
1382 | if (!ndlp) | 1375 | if (!ndlp) |
1383 | return 1; | 1376 | return 1; |
1384 | lpfc_nlp_init(phba, ndlp, nportid); | ||
1385 | 1377 | ||
1386 | elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp, | 1378 | lpfc_nlp_init(vport, ndlp, nportid); |
1387 | ndlp->nlp_DID, ELS_CMD_RNID); | 1379 | |
1380 | elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, | ||
1381 | ndlp->nlp_DID, ELS_CMD_RNID); | ||
1388 | if (!elsiocb) { | 1382 | if (!elsiocb) { |
1389 | lpfc_nlp_put(ndlp); | 1383 | lpfc_nlp_put(ndlp); |
1390 | return 1; | 1384 | return 1; |
@@ -1401,13 +1395,14 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1401 | memset(fp, 0, sizeof (FARP)); | 1395 | memset(fp, 0, sizeof (FARP)); |
1402 | lp = (uint32_t *) pcmd; | 1396 | lp = (uint32_t *) pcmd; |
1403 | *lp++ = be32_to_cpu(nportid); | 1397 | *lp++ = be32_to_cpu(nportid); |
1404 | *lp++ = be32_to_cpu(phba->fc_myDID); | 1398 | *lp++ = be32_to_cpu(vport->fc_myDID); |
1405 | fp->Rflags = 0; | 1399 | fp->Rflags = 0; |
1406 | fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE); | 1400 | fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE); |
1407 | 1401 | ||
1408 | memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name)); | 1402 | memcpy(&fp->RportName, &vport->fc_portname, sizeof (struct lpfc_name)); |
1409 | memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); | 1403 | memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof (struct lpfc_name)); |
1410 | if ((ondlp = lpfc_findnode_did(phba, nportid))) { | 1404 | ondlp = lpfc_findnode_did(vport, nportid); |
1405 | if (ondlp) { | ||
1411 | memcpy(&fp->OportName, &ondlp->nlp_portname, | 1406 | memcpy(&fp->OportName, &ondlp->nlp_portname, |
1412 | sizeof (struct lpfc_name)); | 1407 | sizeof (struct lpfc_name)); |
1413 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, | 1408 | memcpy(&fp->OnodeName, &ondlp->nlp_nodename, |
@@ -1416,22 +1411,23 @@ lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry) | |||
1416 | 1411 | ||
1417 | phba->fc_stat.elsXmitFARPR++; | 1412 | phba->fc_stat.elsXmitFARPR++; |
1418 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; | 1413 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
1419 | spin_lock_irq(phba->host->host_lock); | ||
1420 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { | 1414 | if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) { |
1421 | spin_unlock_irq(phba->host->host_lock); | ||
1422 | lpfc_nlp_put(ndlp); | 1415 | lpfc_nlp_put(ndlp); |
1423 | lpfc_els_free_iocb(phba, elsiocb); | 1416 | lpfc_els_free_iocb(phba, elsiocb); |
1424 | return 1; | 1417 | return 1; |
1425 | } | 1418 | } |
1426 | spin_unlock_irq(phba->host->host_lock); | ||
1427 | lpfc_nlp_put(ndlp); | 1419 | lpfc_nlp_put(ndlp); |
1428 | return 0; | 1420 | return 0; |
1429 | } | 1421 | } |
1430 | 1422 | ||
1431 | void | 1423 | void |
1432 | lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp) | 1424 | lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) |
1433 | { | 1425 | { |
1426 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1427 | |||
1428 | spin_lock_irq(shost->host_lock); | ||
1434 | nlp->nlp_flag &= ~NLP_DELAY_TMO; | 1429 | nlp->nlp_flag &= ~NLP_DELAY_TMO; |
1430 | spin_unlock_irq(shost->host_lock); | ||
1435 | del_timer_sync(&nlp->nlp_delayfunc); | 1431 | del_timer_sync(&nlp->nlp_delayfunc); |
1436 | nlp->nlp_last_elscmd = 0; | 1432 | nlp->nlp_last_elscmd = 0; |
1437 | 1433 | ||
@@ -1439,28 +1435,36 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp) | |||
1439 | list_del_init(&nlp->els_retry_evt.evt_listp); | 1435 | list_del_init(&nlp->els_retry_evt.evt_listp); |
1440 | 1436 | ||
1441 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { | 1437 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { |
1438 | spin_lock_irq(shost->host_lock); | ||
1442 | nlp->nlp_flag &= ~NLP_NPR_2B_DISC; | 1439 | nlp->nlp_flag &= ~NLP_NPR_2B_DISC; |
1443 | if (phba->num_disc_nodes) { | 1440 | spin_unlock_irq(shost->host_lock); |
1441 | if (vport->num_disc_nodes) { | ||
1444 | /* Check to see if there are more | 1442 | /* Check to see if there are more |
1445 | * PLOGIs to be sent | 1443 | * PLOGIs to be sent |
1446 | */ | 1444 | */ |
1447 | lpfc_more_plogi(phba); | 1445 | lpfc_more_plogi(vport); |
1448 | 1446 | ||
1449 | if (phba->num_disc_nodes == 0) { | 1447 | if (vport->num_disc_nodes == 0) { |
1450 | phba->fc_flag &= ~FC_NDISC_ACTIVE; | 1448 | spin_lock_irq(shost->host_lock); |
1451 | lpfc_can_disctmo(phba); | 1449 | vport->fc_flag &= ~FC_NDISC_ACTIVE; |
1452 | if (phba->fc_flag & FC_RSCN_MODE) { | 1450 | spin_unlock_irq(shost->host_lock); |
1451 | lpfc_can_disctmo(vport); | ||
1452 | if (vport->fc_flag & FC_RSCN_MODE) { | ||
1453 | /* | 1453 | /* |
1454 | * Check to see if more RSCNs | 1454 | * Check to see if more RSCNs |
1455 | * came in while we were | 1455 | * came in while we were |
1456 | * processing this one. | 1456 | * processing this one. |
1457 | */ | 1457 | */ |
1458 | if((phba->fc_rscn_id_cnt==0) && | 1458 | if (!vport->fc_rscn_id_cnt && |
1459 | !(phba->fc_flag & FC_RSCN_DISCOVERY)) { | 1459 | !(vport->fc_flag & |
1460 | phba->fc_flag &= ~FC_RSCN_MODE; | 1460 | FC_RSCN_DISCOVERY)) { |
1461 | spin_lock_irq(shost->host_lock); | ||
1462 | vport->fc_flag &= ~FC_RSCN_MODE; | ||
1463 | spin_unlock_irq( | ||
1464 | shost->host_lock); | ||
1461 | } | 1465 | } |
1462 | else { | 1466 | else { |
1463 | lpfc_els_handle_rscn(phba); | 1467 | lpfc_els_handle_rscn(vport); |
1464 | } | 1468 | } |
1465 | } | 1469 | } |
1466 | } | 1470 | } |
@@ -1472,18 +1476,20 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp) | |||
1472 | void | 1476 | void |
1473 | lpfc_els_retry_delay(unsigned long ptr) | 1477 | lpfc_els_retry_delay(unsigned long ptr) |
1474 | { | 1478 | { |
1475 | struct lpfc_nodelist *ndlp; | 1479 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr; |
1476 | struct lpfc_hba *phba; | 1480 | struct lpfc_vport *vport = ndlp->vport; |
1481 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1482 | struct lpfc_hba *phba = vport->phba; | ||
1477 | unsigned long iflag; | 1483 | unsigned long iflag; |
1478 | struct lpfc_work_evt *evtp; | 1484 | struct lpfc_work_evt *evtp = &ndlp->els_retry_evt; |
1479 | 1485 | ||
1480 | ndlp = (struct lpfc_nodelist *)ptr; | 1486 | ndlp = (struct lpfc_nodelist *) ptr; |
1481 | phba = ndlp->nlp_phba; | 1487 | phba = ndlp->vport->phba; |
1482 | evtp = &ndlp->els_retry_evt; | 1488 | evtp = &ndlp->els_retry_evt; |
1483 | 1489 | ||
1484 | spin_lock_irqsave(phba->host->host_lock, iflag); | 1490 | spin_lock_irqsave(shost->host_lock, iflag); |
1485 | if (!list_empty(&evtp->evt_listp)) { | 1491 | if (!list_empty(&evtp->evt_listp)) { |
1486 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 1492 | spin_unlock_irqrestore(shost->host_lock, iflag); |
1487 | return; | 1493 | return; |
1488 | } | 1494 | } |
1489 | 1495 | ||
@@ -1493,31 +1499,29 @@ lpfc_els_retry_delay(unsigned long ptr) | |||
1493 | if (phba->work_wait) | 1499 | if (phba->work_wait) |
1494 | wake_up(phba->work_wait); | 1500 | wake_up(phba->work_wait); |
1495 | 1501 | ||
1496 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 1502 | spin_unlock_irqrestore(shost->host_lock, iflag); |
1497 | return; | 1503 | return; |
1498 | } | 1504 | } |
1499 | 1505 | ||
1500 | void | 1506 | void |
1501 | lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | 1507 | lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) |
1502 | { | 1508 | { |
1503 | struct lpfc_hba *phba; | 1509 | struct lpfc_vport *vport = ndlp->vport; |
1504 | uint32_t cmd; | 1510 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1505 | uint32_t did; | 1511 | uint32_t cmd, did, retry; |
1506 | uint8_t retry; | ||
1507 | 1512 | ||
1508 | phba = ndlp->nlp_phba; | 1513 | spin_lock_irq(shost->host_lock); |
1509 | spin_lock_irq(phba->host->host_lock); | ||
1510 | did = ndlp->nlp_DID; | 1514 | did = ndlp->nlp_DID; |
1511 | cmd = ndlp->nlp_last_elscmd; | 1515 | cmd = ndlp->nlp_last_elscmd; |
1512 | ndlp->nlp_last_elscmd = 0; | 1516 | ndlp->nlp_last_elscmd = 0; |
1513 | 1517 | ||
1514 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1518 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { |
1515 | spin_unlock_irq(phba->host->host_lock); | 1519 | spin_unlock_irq(shost->host_lock); |
1516 | return; | 1520 | return; |
1517 | } | 1521 | } |
1518 | 1522 | ||
1519 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | 1523 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; |
1520 | spin_unlock_irq(phba->host->host_lock); | 1524 | spin_unlock_irq(shost->host_lock); |
1521 | /* | 1525 | /* |
1522 | * If a discovery event readded nlp_delayfunc after timer | 1526 | * If a discovery event readded nlp_delayfunc after timer |
1523 | * firing and before processing the timer, cancel the | 1527 | * firing and before processing the timer, cancel the |
@@ -1528,30 +1532,30 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
1528 | 1532 | ||
1529 | switch (cmd) { | 1533 | switch (cmd) { |
1530 | case ELS_CMD_FLOGI: | 1534 | case ELS_CMD_FLOGI: |
1531 | lpfc_issue_els_flogi(phba, ndlp, retry); | 1535 | lpfc_issue_els_flogi(vport, ndlp, retry); |
1532 | break; | 1536 | break; |
1533 | case ELS_CMD_PLOGI: | 1537 | case ELS_CMD_PLOGI: |
1534 | if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) { | 1538 | if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) { |
1535 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1539 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1536 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 1540 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1537 | } | 1541 | } |
1538 | break; | 1542 | break; |
1539 | case ELS_CMD_ADISC: | 1543 | case ELS_CMD_ADISC: |
1540 | if (!lpfc_issue_els_adisc(phba, ndlp, retry)) { | 1544 | if (!lpfc_issue_els_adisc(vport, ndlp, retry)) { |
1541 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1545 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1542 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); | 1546 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
1543 | } | 1547 | } |
1544 | break; | 1548 | break; |
1545 | case ELS_CMD_PRLI: | 1549 | case ELS_CMD_PRLI: |
1546 | if (!lpfc_issue_els_prli(phba, ndlp, retry)) { | 1550 | if (!lpfc_issue_els_prli(vport, ndlp, retry)) { |
1547 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1551 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1548 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); | 1552 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
1549 | } | 1553 | } |
1550 | break; | 1554 | break; |
1551 | case ELS_CMD_LOGO: | 1555 | case ELS_CMD_LOGO: |
1552 | if (!lpfc_issue_els_logo(phba, ndlp, retry)) { | 1556 | if (!lpfc_issue_els_logo(vport, ndlp, retry)) { |
1553 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1557 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1554 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1558 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1555 | } | 1559 | } |
1556 | break; | 1560 | break; |
1557 | } | 1561 | } |
@@ -1559,26 +1563,20 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) | |||
1559 | } | 1563 | } |
1560 | 1564 | ||
1561 | static int | 1565 | static int |
1562 | lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1566 | lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1563 | struct lpfc_iocbq * rspiocb) | 1567 | struct lpfc_iocbq *rspiocb) |
1564 | { | 1568 | { |
1565 | IOCB_t *irsp; | 1569 | struct lpfc_vport *vport = cmdiocb->vport; |
1566 | struct lpfc_dmabuf *pcmd; | 1570 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1567 | struct lpfc_nodelist *ndlp; | 1571 | IOCB_t *irsp = &rspiocb->iocb; |
1572 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1573 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
1568 | uint32_t *elscmd; | 1574 | uint32_t *elscmd; |
1569 | struct ls_rjt stat; | 1575 | struct ls_rjt stat; |
1570 | int retry, maxretry; | 1576 | int retry = 0, maxretry = lpfc_max_els_tries, delay = 0; |
1571 | int delay; | 1577 | uint32_t cmd = 0; |
1572 | uint32_t cmd; | ||
1573 | uint32_t did; | 1578 | uint32_t did; |
1574 | 1579 | ||
1575 | retry = 0; | ||
1576 | delay = 0; | ||
1577 | maxretry = lpfc_max_els_tries; | ||
1578 | irsp = &rspiocb->iocb; | ||
1579 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1580 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
1581 | cmd = 0; | ||
1582 | 1580 | ||
1583 | /* Note: context2 may be 0 for internal driver abort | 1581 | /* Note: context2 may be 0 for internal driver abort |
1584 | * of delays ELS command. | 1582 | * of delays ELS command. |
@@ -1594,7 +1592,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1594 | else { | 1592 | else { |
1595 | /* We should only hit this case for retrying PLOGI */ | 1593 | /* We should only hit this case for retrying PLOGI */ |
1596 | did = irsp->un.elsreq64.remoteID; | 1594 | did = irsp->un.elsreq64.remoteID; |
1597 | ndlp = lpfc_findnode_did(phba, did); | 1595 | ndlp = lpfc_findnode_did(vport, did); |
1598 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) | 1596 | if (!ndlp && (cmd != ELS_CMD_PLOGI)) |
1599 | return 1; | 1597 | return 1; |
1600 | } | 1598 | } |
@@ -1607,11 +1605,8 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1607 | case IOSTAT_LOCAL_REJECT: | 1605 | case IOSTAT_LOCAL_REJECT: |
1608 | switch ((irsp->un.ulpWord[4] & 0xff)) { | 1606 | switch ((irsp->un.ulpWord[4] & 0xff)) { |
1609 | case IOERR_LOOP_OPEN_FAILURE: | 1607 | case IOERR_LOOP_OPEN_FAILURE: |
1610 | if (cmd == ELS_CMD_PLOGI) { | 1608 | if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0) |
1611 | if (cmdiocb->retry == 0) { | ||
1612 | delay = 1; | 1609 | delay = 1; |
1613 | } | ||
1614 | } | ||
1615 | retry = 1; | 1610 | retry = 1; |
1616 | break; | 1611 | break; |
1617 | 1612 | ||
@@ -1620,9 +1615,8 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1620 | break; | 1615 | break; |
1621 | 1616 | ||
1622 | case IOERR_NO_RESOURCES: | 1617 | case IOERR_NO_RESOURCES: |
1623 | if (cmd == ELS_CMD_PLOGI) { | 1618 | if (cmd == ELS_CMD_PLOGI) |
1624 | delay = 1; | 1619 | delay = 1; |
1625 | } | ||
1626 | retry = 1; | 1620 | retry = 1; |
1627 | break; | 1621 | break; |
1628 | 1622 | ||
@@ -1706,10 +1700,9 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1706 | 1700 | ||
1707 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { | 1701 | if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) { |
1708 | /* If discovery / RSCN timer is running, reset it */ | 1702 | /* If discovery / RSCN timer is running, reset it */ |
1709 | if (timer_pending(&phba->fc_disctmo) || | 1703 | if (timer_pending(&vport->fc_disctmo) || |
1710 | (phba->fc_flag & FC_RSCN_MODE)) { | 1704 | (vport->fc_flag & FC_RSCN_MODE)) |
1711 | lpfc_set_disctmo(phba); | 1705 | lpfc_set_disctmo(vport); |
1712 | } | ||
1713 | } | 1706 | } |
1714 | 1707 | ||
1715 | phba->fc_stat.elsXmitRetry++; | 1708 | phba->fc_stat.elsXmitRetry++; |
@@ -1718,40 +1711,42 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1718 | ndlp->nlp_retry = cmdiocb->retry; | 1711 | ndlp->nlp_retry = cmdiocb->retry; |
1719 | 1712 | ||
1720 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 1713 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); |
1714 | spin_lock_irq(shost->host_lock); | ||
1721 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1715 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
1716 | spin_unlock_irq(shost->host_lock); | ||
1722 | 1717 | ||
1723 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1718 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1724 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1719 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1725 | ndlp->nlp_last_elscmd = cmd; | 1720 | ndlp->nlp_last_elscmd = cmd; |
1726 | 1721 | ||
1727 | return 1; | 1722 | return 1; |
1728 | } | 1723 | } |
1729 | switch (cmd) { | 1724 | switch (cmd) { |
1730 | case ELS_CMD_FLOGI: | 1725 | case ELS_CMD_FLOGI: |
1731 | lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry); | 1726 | lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry); |
1732 | return 1; | 1727 | return 1; |
1733 | case ELS_CMD_PLOGI: | 1728 | case ELS_CMD_PLOGI: |
1734 | if (ndlp) { | 1729 | if (ndlp) { |
1735 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1730 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1736 | lpfc_nlp_set_state(phba, ndlp, | 1731 | lpfc_nlp_set_state(vport, ndlp, |
1737 | NLP_STE_PLOGI_ISSUE); | 1732 | NLP_STE_PLOGI_ISSUE); |
1738 | } | 1733 | } |
1739 | lpfc_issue_els_plogi(phba, did, cmdiocb->retry); | 1734 | lpfc_issue_els_plogi(vport, did, cmdiocb->retry); |
1740 | return 1; | 1735 | return 1; |
1741 | case ELS_CMD_ADISC: | 1736 | case ELS_CMD_ADISC: |
1742 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1737 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1743 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); | 1738 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
1744 | lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry); | 1739 | lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry); |
1745 | return 1; | 1740 | return 1; |
1746 | case ELS_CMD_PRLI: | 1741 | case ELS_CMD_PRLI: |
1747 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1742 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1748 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE); | 1743 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE); |
1749 | lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry); | 1744 | lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry); |
1750 | return 1; | 1745 | return 1; |
1751 | case ELS_CMD_LOGO: | 1746 | case ELS_CMD_LOGO: |
1752 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1747 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1753 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE); | 1748 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); |
1754 | lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry); | 1749 | lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry); |
1755 | return 1; | 1750 | return 1; |
1756 | } | 1751 | } |
1757 | } | 1752 | } |
@@ -1795,19 +1790,16 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) | |||
1795 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); | 1790 | lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); |
1796 | kfree(buf_ptr); | 1791 | kfree(buf_ptr); |
1797 | } | 1792 | } |
1798 | spin_lock_irq(phba->host->host_lock); | ||
1799 | lpfc_sli_release_iocbq(phba, elsiocb); | 1793 | lpfc_sli_release_iocbq(phba, elsiocb); |
1800 | spin_unlock_irq(phba->host->host_lock); | ||
1801 | return 0; | 1794 | return 0; |
1802 | } | 1795 | } |
1803 | 1796 | ||
1804 | static void | 1797 | static void |
1805 | lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 1798 | lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1806 | struct lpfc_iocbq * rspiocb) | 1799 | struct lpfc_iocbq *rspiocb) |
1807 | { | 1800 | { |
1808 | struct lpfc_nodelist *ndlp; | 1801 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; |
1809 | 1802 | struct lpfc_vport *vport = cmdiocb->vport; | |
1810 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1811 | 1803 | ||
1812 | /* ACC to LOGO completes to NPort <nlp_DID> */ | 1804 | /* ACC to LOGO completes to NPort <nlp_DID> */ |
1813 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 1805 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
@@ -1818,10 +1810,10 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1818 | 1810 | ||
1819 | switch (ndlp->nlp_state) { | 1811 | switch (ndlp->nlp_state) { |
1820 | case NLP_STE_UNUSED_NODE: /* node is just allocated */ | 1812 | case NLP_STE_UNUSED_NODE: /* node is just allocated */ |
1821 | lpfc_drop_node(phba, ndlp); | 1813 | lpfc_drop_node(vport, ndlp); |
1822 | break; | 1814 | break; |
1823 | case NLP_STE_NPR_NODE: /* NPort Recovery mode */ | 1815 | case NLP_STE_NPR_NODE: /* NPort Recovery mode */ |
1824 | lpfc_unreg_rpi(phba, ndlp); | 1816 | lpfc_unreg_rpi(vport, ndlp); |
1825 | break; | 1817 | break; |
1826 | default: | 1818 | default: |
1827 | break; | 1819 | break; |
@@ -1834,20 +1826,20 @@ static void | |||
1834 | lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 1826 | lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
1835 | struct lpfc_iocbq *rspiocb) | 1827 | struct lpfc_iocbq *rspiocb) |
1836 | { | 1828 | { |
1829 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1830 | struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL; | ||
1831 | struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL; | ||
1837 | IOCB_t *irsp; | 1832 | IOCB_t *irsp; |
1838 | struct lpfc_nodelist *ndlp; | ||
1839 | LPFC_MBOXQ_t *mbox = NULL; | 1833 | LPFC_MBOXQ_t *mbox = NULL; |
1840 | struct lpfc_dmabuf *mp; | 1834 | struct lpfc_dmabuf *mp = NULL; |
1841 | 1835 | ||
1842 | irsp = &rspiocb->iocb; | 1836 | irsp = &rspiocb->iocb; |
1843 | 1837 | ||
1844 | ndlp = (struct lpfc_nodelist *) cmdiocb->context1; | ||
1845 | if (cmdiocb->context_un.mbox) | 1838 | if (cmdiocb->context_un.mbox) |
1846 | mbox = cmdiocb->context_un.mbox; | 1839 | mbox = cmdiocb->context_un.mbox; |
1847 | 1840 | ||
1848 | |||
1849 | /* Check to see if link went down during discovery */ | 1841 | /* Check to see if link went down during discovery */ |
1850 | if (lpfc_els_chk_latt(phba) || !ndlp) { | 1842 | if (!ndlp || lpfc_els_chk_latt(vport)) { |
1851 | if (mbox) { | 1843 | if (mbox) { |
1852 | mp = (struct lpfc_dmabuf *) mbox->context1; | 1844 | mp = (struct lpfc_dmabuf *) mbox->context1; |
1853 | if (mp) { | 1845 | if (mp) { |
@@ -1866,17 +1858,19 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1866 | phba->brd_no, | 1858 | phba->brd_no, |
1867 | cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, | 1859 | cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus, |
1868 | rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, | 1860 | rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout, |
1869 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, | 1861 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
1870 | ndlp->nlp_rpi); | 1862 | ndlp->nlp_rpi); |
1871 | 1863 | ||
1872 | if (mbox) { | 1864 | if (mbox) { |
1873 | if ((rspiocb->iocb.ulpStatus == 0) | 1865 | if ((rspiocb->iocb.ulpStatus == 0) |
1874 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { | 1866 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { |
1875 | lpfc_unreg_rpi(phba, ndlp); | 1867 | lpfc_unreg_rpi(vport, ndlp); |
1876 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; | 1868 | mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; |
1877 | mbox->context2 = lpfc_nlp_get(ndlp); | 1869 | mbox->context2 = lpfc_nlp_get(ndlp); |
1870 | mbox->vport = vport; | ||
1878 | ndlp->nlp_prev_state = ndlp->nlp_state; | 1871 | ndlp->nlp_prev_state = ndlp->nlp_state; |
1879 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE); | 1872 | lpfc_nlp_set_state(vport, ndlp, |
1873 | NLP_STE_REG_LOGIN_ISSUE); | ||
1880 | if (lpfc_sli_issue_mbox(phba, mbox, | 1874 | if (lpfc_sli_issue_mbox(phba, mbox, |
1881 | (MBX_NOWAIT | MBX_STOP_IOCB)) | 1875 | (MBX_NOWAIT | MBX_STOP_IOCB)) |
1882 | != MBX_NOT_FINISHED) { | 1876 | != MBX_NOT_FINISHED) { |
@@ -1892,7 +1886,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1892 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || | 1886 | (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || |
1893 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) { | 1887 | (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) { |
1894 | if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { | 1888 | if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { |
1895 | lpfc_drop_node(phba, ndlp); | 1889 | lpfc_drop_node(vport, ndlp); |
1896 | ndlp = NULL; | 1890 | ndlp = NULL; |
1897 | } | 1891 | } |
1898 | } | 1892 | } |
@@ -1906,19 +1900,21 @@ lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1906 | } | 1900 | } |
1907 | out: | 1901 | out: |
1908 | if (ndlp) { | 1902 | if (ndlp) { |
1909 | spin_lock_irq(phba->host->host_lock); | 1903 | spin_lock_irq(shost->host_lock); |
1910 | ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; | 1904 | ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; |
1911 | spin_unlock_irq(phba->host->host_lock); | 1905 | spin_unlock_irq(shost->host_lock); |
1912 | } | 1906 | } |
1913 | lpfc_els_free_iocb(phba, cmdiocb); | 1907 | lpfc_els_free_iocb(phba, cmdiocb); |
1914 | return; | 1908 | return; |
1915 | } | 1909 | } |
1916 | 1910 | ||
1917 | int | 1911 | int |
1918 | lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | 1912 | lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, |
1919 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp, | 1913 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, |
1920 | LPFC_MBOXQ_t * mbox, uint8_t newnode) | 1914 | LPFC_MBOXQ_t *mbox, uint8_t newnode) |
1921 | { | 1915 | { |
1916 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1917 | struct lpfc_hba *phba = vport->phba; | ||
1922 | IOCB_t *icmd; | 1918 | IOCB_t *icmd; |
1923 | IOCB_t *oldcmd; | 1919 | IOCB_t *oldcmd; |
1924 | struct lpfc_iocbq *elsiocb; | 1920 | struct lpfc_iocbq *elsiocb; |
@@ -1936,12 +1932,15 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1936 | switch (flag) { | 1932 | switch (flag) { |
1937 | case ELS_CMD_ACC: | 1933 | case ELS_CMD_ACC: |
1938 | cmdsize = sizeof (uint32_t); | 1934 | cmdsize = sizeof (uint32_t); |
1939 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 1935 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, |
1940 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | 1936 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
1941 | if (!elsiocb) { | 1937 | if (!elsiocb) { |
1938 | spin_lock_irq(shost->host_lock); | ||
1942 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; | 1939 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; |
1940 | spin_unlock_irq(shost->host_lock); | ||
1943 | return 1; | 1941 | return 1; |
1944 | } | 1942 | } |
1943 | |||
1945 | icmd = &elsiocb->iocb; | 1944 | icmd = &elsiocb->iocb; |
1946 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ | 1945 | icmd->ulpContext = oldcmd->ulpContext; /* Xri */ |
1947 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); | 1946 | pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
@@ -1950,8 +1949,8 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1950 | break; | 1949 | break; |
1951 | case ELS_CMD_PLOGI: | 1950 | case ELS_CMD_PLOGI: |
1952 | cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); | 1951 | cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t)); |
1953 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 1952 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, |
1954 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | 1953 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); |
1955 | if (!elsiocb) | 1954 | if (!elsiocb) |
1956 | return 1; | 1955 | return 1; |
1957 | 1956 | ||
@@ -1964,11 +1963,11 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
1964 | 1963 | ||
1965 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; | 1964 | *((uint32_t *) (pcmd)) = ELS_CMD_ACC; |
1966 | pcmd += sizeof (uint32_t); | 1965 | pcmd += sizeof (uint32_t); |
1967 | memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); | 1966 | memcpy(pcmd, &vport->fc_sparam, sizeof (struct serv_parm)); |
1968 | break; | 1967 | break; |
1969 | case ELS_CMD_PRLO: | 1968 | case ELS_CMD_PRLO: |
1970 | cmdsize = sizeof (uint32_t) + sizeof (PRLO); | 1969 | cmdsize = sizeof (uint32_t) + sizeof (PRLO); |
1971 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 1970 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, |
1972 | ndlp, ndlp->nlp_DID, ELS_CMD_PRLO); | 1971 | ndlp, ndlp->nlp_DID, ELS_CMD_PRLO); |
1973 | if (!elsiocb) | 1972 | if (!elsiocb) |
1974 | return 1; | 1973 | return 1; |
@@ -2001,18 +2000,16 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
2001 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); | 2000 | ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); |
2002 | 2001 | ||
2003 | if (ndlp->nlp_flag & NLP_LOGO_ACC) { | 2002 | if (ndlp->nlp_flag & NLP_LOGO_ACC) { |
2004 | spin_lock_irq(phba->host->host_lock); | 2003 | spin_lock_irq(shost->host_lock); |
2005 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; | 2004 | ndlp->nlp_flag &= ~NLP_LOGO_ACC; |
2006 | spin_unlock_irq(phba->host->host_lock); | 2005 | spin_unlock_irq(shost->host_lock); |
2007 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; | 2006 | elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; |
2008 | } else { | 2007 | } else { |
2009 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2008 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2010 | } | 2009 | } |
2011 | 2010 | ||
2012 | phba->fc_stat.elsXmitACC++; | 2011 | phba->fc_stat.elsXmitACC++; |
2013 | spin_lock_irq(phba->host->host_lock); | ||
2014 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2012 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2015 | spin_unlock_irq(phba->host->host_lock); | ||
2016 | if (rc == IOCB_ERROR) { | 2013 | if (rc == IOCB_ERROR) { |
2017 | lpfc_els_free_iocb(phba, elsiocb); | 2014 | lpfc_els_free_iocb(phba, elsiocb); |
2018 | return 1; | 2015 | return 1; |
@@ -2021,9 +2018,10 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag, | |||
2021 | } | 2018 | } |
2022 | 2019 | ||
2023 | int | 2020 | int |
2024 | lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | 2021 | lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, |
2025 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | 2022 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) |
2026 | { | 2023 | { |
2024 | struct lpfc_hba *phba = vport->phba; | ||
2027 | IOCB_t *icmd; | 2025 | IOCB_t *icmd; |
2028 | IOCB_t *oldcmd; | 2026 | IOCB_t *oldcmd; |
2029 | struct lpfc_iocbq *elsiocb; | 2027 | struct lpfc_iocbq *elsiocb; |
@@ -2037,8 +2035,8 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | |||
2037 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2035 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
2038 | 2036 | ||
2039 | cmdsize = 2 * sizeof (uint32_t); | 2037 | cmdsize = 2 * sizeof (uint32_t); |
2040 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2038 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
2041 | ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT); | 2039 | ndlp->nlp_DID, ELS_CMD_LS_RJT); |
2042 | if (!elsiocb) | 2040 | if (!elsiocb) |
2043 | return 1; | 2041 | return 1; |
2044 | 2042 | ||
@@ -2061,9 +2059,7 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | |||
2061 | 2059 | ||
2062 | phba->fc_stat.elsXmitLSRJT++; | 2060 | phba->fc_stat.elsXmitLSRJT++; |
2063 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2061 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2064 | spin_lock_irq(phba->host->host_lock); | ||
2065 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2062 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2066 | spin_unlock_irq(phba->host->host_lock); | ||
2067 | if (rc == IOCB_ERROR) { | 2063 | if (rc == IOCB_ERROR) { |
2068 | lpfc_els_free_iocb(phba, elsiocb); | 2064 | lpfc_els_free_iocb(phba, elsiocb); |
2069 | return 1; | 2065 | return 1; |
@@ -2072,25 +2068,22 @@ lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError, | |||
2072 | } | 2068 | } |
2073 | 2069 | ||
2074 | int | 2070 | int |
2075 | lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, | 2071 | lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, |
2076 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | 2072 | struct lpfc_nodelist *ndlp) |
2077 | { | 2073 | { |
2074 | struct lpfc_hba *phba = vport->phba; | ||
2075 | struct lpfc_sli *psli = &phba->sli; | ||
2076 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; | ||
2078 | ADISC *ap; | 2077 | ADISC *ap; |
2079 | IOCB_t *icmd; | 2078 | IOCB_t *icmd, *oldcmd; |
2080 | IOCB_t *oldcmd; | ||
2081 | struct lpfc_iocbq *elsiocb; | 2079 | struct lpfc_iocbq *elsiocb; |
2082 | struct lpfc_sli_ring *pring; | ||
2083 | struct lpfc_sli *psli; | ||
2084 | uint8_t *pcmd; | 2080 | uint8_t *pcmd; |
2085 | uint16_t cmdsize; | 2081 | uint16_t cmdsize; |
2086 | int rc; | 2082 | int rc; |
2087 | 2083 | ||
2088 | psli = &phba->sli; | ||
2089 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | ||
2090 | |||
2091 | cmdsize = sizeof (uint32_t) + sizeof (ADISC); | 2084 | cmdsize = sizeof (uint32_t) + sizeof (ADISC); |
2092 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2085 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
2093 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | 2086 | ndlp->nlp_DID, ELS_CMD_ACC); |
2094 | if (!elsiocb) | 2087 | if (!elsiocb) |
2095 | return 1; | 2088 | return 1; |
2096 | 2089 | ||
@@ -2113,15 +2106,13 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, | |||
2113 | 2106 | ||
2114 | ap = (ADISC *) (pcmd); | 2107 | ap = (ADISC *) (pcmd); |
2115 | ap->hardAL_PA = phba->fc_pref_ALPA; | 2108 | ap->hardAL_PA = phba->fc_pref_ALPA; |
2116 | memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name)); | 2109 | memcpy(&ap->portName, &vport->fc_portname, sizeof (struct lpfc_name)); |
2117 | memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); | 2110 | memcpy(&ap->nodeName, &vport->fc_nodename, sizeof (struct lpfc_name)); |
2118 | ap->DID = be32_to_cpu(phba->fc_myDID); | 2111 | ap->DID = be32_to_cpu(vport->fc_myDID); |
2119 | 2112 | ||
2120 | phba->fc_stat.elsXmitACC++; | 2113 | phba->fc_stat.elsXmitACC++; |
2121 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2114 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2122 | spin_lock_irq(phba->host->host_lock); | ||
2123 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2115 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2124 | spin_unlock_irq(phba->host->host_lock); | ||
2125 | if (rc == IOCB_ERROR) { | 2116 | if (rc == IOCB_ERROR) { |
2126 | lpfc_els_free_iocb(phba, elsiocb); | 2117 | lpfc_els_free_iocb(phba, elsiocb); |
2127 | return 1; | 2118 | return 1; |
@@ -2130,9 +2121,10 @@ lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba, | |||
2130 | } | 2121 | } |
2131 | 2122 | ||
2132 | int | 2123 | int |
2133 | lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, | 2124 | lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, |
2134 | struct lpfc_nodelist *ndlp) | 2125 | struct lpfc_nodelist *ndlp) |
2135 | { | 2126 | { |
2127 | struct lpfc_hba *phba = vport->phba; | ||
2136 | PRLI *npr; | 2128 | PRLI *npr; |
2137 | lpfc_vpd_t *vpd; | 2129 | lpfc_vpd_t *vpd; |
2138 | IOCB_t *icmd; | 2130 | IOCB_t *icmd; |
@@ -2148,8 +2140,10 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, | |||
2148 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2140 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ |
2149 | 2141 | ||
2150 | cmdsize = sizeof (uint32_t) + sizeof (PRLI); | 2142 | cmdsize = sizeof (uint32_t) + sizeof (PRLI); |
2151 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp, | 2143 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
2152 | ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); | 2144 | ndlp->nlp_DID, |
2145 | (ELS_CMD_ACC | | ||
2146 | (ELS_CMD_PRLI & ~ELS_RSP_MASK))); | ||
2153 | if (!elsiocb) | 2147 | if (!elsiocb) |
2154 | return 1; | 2148 | return 1; |
2155 | 2149 | ||
@@ -2196,9 +2190,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, | |||
2196 | phba->fc_stat.elsXmitACC++; | 2190 | phba->fc_stat.elsXmitACC++; |
2197 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; | 2191 | elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; |
2198 | 2192 | ||
2199 | spin_lock_irq(phba->host->host_lock); | ||
2200 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2193 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2201 | spin_unlock_irq(phba->host->host_lock); | ||
2202 | if (rc == IOCB_ERROR) { | 2194 | if (rc == IOCB_ERROR) { |
2203 | lpfc_els_free_iocb(phba, elsiocb); | 2195 | lpfc_els_free_iocb(phba, elsiocb); |
2204 | return 1; | 2196 | return 1; |
@@ -2207,12 +2199,12 @@ lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb, | |||
2207 | } | 2199 | } |
2208 | 2200 | ||
2209 | static int | 2201 | static int |
2210 | lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | 2202 | lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, |
2211 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) | 2203 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) |
2212 | { | 2204 | { |
2205 | struct lpfc_hba *phba = vport->phba; | ||
2213 | RNID *rn; | 2206 | RNID *rn; |
2214 | IOCB_t *icmd; | 2207 | IOCB_t *icmd, *oldcmd; |
2215 | IOCB_t *oldcmd; | ||
2216 | struct lpfc_iocbq *elsiocb; | 2208 | struct lpfc_iocbq *elsiocb; |
2217 | struct lpfc_sli_ring *pring; | 2209 | struct lpfc_sli_ring *pring; |
2218 | struct lpfc_sli *psli; | 2210 | struct lpfc_sli *psli; |
@@ -2228,8 +2220,8 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2228 | if (format) | 2220 | if (format) |
2229 | cmdsize += sizeof (RNID_TOP_DISC); | 2221 | cmdsize += sizeof (RNID_TOP_DISC); |
2230 | 2222 | ||
2231 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | 2223 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
2232 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | 2224 | ndlp->nlp_DID, ELS_CMD_ACC); |
2233 | if (!elsiocb) | 2225 | if (!elsiocb) |
2234 | return 1; | 2226 | return 1; |
2235 | 2227 | ||
@@ -2253,8 +2245,8 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2253 | rn = (RNID *) (pcmd); | 2245 | rn = (RNID *) (pcmd); |
2254 | rn->Format = format; | 2246 | rn->Format = format; |
2255 | rn->CommonLen = (2 * sizeof (struct lpfc_name)); | 2247 | rn->CommonLen = (2 * sizeof (struct lpfc_name)); |
2256 | memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name)); | 2248 | memcpy(&rn->portName, &vport->fc_portname, sizeof (struct lpfc_name)); |
2257 | memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name)); | 2249 | memcpy(&rn->nodeName, &vport->fc_nodename, sizeof (struct lpfc_name)); |
2258 | switch (format) { | 2250 | switch (format) { |
2259 | case 0: | 2251 | case 0: |
2260 | rn->SpecificLen = 0; | 2252 | rn->SpecificLen = 0; |
@@ -2262,7 +2254,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2262 | case RNID_TOPOLOGY_DISC: | 2254 | case RNID_TOPOLOGY_DISC: |
2263 | rn->SpecificLen = sizeof (RNID_TOP_DISC); | 2255 | rn->SpecificLen = sizeof (RNID_TOP_DISC); |
2264 | memcpy(&rn->un.topologyDisc.portName, | 2256 | memcpy(&rn->un.topologyDisc.portName, |
2265 | &phba->fc_portname, sizeof (struct lpfc_name)); | 2257 | &vport->fc_portname, sizeof (struct lpfc_name)); |
2266 | rn->un.topologyDisc.unitType = RNID_HBA; | 2258 | rn->un.topologyDisc.unitType = RNID_HBA; |
2267 | rn->un.topologyDisc.physPort = 0; | 2259 | rn->un.topologyDisc.physPort = 0; |
2268 | rn->un.topologyDisc.attachedNodes = 0; | 2260 | rn->un.topologyDisc.attachedNodes = 0; |
@@ -2279,9 +2271,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2279 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, | 2271 | elsiocb->context1 = NULL; /* Don't need ndlp for cmpl, |
2280 | * it could be freed */ | 2272 | * it could be freed */ |
2281 | 2273 | ||
2282 | spin_lock_irq(phba->host->host_lock); | ||
2283 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); | 2274 | rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0); |
2284 | spin_unlock_irq(phba->host->host_lock); | ||
2285 | if (rc == IOCB_ERROR) { | 2275 | if (rc == IOCB_ERROR) { |
2286 | lpfc_els_free_iocb(phba, elsiocb); | 2276 | lpfc_els_free_iocb(phba, elsiocb); |
2287 | return 1; | 2277 | return 1; |
@@ -2290,120 +2280,122 @@ lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format, | |||
2290 | } | 2280 | } |
2291 | 2281 | ||
2292 | int | 2282 | int |
2293 | lpfc_els_disc_adisc(struct lpfc_hba *phba) | 2283 | lpfc_els_disc_adisc(struct lpfc_vport *vport) |
2294 | { | 2284 | { |
2295 | int sentadisc; | 2285 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2296 | struct lpfc_nodelist *ndlp, *next_ndlp; | 2286 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2287 | int sentadisc = 0; | ||
2297 | 2288 | ||
2298 | sentadisc = 0; | ||
2299 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ | 2289 | /* go thru NPR nodes and issue any remaining ELS ADISCs */ |
2300 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { | 2290 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { |
2301 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && | 2291 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2302 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && | 2292 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2303 | (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { | 2293 | (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { |
2304 | spin_lock_irq(phba->host->host_lock); | 2294 | spin_lock_irq(shost->host_lock); |
2305 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 2295 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
2306 | spin_unlock_irq(phba->host->host_lock); | 2296 | spin_unlock_irq(shost->host_lock); |
2307 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2297 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2308 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE); | 2298 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); |
2309 | lpfc_issue_els_adisc(phba, ndlp, 0); | 2299 | lpfc_issue_els_adisc(vport, ndlp, 0); |
2310 | sentadisc++; | 2300 | sentadisc++; |
2311 | phba->num_disc_nodes++; | 2301 | vport->num_disc_nodes++; |
2312 | if (phba->num_disc_nodes >= | 2302 | if (vport->num_disc_nodes >= |
2313 | phba->cfg_discovery_threads) { | 2303 | vport->phba->cfg_discovery_threads) { |
2314 | spin_lock_irq(phba->host->host_lock); | 2304 | spin_lock_irq(shost->host_lock); |
2315 | phba->fc_flag |= FC_NLP_MORE; | 2305 | vport->fc_flag |= FC_NLP_MORE; |
2316 | spin_unlock_irq(phba->host->host_lock); | 2306 | spin_unlock_irq(shost->host_lock); |
2317 | break; | 2307 | break; |
2318 | } | 2308 | } |
2319 | } | 2309 | } |
2320 | } | 2310 | } |
2321 | if (sentadisc == 0) { | 2311 | if (sentadisc == 0) { |
2322 | spin_lock_irq(phba->host->host_lock); | 2312 | spin_lock_irq(shost->host_lock); |
2323 | phba->fc_flag &= ~FC_NLP_MORE; | 2313 | vport->fc_flag &= ~FC_NLP_MORE; |
2324 | spin_unlock_irq(phba->host->host_lock); | 2314 | spin_unlock_irq(shost->host_lock); |
2325 | } | 2315 | } |
2326 | return sentadisc; | 2316 | return sentadisc; |
2327 | } | 2317 | } |
2328 | 2318 | ||
2329 | int | 2319 | int |
2330 | lpfc_els_disc_plogi(struct lpfc_hba * phba) | 2320 | lpfc_els_disc_plogi(struct lpfc_vport *vport) |
2331 | { | 2321 | { |
2332 | int sentplogi; | 2322 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2333 | struct lpfc_nodelist *ndlp, *next_ndlp; | 2323 | struct lpfc_nodelist *ndlp, *next_ndlp; |
2324 | int sentplogi = 0; | ||
2334 | 2325 | ||
2335 | sentplogi = 0; | 2326 | /* go thru NPR nodes and issue any remaining ELS PLOGIs */ |
2336 | /* go thru NPR list and issue any remaining ELS PLOGIs */ | 2327 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { |
2337 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp) { | ||
2338 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && | 2328 | if (ndlp->nlp_state == NLP_STE_NPR_NODE && |
2339 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && | 2329 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && |
2340 | (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && | 2330 | (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && |
2341 | (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) { | 2331 | (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) { |
2342 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2332 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2343 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 2333 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
2344 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 2334 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
2345 | sentplogi++; | 2335 | sentplogi++; |
2346 | phba->num_disc_nodes++; | 2336 | vport->num_disc_nodes++; |
2347 | if (phba->num_disc_nodes >= | 2337 | if (vport->num_disc_nodes >= |
2348 | phba->cfg_discovery_threads) { | 2338 | vport->phba->cfg_discovery_threads) { |
2349 | spin_lock_irq(phba->host->host_lock); | 2339 | spin_lock_irq(shost->host_lock); |
2350 | phba->fc_flag |= FC_NLP_MORE; | 2340 | vport->fc_flag |= FC_NLP_MORE; |
2351 | spin_unlock_irq(phba->host->host_lock); | 2341 | spin_unlock_irq(shost->host_lock); |
2352 | break; | 2342 | break; |
2353 | } | 2343 | } |
2354 | } | 2344 | } |
2355 | } | 2345 | } |
2356 | if (sentplogi == 0) { | 2346 | if (sentplogi == 0) { |
2357 | spin_lock_irq(phba->host->host_lock); | 2347 | spin_lock_irq(shost->host_lock); |
2358 | phba->fc_flag &= ~FC_NLP_MORE; | 2348 | vport->fc_flag &= ~FC_NLP_MORE; |
2359 | spin_unlock_irq(phba->host->host_lock); | 2349 | spin_unlock_irq(shost->host_lock); |
2360 | } | 2350 | } |
2361 | return sentplogi; | 2351 | return sentplogi; |
2362 | } | 2352 | } |
2363 | 2353 | ||
2364 | int | 2354 | int |
2365 | lpfc_els_flush_rscn(struct lpfc_hba * phba) | 2355 | lpfc_els_flush_rscn(struct lpfc_vport *vport) |
2366 | { | 2356 | { |
2357 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
2358 | struct lpfc_hba *phba = vport->phba; | ||
2367 | struct lpfc_dmabuf *mp; | 2359 | struct lpfc_dmabuf *mp; |
2368 | int i; | 2360 | int i; |
2369 | 2361 | ||
2370 | for (i = 0; i < phba->fc_rscn_id_cnt; i++) { | 2362 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { |
2371 | mp = phba->fc_rscn_id_list[i]; | 2363 | mp = vport->fc_rscn_id_list[i]; |
2372 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2364 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
2373 | kfree(mp); | 2365 | kfree(mp); |
2374 | phba->fc_rscn_id_list[i] = NULL; | 2366 | vport->fc_rscn_id_list[i] = NULL; |
2375 | } | 2367 | } |
2376 | phba->fc_rscn_id_cnt = 0; | 2368 | spin_lock_irq(shost->host_lock); |
2377 | spin_lock_irq(phba->host->host_lock); | 2369 | vport->fc_rscn_id_cnt = 0; |
2378 | phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); | 2370 | vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY); |
2379 | spin_unlock_irq(phba->host->host_lock); | 2371 | spin_unlock_irq(shost->host_lock); |
2380 | lpfc_can_disctmo(phba); | 2372 | lpfc_can_disctmo(vport); |
2381 | return 0; | 2373 | return 0; |
2382 | } | 2374 | } |
2383 | 2375 | ||
2384 | int | 2376 | int |
2385 | lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | 2377 | lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) |
2386 | { | 2378 | { |
2387 | D_ID ns_did; | 2379 | D_ID ns_did; |
2388 | D_ID rscn_did; | 2380 | D_ID rscn_did; |
2389 | struct lpfc_dmabuf *mp; | 2381 | struct lpfc_dmabuf *mp; |
2390 | uint32_t *lp; | 2382 | uint32_t *lp; |
2391 | uint32_t payload_len, cmd, i, match; | 2383 | uint32_t payload_len, cmd, i, match; |
2384 | struct lpfc_hba *phba = vport->phba; | ||
2392 | 2385 | ||
2393 | ns_did.un.word = did; | 2386 | ns_did.un.word = did; |
2394 | match = 0; | 2387 | match = 0; |
2395 | 2388 | ||
2396 | /* Never match fabric nodes for RSCNs */ | 2389 | /* Never match fabric nodes for RSCNs */ |
2397 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) | 2390 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) |
2398 | return(0); | 2391 | return 0; |
2399 | 2392 | ||
2400 | /* If we are doing a FULL RSCN rediscovery, match everything */ | 2393 | /* If we are doing a FULL RSCN rediscovery, match everything */ |
2401 | if (phba->fc_flag & FC_RSCN_DISCOVERY) { | 2394 | if (vport->fc_flag & FC_RSCN_DISCOVERY) |
2402 | return did; | 2395 | return did; |
2403 | } | ||
2404 | 2396 | ||
2405 | for (i = 0; i < phba->fc_rscn_id_cnt; i++) { | 2397 | for (i = 0; i < vport->fc_rscn_id_cnt; i++) { |
2406 | mp = phba->fc_rscn_id_list[i]; | 2398 | mp = vport->fc_rscn_id_list[i]; |
2407 | lp = (uint32_t *) mp->virt; | 2399 | lp = (uint32_t *) mp->virt; |
2408 | cmd = *lp++; | 2400 | cmd = *lp++; |
2409 | payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */ | 2401 | payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */ |
@@ -2414,44 +2406,38 @@ lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did) | |||
2414 | payload_len -= sizeof (uint32_t); | 2406 | payload_len -= sizeof (uint32_t); |
2415 | switch (rscn_did.un.b.resv) { | 2407 | switch (rscn_did.un.b.resv) { |
2416 | case 0: /* Single N_Port ID effected */ | 2408 | case 0: /* Single N_Port ID effected */ |
2417 | if (ns_did.un.word == rscn_did.un.word) { | 2409 | if (ns_did.un.word == rscn_did.un.word) |
2418 | match = did; | 2410 | match = did; |
2419 | } | ||
2420 | break; | 2411 | break; |
2421 | case 1: /* Whole N_Port Area effected */ | 2412 | case 1: /* Whole N_Port Area effected */ |
2422 | if ((ns_did.un.b.domain == rscn_did.un.b.domain) | 2413 | if ((ns_did.un.b.domain == rscn_did.un.b.domain) |
2423 | && (ns_did.un.b.area == rscn_did.un.b.area)) | 2414 | && (ns_did.un.b.area == rscn_did.un.b.area)) |
2424 | { | ||
2425 | match = did; | 2415 | match = did; |
2426 | } | ||
2427 | break; | 2416 | break; |
2428 | case 2: /* Whole N_Port Domain effected */ | 2417 | case 2: /* Whole N_Port Domain effected */ |
2429 | if (ns_did.un.b.domain == rscn_did.un.b.domain) | 2418 | if (ns_did.un.b.domain == rscn_did.un.b.domain) |
2430 | { | ||
2431 | match = did; | 2419 | match = did; |
2432 | } | ||
2433 | break; | 2420 | break; |
2434 | case 3: /* Whole Fabric effected */ | 2421 | case 3: /* Whole Fabric effected */ |
2435 | match = did; | 2422 | match = did; |
2436 | break; | 2423 | break; |
2437 | default: | 2424 | default: |
2438 | /* Unknown Identifier in RSCN list */ | 2425 | /* Unknown Identifier in RSCN node */ |
2439 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | 2426 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
2440 | "%d:0217 Unknown Identifier in " | 2427 | "%d:0217 Unknown Identifier in " |
2441 | "RSCN payload Data: x%x\n", | 2428 | "RSCN payload Data: x%x\n", |
2442 | phba->brd_no, rscn_did.un.word); | 2429 | phba->brd_no, rscn_did.un.word); |
2443 | break; | 2430 | break; |
2444 | } | 2431 | } |
2445 | if (match) { | 2432 | if (match) |
2446 | break; | 2433 | break; |
2447 | } | 2434 | } |
2448 | } | 2435 | } |
2449 | } | ||
2450 | return match; | 2436 | return match; |
2451 | } | 2437 | } |
2452 | 2438 | ||
2453 | static int | 2439 | static int |
2454 | lpfc_rscn_recovery_check(struct lpfc_hba *phba) | 2440 | lpfc_rscn_recovery_check(struct lpfc_vport *vport) |
2455 | { | 2441 | { |
2456 | struct lpfc_nodelist *ndlp = NULL; | 2442 | struct lpfc_nodelist *ndlp = NULL; |
2457 | 2443 | ||
@@ -2459,12 +2445,12 @@ lpfc_rscn_recovery_check(struct lpfc_hba *phba) | |||
2459 | * them to NPR state. | 2445 | * them to NPR state. |
2460 | */ | 2446 | */ |
2461 | 2447 | ||
2462 | list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) { | 2448 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { |
2463 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE || | 2449 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE || |
2464 | lpfc_rscn_payload_check(phba, ndlp->nlp_DID) == 0) | 2450 | lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0) |
2465 | continue; | 2451 | continue; |
2466 | 2452 | ||
2467 | lpfc_disc_state_machine(phba, ndlp, NULL, | 2453 | lpfc_disc_state_machine(vport, ndlp, NULL, |
2468 | NLP_EVT_DEVICE_RECOVERY); | 2454 | NLP_EVT_DEVICE_RECOVERY); |
2469 | 2455 | ||
2470 | /* | 2456 | /* |
@@ -2472,17 +2458,18 @@ lpfc_rscn_recovery_check(struct lpfc_hba *phba) | |||
2472 | * recovery event. | 2458 | * recovery event. |
2473 | */ | 2459 | */ |
2474 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 2460 | if (ndlp->nlp_flag & NLP_DELAY_TMO) |
2475 | lpfc_cancel_retry_delay_tmo(phba, ndlp); | 2461 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
2476 | } | 2462 | } |
2477 | 2463 | ||
2478 | return 0; | 2464 | return 0; |
2479 | } | 2465 | } |
2480 | 2466 | ||
2481 | static int | 2467 | static int |
2482 | lpfc_els_rcv_rscn(struct lpfc_hba * phba, | 2468 | lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2483 | struct lpfc_iocbq * cmdiocb, | 2469 | struct lpfc_nodelist *ndlp, uint8_t newnode) |
2484 | struct lpfc_nodelist * ndlp, uint8_t newnode) | ||
2485 | { | 2470 | { |
2471 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
2472 | struct lpfc_hba *phba = vport->phba; | ||
2486 | struct lpfc_dmabuf *pcmd; | 2473 | struct lpfc_dmabuf *pcmd; |
2487 | uint32_t *lp; | 2474 | uint32_t *lp; |
2488 | IOCB_t *icmd; | 2475 | IOCB_t *icmd; |
@@ -2503,18 +2490,18 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2503 | KERN_INFO, | 2490 | KERN_INFO, |
2504 | LOG_DISCOVERY, | 2491 | LOG_DISCOVERY, |
2505 | "%d:0214 RSCN received Data: x%x x%x x%x x%x\n", | 2492 | "%d:0214 RSCN received Data: x%x x%x x%x x%x\n", |
2506 | phba->brd_no, | 2493 | phba->brd_no, vport->fc_flag, payload_len, *lp, |
2507 | phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt); | 2494 | vport->fc_rscn_id_cnt); |
2508 | 2495 | ||
2509 | for (i = 0; i < payload_len/sizeof(uint32_t); i++) | 2496 | for (i = 0; i < payload_len/sizeof(uint32_t); i++) |
2510 | fc_host_post_event(phba->host, fc_get_event_number(), | 2497 | fc_host_post_event(shost, fc_get_event_number(), |
2511 | FCH_EVT_RSCN, lp[i]); | 2498 | FCH_EVT_RSCN, lp[i]); |
2512 | 2499 | ||
2513 | /* If we are about to begin discovery, just ACC the RSCN. | 2500 | /* If we are about to begin discovery, just ACC the RSCN. |
2514 | * Discovery processing will satisfy it. | 2501 | * Discovery processing will satisfy it. |
2515 | */ | 2502 | */ |
2516 | if (phba->hba_state <= LPFC_NS_QRY) { | 2503 | if (vport->port_state <= LPFC_NS_QRY) { |
2517 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2504 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, |
2518 | newnode); | 2505 | newnode); |
2519 | return 0; | 2506 | return 0; |
2520 | } | 2507 | } |
@@ -2522,13 +2509,13 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2522 | /* If we are already processing an RSCN, save the received | 2509 | /* If we are already processing an RSCN, save the received |
2523 | * RSCN payload buffer, cmdiocb->context2 to process later. | 2510 | * RSCN payload buffer, cmdiocb->context2 to process later. |
2524 | */ | 2511 | */ |
2525 | if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) { | 2512 | if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) { |
2526 | if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) && | 2513 | if ((vport->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) && |
2527 | !(phba->fc_flag & FC_RSCN_DISCOVERY)) { | 2514 | !(vport->fc_flag & FC_RSCN_DISCOVERY)) { |
2528 | spin_lock_irq(phba->host->host_lock); | 2515 | spin_lock_irq(shost->host_lock); |
2529 | phba->fc_flag |= FC_RSCN_MODE; | 2516 | vport->fc_flag |= FC_RSCN_MODE; |
2530 | spin_unlock_irq(phba->host->host_lock); | 2517 | spin_unlock_irq(shost->host_lock); |
2531 | phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd; | 2518 | vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd; |
2532 | 2519 | ||
2533 | /* If we zero, cmdiocb->context2, the calling | 2520 | /* If we zero, cmdiocb->context2, the calling |
2534 | * routine will not try to free it. | 2521 | * routine will not try to free it. |
@@ -2539,54 +2526,59 @@ lpfc_els_rcv_rscn(struct lpfc_hba * phba, | |||
2539 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 2526 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
2540 | "%d:0235 Deferred RSCN " | 2527 | "%d:0235 Deferred RSCN " |
2541 | "Data: x%x x%x x%x\n", | 2528 | "Data: x%x x%x x%x\n", |
2542 | phba->brd_no, phba->fc_rscn_id_cnt, | 2529 | phba->brd_no, vport->fc_rscn_id_cnt, |
2543 | phba->fc_flag, phba->hba_state); | 2530 | vport->fc_flag, |
2531 | vport->port_state); | ||
2544 | } else { | 2532 | } else { |
2545 | spin_lock_irq(phba->host->host_lock); | 2533 | spin_lock_irq(shost->host_lock); |
2546 | phba->fc_flag |= FC_RSCN_DISCOVERY; | 2534 | vport->fc_flag |= FC_RSCN_DISCOVERY; |
2547 | spin_unlock_irq(phba->host->host_lock); | 2535 | spin_unlock_irq(shost->host_lock); |
2548 | /* ReDiscovery RSCN */ | 2536 | /* ReDiscovery RSCN */ |
2549 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 2537 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
2550 | "%d:0234 ReDiscovery RSCN " | 2538 | "%d:0234 ReDiscovery RSCN " |
2551 | "Data: x%x x%x x%x\n", | 2539 | "Data: x%x x%x x%x\n", |
2552 | phba->brd_no, phba->fc_rscn_id_cnt, | 2540 | phba->brd_no, vport->fc_rscn_id_cnt, |
2553 | phba->fc_flag, phba->hba_state); | 2541 | vport->fc_flag, |
2542 | vport->port_state); | ||
2554 | } | 2543 | } |
2555 | /* Send back ACC */ | 2544 | /* Send back ACC */ |
2556 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, | 2545 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, |
2557 | newnode); | 2546 | newnode); |
2558 | 2547 | ||
2559 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2548 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2560 | lpfc_rscn_recovery_check(phba); | 2549 | lpfc_rscn_recovery_check(vport); |
2561 | return 0; | 2550 | return 0; |
2562 | } | 2551 | } |
2563 | 2552 | ||
2564 | phba->fc_flag |= FC_RSCN_MODE; | 2553 | spin_lock_irq(shost->host_lock); |
2565 | phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd; | 2554 | vport->fc_flag |= FC_RSCN_MODE; |
2555 | spin_unlock_irq(shost->host_lock); | ||
2556 | vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd; | ||
2566 | /* | 2557 | /* |
2567 | * If we zero, cmdiocb->context2, the calling routine will | 2558 | * If we zero, cmdiocb->context2, the calling routine will |
2568 | * not try to free it. | 2559 | * not try to free it. |
2569 | */ | 2560 | */ |
2570 | cmdiocb->context2 = NULL; | 2561 | cmdiocb->context2 = NULL; |
2571 | 2562 | ||
2572 | lpfc_set_disctmo(phba); | 2563 | lpfc_set_disctmo(vport); |
2573 | 2564 | ||
2574 | /* Send back ACC */ | 2565 | /* Send back ACC */ |
2575 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); | 2566 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode); |
2576 | 2567 | ||
2577 | /* send RECOVERY event for ALL nodes that match RSCN payload */ | 2568 | /* send RECOVERY event for ALL nodes that match RSCN payload */ |
2578 | lpfc_rscn_recovery_check(phba); | 2569 | lpfc_rscn_recovery_check(vport); |
2579 | 2570 | ||
2580 | return lpfc_els_handle_rscn(phba); | 2571 | return lpfc_els_handle_rscn(vport); |
2581 | } | 2572 | } |
2582 | 2573 | ||
2583 | int | 2574 | int |
2584 | lpfc_els_handle_rscn(struct lpfc_hba * phba) | 2575 | lpfc_els_handle_rscn(struct lpfc_vport *vport) |
2585 | { | 2576 | { |
2586 | struct lpfc_nodelist *ndlp; | 2577 | struct lpfc_nodelist *ndlp; |
2578 | struct lpfc_hba *phba = vport->phba; | ||
2587 | 2579 | ||
2588 | /* Start timer for RSCN processing */ | 2580 | /* Start timer for RSCN processing */ |
2589 | lpfc_set_disctmo(phba); | 2581 | lpfc_set_disctmo(vport); |
2590 | 2582 | ||
2591 | /* RSCN processed */ | 2583 | /* RSCN processed */ |
2592 | lpfc_printf_log(phba, | 2584 | lpfc_printf_log(phba, |
@@ -2594,53 +2586,53 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) | |||
2594 | LOG_DISCOVERY, | 2586 | LOG_DISCOVERY, |
2595 | "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n", | 2587 | "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n", |
2596 | phba->brd_no, | 2588 | phba->brd_no, |
2597 | phba->fc_flag, 0, phba->fc_rscn_id_cnt, | 2589 | vport->fc_flag, 0, vport->fc_rscn_id_cnt, |
2598 | phba->hba_state); | 2590 | vport->port_state); |
2599 | 2591 | ||
2600 | /* To process RSCN, first compare RSCN data with NameServer */ | 2592 | /* To process RSCN, first compare RSCN data with NameServer */ |
2601 | phba->fc_ns_retry = 0; | 2593 | vport->fc_ns_retry = 0; |
2602 | ndlp = lpfc_findnode_did(phba, NameServer_DID); | 2594 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
2603 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 2595 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { |
2604 | /* Good ndlp, issue CT Request to NameServer */ | 2596 | /* Good ndlp, issue CT Request to NameServer */ |
2605 | if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) { | 2597 | if (lpfc_ns_cmd(vport, ndlp, SLI_CTNS_GID_FT) == 0) |
2606 | /* Wait for NameServer query cmpl before we can | 2598 | /* Wait for NameServer query cmpl before we can |
2607 | continue */ | 2599 | continue */ |
2608 | return 1; | 2600 | return 1; |
2609 | } | ||
2610 | } else { | 2601 | } else { |
2611 | /* If login to NameServer does not exist, issue one */ | 2602 | /* If login to NameServer does not exist, issue one */ |
2612 | /* Good status, issue PLOGI to NameServer */ | 2603 | /* Good status, issue PLOGI to NameServer */ |
2613 | ndlp = lpfc_findnode_did(phba, NameServer_DID); | 2604 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
2614 | if (ndlp) { | 2605 | if (ndlp) |
2615 | /* Wait for NameServer login cmpl before we can | 2606 | /* Wait for NameServer login cmpl before we can |
2616 | continue */ | 2607 | continue */ |
2617 | return 1; | 2608 | return 1; |
2618 | } | 2609 | |
2619 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 2610 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
2620 | if (!ndlp) { | 2611 | if (!ndlp) { |
2621 | lpfc_els_flush_rscn(phba); | 2612 | lpfc_els_flush_rscn(vport); |
2622 | return 0; | 2613 | return 0; |
2623 | } else { | 2614 | } else { |
2624 | lpfc_nlp_init(phba, ndlp, NameServer_DID); | 2615 | lpfc_nlp_init(vport, ndlp, NameServer_DID); |
2625 | ndlp->nlp_type |= NLP_FABRIC; | 2616 | ndlp->nlp_type |= NLP_FABRIC; |
2626 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2617 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2627 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE); | 2618 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
2628 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); | 2619 | lpfc_issue_els_plogi(vport, NameServer_DID, 0); |
2629 | /* Wait for NameServer login cmpl before we can | 2620 | /* Wait for NameServer login cmpl before we can |
2630 | continue */ | 2621 | continue */ |
2631 | return 1; | 2622 | return 1; |
2632 | } | 2623 | } |
2633 | } | 2624 | } |
2634 | 2625 | ||
2635 | lpfc_els_flush_rscn(phba); | 2626 | lpfc_els_flush_rscn(vport); |
2636 | return 0; | 2627 | return 0; |
2637 | } | 2628 | } |
2638 | 2629 | ||
2639 | static int | 2630 | static int |
2640 | lpfc_els_rcv_flogi(struct lpfc_hba * phba, | 2631 | lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2641 | struct lpfc_iocbq * cmdiocb, | 2632 | struct lpfc_nodelist *ndlp, uint8_t newnode) |
2642 | struct lpfc_nodelist * ndlp, uint8_t newnode) | ||
2643 | { | 2633 | { |
2634 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
2635 | struct lpfc_hba *phba = vport->phba; | ||
2644 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 2636 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
2645 | uint32_t *lp = (uint32_t *) pcmd->virt; | 2637 | uint32_t *lp = (uint32_t *) pcmd->virt; |
2646 | IOCB_t *icmd = &cmdiocb->iocb; | 2638 | IOCB_t *icmd = &cmdiocb->iocb; |
@@ -2655,7 +2647,7 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2655 | 2647 | ||
2656 | /* FLOGI received */ | 2648 | /* FLOGI received */ |
2657 | 2649 | ||
2658 | lpfc_set_disctmo(phba); | 2650 | lpfc_set_disctmo(vport); |
2659 | 2651 | ||
2660 | if (phba->fc_topology == TOPOLOGY_LOOP) { | 2652 | if (phba->fc_topology == TOPOLOGY_LOOP) { |
2661 | /* We should never receive a FLOGI in loop mode, ignore it */ | 2653 | /* We should never receive a FLOGI in loop mode, ignore it */ |
@@ -2672,19 +2664,19 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2672 | 2664 | ||
2673 | did = Fabric_DID; | 2665 | did = Fabric_DID; |
2674 | 2666 | ||
2675 | if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) { | 2667 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) { |
2676 | /* For a FLOGI we accept, then if our portname is greater | 2668 | /* For a FLOGI we accept, then if our portname is greater |
2677 | * then the remote portname we initiate Nport login. | 2669 | * then the remote portname we initiate Nport login. |
2678 | */ | 2670 | */ |
2679 | 2671 | ||
2680 | rc = memcmp(&phba->fc_portname, &sp->portName, | 2672 | rc = memcmp(&vport->fc_portname, &sp->portName, |
2681 | sizeof (struct lpfc_name)); | 2673 | sizeof (struct lpfc_name)); |
2682 | 2674 | ||
2683 | if (!rc) { | 2675 | if (!rc) { |
2684 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, | 2676 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
2685 | GFP_KERNEL)) == 0) { | 2677 | if (!mbox) |
2686 | return 1; | 2678 | return 1; |
2687 | } | 2679 | |
2688 | lpfc_linkdown(phba); | 2680 | lpfc_linkdown(phba); |
2689 | lpfc_init_link(phba, mbox, | 2681 | lpfc_init_link(phba, mbox, |
2690 | phba->cfg_topology, | 2682 | phba->cfg_topology, |
@@ -2699,31 +2691,33 @@ lpfc_els_rcv_flogi(struct lpfc_hba * phba, | |||
2699 | } | 2691 | } |
2700 | return 1; | 2692 | return 1; |
2701 | } else if (rc > 0) { /* greater than */ | 2693 | } else if (rc > 0) { /* greater than */ |
2702 | spin_lock_irq(phba->host->host_lock); | 2694 | spin_lock_irq(shost->host_lock); |
2703 | phba->fc_flag |= FC_PT2PT_PLOGI; | 2695 | vport->fc_flag |= FC_PT2PT_PLOGI; |
2704 | spin_unlock_irq(phba->host->host_lock); | 2696 | spin_unlock_irq(shost->host_lock); |
2705 | } | 2697 | } |
2706 | phba->fc_flag |= FC_PT2PT; | 2698 | spin_lock_irq(shost->host_lock); |
2707 | phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 2699 | vport->fc_flag |= FC_PT2PT; |
2700 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | ||
2701 | spin_unlock_irq(shost->host_lock); | ||
2708 | } else { | 2702 | } else { |
2709 | /* Reject this request because invalid parameters */ | 2703 | /* Reject this request because invalid parameters */ |
2710 | stat.un.b.lsRjtRsvd0 = 0; | 2704 | stat.un.b.lsRjtRsvd0 = 0; |
2711 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2705 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2712 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; | 2706 | stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; |
2713 | stat.un.b.vendorUnique = 0; | 2707 | stat.un.b.vendorUnique = 0; |
2714 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2708 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2715 | return 1; | 2709 | return 1; |
2716 | } | 2710 | } |
2717 | 2711 | ||
2718 | /* Send back ACC */ | 2712 | /* Send back ACC */ |
2719 | lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); | 2713 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode); |
2720 | 2714 | ||
2721 | return 0; | 2715 | return 0; |
2722 | } | 2716 | } |
2723 | 2717 | ||
2724 | static int | 2718 | static int |
2725 | lpfc_els_rcv_rnid(struct lpfc_hba * phba, | 2719 | lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2726 | struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp) | 2720 | struct lpfc_nodelist *ndlp) |
2727 | { | 2721 | { |
2728 | struct lpfc_dmabuf *pcmd; | 2722 | struct lpfc_dmabuf *pcmd; |
2729 | uint32_t *lp; | 2723 | uint32_t *lp; |
@@ -2746,7 +2740,7 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, | |||
2746 | case 0: | 2740 | case 0: |
2747 | case RNID_TOPOLOGY_DISC: | 2741 | case RNID_TOPOLOGY_DISC: |
2748 | /* Send back ACC */ | 2742 | /* Send back ACC */ |
2749 | lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp); | 2743 | lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp); |
2750 | break; | 2744 | break; |
2751 | default: | 2745 | default: |
2752 | /* Reject this request because format not supported */ | 2746 | /* Reject this request because format not supported */ |
@@ -2754,14 +2748,14 @@ lpfc_els_rcv_rnid(struct lpfc_hba * phba, | |||
2754 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2748 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2755 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 2749 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
2756 | stat.un.b.vendorUnique = 0; | 2750 | stat.un.b.vendorUnique = 0; |
2757 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2751 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2758 | } | 2752 | } |
2759 | return 0; | 2753 | return 0; |
2760 | } | 2754 | } |
2761 | 2755 | ||
2762 | static int | 2756 | static int |
2763 | lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 2757 | lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2764 | struct lpfc_nodelist *ndlp) | 2758 | struct lpfc_nodelist *ndlp) |
2765 | { | 2759 | { |
2766 | struct ls_rjt stat; | 2760 | struct ls_rjt stat; |
2767 | 2761 | ||
@@ -2770,15 +2764,15 @@ lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
2770 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2764 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2771 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 2765 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
2772 | stat.un.b.vendorUnique = 0; | 2766 | stat.un.b.vendorUnique = 0; |
2773 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2767 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2774 | return 0; | 2768 | return 0; |
2775 | } | 2769 | } |
2776 | 2770 | ||
2777 | static void | 2771 | static void |
2778 | lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 2772 | lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
2779 | { | 2773 | { |
2780 | struct lpfc_sli *psli; | 2774 | struct lpfc_sli *psli = &phba->sli; |
2781 | struct lpfc_sli_ring *pring; | 2775 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
2782 | MAILBOX_t *mb; | 2776 | MAILBOX_t *mb; |
2783 | IOCB_t *icmd; | 2777 | IOCB_t *icmd; |
2784 | RPS_RSP *rps_rsp; | 2778 | RPS_RSP *rps_rsp; |
@@ -2788,8 +2782,6 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2788 | uint16_t xri, status; | 2782 | uint16_t xri, status; |
2789 | uint32_t cmdsize; | 2783 | uint32_t cmdsize; |
2790 | 2784 | ||
2791 | psli = &phba->sli; | ||
2792 | pring = &psli->ring[LPFC_ELS_RING]; | ||
2793 | mb = &pmb->mb; | 2785 | mb = &pmb->mb; |
2794 | 2786 | ||
2795 | ndlp = (struct lpfc_nodelist *) pmb->context2; | 2787 | ndlp = (struct lpfc_nodelist *) pmb->context2; |
@@ -2804,8 +2796,9 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2804 | 2796 | ||
2805 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); | 2797 | cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); |
2806 | mempool_free(pmb, phba->mbox_mem_pool); | 2798 | mempool_free(pmb, phba->mbox_mem_pool); |
2807 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp, | 2799 | elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, |
2808 | ndlp->nlp_DID, ELS_CMD_ACC); | 2800 | lpfc_max_els_tries, ndlp, |
2801 | ndlp->nlp_DID, ELS_CMD_ACC); | ||
2809 | lpfc_nlp_put(ndlp); | 2802 | lpfc_nlp_put(ndlp); |
2810 | if (!elsiocb) | 2803 | if (!elsiocb) |
2811 | return; | 2804 | return; |
@@ -2822,7 +2815,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2822 | status = 0x10; | 2815 | status = 0x10; |
2823 | else | 2816 | else |
2824 | status = 0x8; | 2817 | status = 0x8; |
2825 | if (phba->fc_flag & FC_FABRIC) | 2818 | if (phba->pport->fc_flag & FC_FABRIC) |
2826 | status |= 0x4; | 2819 | status |= 0x4; |
2827 | 2820 | ||
2828 | rps_rsp->rsvd1 = 0; | 2821 | rps_rsp->rsvd1 = 0; |
@@ -2852,9 +2845,10 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2852 | } | 2845 | } |
2853 | 2846 | ||
2854 | static int | 2847 | static int |
2855 | lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2848 | lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2856 | struct lpfc_nodelist * ndlp) | 2849 | struct lpfc_nodelist *ndlp) |
2857 | { | 2850 | { |
2851 | struct lpfc_hba *phba = vport->phba; | ||
2858 | uint32_t *lp; | 2852 | uint32_t *lp; |
2859 | uint8_t flag; | 2853 | uint8_t flag; |
2860 | LPFC_MBOXQ_t *mbox; | 2854 | LPFC_MBOXQ_t *mbox; |
@@ -2868,7 +2862,7 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2868 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2862 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2869 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 2863 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
2870 | stat.un.b.vendorUnique = 0; | 2864 | stat.un.b.vendorUnique = 0; |
2871 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2865 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2872 | } | 2866 | } |
2873 | 2867 | ||
2874 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 2868 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
@@ -2878,19 +2872,21 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2878 | 2872 | ||
2879 | if ((flag == 0) || | 2873 | if ((flag == 0) || |
2880 | ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || | 2874 | ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || |
2881 | ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname, | 2875 | ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname, |
2882 | sizeof (struct lpfc_name)) == 0))) { | 2876 | sizeof (struct lpfc_name)) == 0))) { |
2883 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) { | 2877 | |
2878 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); | ||
2879 | if (mbox) { | ||
2884 | lpfc_read_lnk_stat(phba, mbox); | 2880 | lpfc_read_lnk_stat(phba, mbox); |
2885 | mbox->context1 = | 2881 | mbox->context1 = |
2886 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); | 2882 | (void *)((unsigned long)cmdiocb->iocb.ulpContext); |
2887 | mbox->context2 = lpfc_nlp_get(ndlp); | 2883 | mbox->context2 = lpfc_nlp_get(ndlp); |
2888 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; | 2884 | mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; |
2889 | if (lpfc_sli_issue_mbox (phba, mbox, | 2885 | if (lpfc_sli_issue_mbox (phba, mbox, |
2890 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) { | 2886 | (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) |
2891 | /* Mbox completion will send ELS Response */ | 2887 | /* Mbox completion will send ELS Response */ |
2892 | return 0; | 2888 | return 0; |
2893 | } | 2889 | |
2894 | lpfc_nlp_put(ndlp); | 2890 | lpfc_nlp_put(ndlp); |
2895 | mempool_free(mbox, phba->mbox_mem_pool); | 2891 | mempool_free(mbox, phba->mbox_mem_pool); |
2896 | } | 2892 | } |
@@ -2899,27 +2895,25 @@ lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2899 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2895 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2900 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 2896 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
2901 | stat.un.b.vendorUnique = 0; | 2897 | stat.un.b.vendorUnique = 0; |
2902 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2898 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2903 | return 0; | 2899 | return 0; |
2904 | } | 2900 | } |
2905 | 2901 | ||
2906 | static int | 2902 | static int |
2907 | lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, | 2903 | lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, |
2908 | struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp) | 2904 | struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) |
2909 | { | 2905 | { |
2910 | IOCB_t *icmd; | 2906 | struct lpfc_hba *phba = vport->phba; |
2911 | IOCB_t *oldcmd; | 2907 | IOCB_t *icmd, *oldcmd; |
2912 | RPL_RSP rpl_rsp; | 2908 | RPL_RSP rpl_rsp; |
2913 | struct lpfc_iocbq *elsiocb; | 2909 | struct lpfc_iocbq *elsiocb; |
2914 | struct lpfc_sli_ring *pring; | 2910 | struct lpfc_sli *psli = &phba->sli; |
2915 | struct lpfc_sli *psli; | 2911 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
2916 | uint8_t *pcmd; | 2912 | uint8_t *pcmd; |
2917 | 2913 | ||
2918 | psli = &phba->sli; | 2914 | elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, |
2919 | pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ | 2915 | ndlp->nlp_DID, ELS_CMD_ACC); |
2920 | 2916 | ||
2921 | elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, | ||
2922 | ndlp, ndlp->nlp_DID, ELS_CMD_ACC); | ||
2923 | if (!elsiocb) | 2917 | if (!elsiocb) |
2924 | return 1; | 2918 | return 1; |
2925 | 2919 | ||
@@ -2937,8 +2931,8 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, | |||
2937 | rpl_rsp.listLen = be32_to_cpu(1); | 2931 | rpl_rsp.listLen = be32_to_cpu(1); |
2938 | rpl_rsp.index = 0; | 2932 | rpl_rsp.index = 0; |
2939 | rpl_rsp.port_num_blk.portNum = 0; | 2933 | rpl_rsp.port_num_blk.portNum = 0; |
2940 | rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID); | 2934 | rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID); |
2941 | memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname, | 2935 | memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname, |
2942 | sizeof(struct lpfc_name)); | 2936 | sizeof(struct lpfc_name)); |
2943 | 2937 | ||
2944 | memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); | 2938 | memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t)); |
@@ -2963,8 +2957,8 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, | |||
2963 | } | 2957 | } |
2964 | 2958 | ||
2965 | static int | 2959 | static int |
2966 | lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 2960 | lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
2967 | struct lpfc_nodelist * ndlp) | 2961 | struct lpfc_nodelist *ndlp) |
2968 | { | 2962 | { |
2969 | struct lpfc_dmabuf *pcmd; | 2963 | struct lpfc_dmabuf *pcmd; |
2970 | uint32_t *lp; | 2964 | uint32_t *lp; |
@@ -2979,7 +2973,7 @@ lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2979 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 2973 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
2980 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; | 2974 | stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
2981 | stat.un.b.vendorUnique = 0; | 2975 | stat.un.b.vendorUnique = 0; |
2982 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp); | 2976 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); |
2983 | } | 2977 | } |
2984 | 2978 | ||
2985 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 2979 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
@@ -2996,15 +2990,16 @@ lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
2996 | } else { | 2990 | } else { |
2997 | cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); | 2991 | cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t); |
2998 | } | 2992 | } |
2999 | lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp); | 2993 | lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp); |
3000 | 2994 | ||
3001 | return 0; | 2995 | return 0; |
3002 | } | 2996 | } |
3003 | 2997 | ||
3004 | static int | 2998 | static int |
3005 | lpfc_els_rcv_farp(struct lpfc_hba * phba, | 2999 | lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
3006 | struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp) | 3000 | struct lpfc_nodelist *ndlp) |
3007 | { | 3001 | { |
3002 | struct lpfc_hba *phba = vport->phba; | ||
3008 | struct lpfc_dmabuf *pcmd; | 3003 | struct lpfc_dmabuf *pcmd; |
3009 | uint32_t *lp; | 3004 | uint32_t *lp; |
3010 | IOCB_t *icmd; | 3005 | IOCB_t *icmd; |
@@ -3034,14 +3029,14 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
3034 | cnt = 0; | 3029 | cnt = 0; |
3035 | /* If this FARP command is searching for my portname */ | 3030 | /* If this FARP command is searching for my portname */ |
3036 | if (fp->Mflags & FARP_MATCH_PORT) { | 3031 | if (fp->Mflags & FARP_MATCH_PORT) { |
3037 | if (memcmp(&fp->RportName, &phba->fc_portname, | 3032 | if (memcmp(&fp->RportName, &vport->fc_portname, |
3038 | sizeof (struct lpfc_name)) == 0) | 3033 | sizeof (struct lpfc_name)) == 0) |
3039 | cnt = 1; | 3034 | cnt = 1; |
3040 | } | 3035 | } |
3041 | 3036 | ||
3042 | /* If this FARP command is searching for my nodename */ | 3037 | /* If this FARP command is searching for my nodename */ |
3043 | if (fp->Mflags & FARP_MATCH_NODE) { | 3038 | if (fp->Mflags & FARP_MATCH_NODE) { |
3044 | if (memcmp(&fp->RnodeName, &phba->fc_nodename, | 3039 | if (memcmp(&fp->RnodeName, &vport->fc_nodename, |
3045 | sizeof (struct lpfc_name)) == 0) | 3040 | sizeof (struct lpfc_name)) == 0) |
3046 | cnt = 1; | 3041 | cnt = 1; |
3047 | } | 3042 | } |
@@ -3052,28 +3047,28 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
3052 | /* Log back into the node before sending the FARP. */ | 3047 | /* Log back into the node before sending the FARP. */ |
3053 | if (fp->Rflags & FARP_REQUEST_PLOGI) { | 3048 | if (fp->Rflags & FARP_REQUEST_PLOGI) { |
3054 | ndlp->nlp_prev_state = ndlp->nlp_state; | 3049 | ndlp->nlp_prev_state = ndlp->nlp_state; |
3055 | lpfc_nlp_set_state(phba, ndlp, | 3050 | lpfc_nlp_set_state(vport, ndlp, |
3056 | NLP_STE_PLOGI_ISSUE); | 3051 | NLP_STE_PLOGI_ISSUE); |
3057 | lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0); | 3052 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
3058 | } | 3053 | } |
3059 | 3054 | ||
3060 | /* Send a FARP response to that node */ | 3055 | /* Send a FARP response to that node */ |
3061 | if (fp->Rflags & FARP_REQUEST_FARPR) { | 3056 | if (fp->Rflags & FARP_REQUEST_FARPR) |
3062 | lpfc_issue_els_farpr(phba, did, 0); | 3057 | lpfc_issue_els_farpr(vport, did, 0); |
3063 | } | ||
3064 | } | 3058 | } |
3065 | } | 3059 | } |
3066 | return 0; | 3060 | return 0; |
3067 | } | 3061 | } |
3068 | 3062 | ||
3069 | static int | 3063 | static int |
3070 | lpfc_els_rcv_farpr(struct lpfc_hba * phba, | 3064 | lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
3071 | struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp) | 3065 | struct lpfc_nodelist *ndlp) |
3072 | { | 3066 | { |
3073 | struct lpfc_dmabuf *pcmd; | 3067 | struct lpfc_dmabuf *pcmd; |
3074 | uint32_t *lp; | 3068 | uint32_t *lp; |
3075 | IOCB_t *icmd; | 3069 | IOCB_t *icmd; |
3076 | uint32_t cmd, did; | 3070 | uint32_t cmd, did; |
3071 | struct lpfc_hba *phba = vport->phba; | ||
3077 | 3072 | ||
3078 | icmd = &cmdiocb->iocb; | 3073 | icmd = &cmdiocb->iocb; |
3079 | did = icmd->un.elsreq64.remoteID; | 3074 | did = icmd->un.elsreq64.remoteID; |
@@ -3089,14 +3084,14 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba, | |||
3089 | phba->brd_no, did); | 3084 | phba->brd_no, did); |
3090 | 3085 | ||
3091 | /* ACCEPT the Farp resp request */ | 3086 | /* ACCEPT the Farp resp request */ |
3092 | lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); | 3087 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); |
3093 | 3088 | ||
3094 | return 0; | 3089 | return 0; |
3095 | } | 3090 | } |
3096 | 3091 | ||
3097 | static int | 3092 | static int |
3098 | lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 3093 | lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
3099 | struct lpfc_nodelist * fan_ndlp) | 3094 | struct lpfc_nodelist *fan_ndlp) |
3100 | { | 3095 | { |
3101 | struct lpfc_dmabuf *pcmd; | 3096 | struct lpfc_dmabuf *pcmd; |
3102 | uint32_t *lp; | 3097 | uint32_t *lp; |
@@ -3104,6 +3099,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3104 | uint32_t cmd, did; | 3099 | uint32_t cmd, did; |
3105 | FAN *fp; | 3100 | FAN *fp; |
3106 | struct lpfc_nodelist *ndlp, *next_ndlp; | 3101 | struct lpfc_nodelist *ndlp, *next_ndlp; |
3102 | struct lpfc_hba *phba = vport->phba; | ||
3107 | 3103 | ||
3108 | /* FAN received */ | 3104 | /* FAN received */ |
3109 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", | 3105 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", |
@@ -3119,7 +3115,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3119 | 3115 | ||
3120 | /* FAN received; Fan does not have a reply sequence */ | 3116 | /* FAN received; Fan does not have a reply sequence */ |
3121 | 3117 | ||
3122 | if (phba->hba_state == LPFC_LOCAL_CFG_LINK) { | 3118 | if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) { |
3123 | if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, | 3119 | if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, |
3124 | sizeof(struct lpfc_name)) != 0) || | 3120 | sizeof(struct lpfc_name)) != 0) || |
3125 | (memcmp(&phba->fc_fabparam.portName, &fp->FportName, | 3121 | (memcmp(&phba->fc_fabparam.portName, &fp->FportName, |
@@ -3130,7 +3126,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3130 | */ | 3126 | */ |
3131 | 3127 | ||
3132 | list_for_each_entry_safe(ndlp, next_ndlp, | 3128 | list_for_each_entry_safe(ndlp, next_ndlp, |
3133 | &phba->fc_nodes, nlp_listp) { | 3129 | &vport->fc_nodes, nlp_listp) { |
3134 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | 3130 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) |
3135 | continue; | 3131 | continue; |
3136 | if (ndlp->nlp_type & NLP_FABRIC) { | 3132 | if (ndlp->nlp_type & NLP_FABRIC) { |
@@ -3138,24 +3134,24 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3138 | * Clean up old Fabric, Nameserver and | 3134 | * Clean up old Fabric, Nameserver and |
3139 | * other NLP_FABRIC logins | 3135 | * other NLP_FABRIC logins |
3140 | */ | 3136 | */ |
3141 | lpfc_drop_node(phba, ndlp); | 3137 | lpfc_drop_node(vport, ndlp); |
3142 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | 3138 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { |
3143 | /* Fail outstanding I/O now since this | 3139 | /* Fail outstanding I/O now since this |
3144 | * device is marked for PLOGI | 3140 | * device is marked for PLOGI |
3145 | */ | 3141 | */ |
3146 | lpfc_unreg_rpi(phba, ndlp); | 3142 | lpfc_unreg_rpi(vport, ndlp); |
3147 | } | 3143 | } |
3148 | } | 3144 | } |
3149 | 3145 | ||
3150 | phba->hba_state = LPFC_FLOGI; | 3146 | vport->port_state = LPFC_FLOGI; |
3151 | lpfc_set_disctmo(phba); | 3147 | lpfc_set_disctmo(vport); |
3152 | lpfc_initial_flogi(phba); | 3148 | lpfc_initial_flogi(vport); |
3153 | return 0; | 3149 | return 0; |
3154 | } | 3150 | } |
3155 | /* Discovery not needed, | 3151 | /* Discovery not needed, |
3156 | * move the nodes to their original state. | 3152 | * move the nodes to their original state. |
3157 | */ | 3153 | */ |
3158 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, | 3154 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, |
3159 | nlp_listp) { | 3155 | nlp_listp) { |
3160 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | 3156 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) |
3161 | continue; | 3157 | continue; |
@@ -3163,13 +3159,13 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3163 | switch (ndlp->nlp_prev_state) { | 3159 | switch (ndlp->nlp_prev_state) { |
3164 | case NLP_STE_UNMAPPED_NODE: | 3160 | case NLP_STE_UNMAPPED_NODE: |
3165 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 3161 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
3166 | lpfc_nlp_set_state(phba, ndlp, | 3162 | lpfc_nlp_set_state(vport, ndlp, |
3167 | NLP_STE_UNMAPPED_NODE); | 3163 | NLP_STE_UNMAPPED_NODE); |
3168 | break; | 3164 | break; |
3169 | 3165 | ||
3170 | case NLP_STE_MAPPED_NODE: | 3166 | case NLP_STE_MAPPED_NODE: |
3171 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 3167 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
3172 | lpfc_nlp_set_state(phba, ndlp, | 3168 | lpfc_nlp_set_state(vport, ndlp, |
3173 | NLP_STE_MAPPED_NODE); | 3169 | NLP_STE_MAPPED_NODE); |
3174 | break; | 3170 | break; |
3175 | 3171 | ||
@@ -3179,7 +3175,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3179 | } | 3175 | } |
3180 | 3176 | ||
3181 | /* Start discovery - this should just do CLEAR_LA */ | 3177 | /* Start discovery - this should just do CLEAR_LA */ |
3182 | lpfc_disc_start(phba); | 3178 | lpfc_disc_start(vport); |
3183 | } | 3179 | } |
3184 | return 0; | 3180 | return 0; |
3185 | } | 3181 | } |
@@ -3187,42 +3183,37 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
3187 | void | 3183 | void |
3188 | lpfc_els_timeout(unsigned long ptr) | 3184 | lpfc_els_timeout(unsigned long ptr) |
3189 | { | 3185 | { |
3190 | struct lpfc_hba *phba; | 3186 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; |
3187 | struct lpfc_hba *phba = vport->phba; | ||
3191 | unsigned long iflag; | 3188 | unsigned long iflag; |
3192 | 3189 | ||
3193 | phba = (struct lpfc_hba *)ptr; | 3190 | spin_lock_irqsave(&vport->work_port_lock, iflag); |
3194 | if (phba == 0) | 3191 | if ((vport->work_port_events & WORKER_ELS_TMO) == 0) { |
3195 | return; | 3192 | vport->work_port_events |= WORKER_ELS_TMO; |
3196 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
3197 | if (!(phba->work_hba_events & WORKER_ELS_TMO)) { | ||
3198 | phba->work_hba_events |= WORKER_ELS_TMO; | ||
3199 | if (phba->work_wait) | 3193 | if (phba->work_wait) |
3200 | wake_up(phba->work_wait); | 3194 | wake_up(phba->work_wait); |
3201 | } | 3195 | } |
3202 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | 3196 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); |
3203 | return; | 3197 | return; |
3204 | } | 3198 | } |
3205 | 3199 | ||
3206 | void | 3200 | void |
3207 | lpfc_els_timeout_handler(struct lpfc_hba *phba) | 3201 | lpfc_els_timeout_handler(struct lpfc_vport *vport) |
3208 | { | 3202 | { |
3203 | struct lpfc_hba *phba = vport->phba; | ||
3209 | struct lpfc_sli_ring *pring; | 3204 | struct lpfc_sli_ring *pring; |
3210 | struct lpfc_iocbq *tmp_iocb, *piocb; | 3205 | struct lpfc_iocbq *tmp_iocb, *piocb; |
3211 | IOCB_t *cmd = NULL; | 3206 | IOCB_t *cmd = NULL; |
3212 | struct lpfc_dmabuf *pcmd; | 3207 | struct lpfc_dmabuf *pcmd; |
3213 | uint32_t *elscmd; | 3208 | uint32_t els_command = 0; |
3214 | uint32_t els_command=0; | ||
3215 | uint32_t timeout; | 3209 | uint32_t timeout; |
3216 | uint32_t remote_ID; | 3210 | uint32_t remote_ID = 0xffffffff; |
3217 | 3211 | ||
3218 | if (phba == 0) | ||
3219 | return; | ||
3220 | spin_lock_irq(phba->host->host_lock); | ||
3221 | /* If the timer is already canceled do nothing */ | 3212 | /* If the timer is already canceled do nothing */ |
3222 | if (!(phba->work_hba_events & WORKER_ELS_TMO)) { | 3213 | if ((vport->work_port_events & WORKER_ELS_TMO) == 0) { |
3223 | spin_unlock_irq(phba->host->host_lock); | ||
3224 | return; | 3214 | return; |
3225 | } | 3215 | } |
3216 | spin_lock_irq(&phba->hbalock); | ||
3226 | timeout = (uint32_t)(phba->fc_ratov << 1); | 3217 | timeout = (uint32_t)(phba->fc_ratov << 1); |
3227 | 3218 | ||
3228 | pring = &phba->sli.ring[LPFC_ELS_RING]; | 3219 | pring = &phba->sli.ring[LPFC_ELS_RING]; |
@@ -3230,16 +3221,17 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3230 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 3221 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
3231 | cmd = &piocb->iocb; | 3222 | cmd = &piocb->iocb; |
3232 | 3223 | ||
3233 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) || | 3224 | if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 || |
3234 | (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) || | 3225 | piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN || |
3235 | (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) { | 3226 | piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) |
3236 | continue; | 3227 | continue; |
3237 | } | 3228 | |
3229 | if (piocb->vport != vport) | ||
3230 | continue; | ||
3231 | |||
3238 | pcmd = (struct lpfc_dmabuf *) piocb->context2; | 3232 | pcmd = (struct lpfc_dmabuf *) piocb->context2; |
3239 | if (pcmd) { | 3233 | if (pcmd) |
3240 | elscmd = (uint32_t *) (pcmd->virt); | 3234 | els_command = *(uint32_t *) (pcmd->virt); |
3241 | els_command = *elscmd; | ||
3242 | } | ||
3243 | 3235 | ||
3244 | if ((els_command == ELS_CMD_FARP) | 3236 | if ((els_command == ELS_CMD_FARP) |
3245 | || (els_command == ELS_CMD_FARPR)) { | 3237 | || (els_command == ELS_CMD_FARPR)) { |
@@ -3255,12 +3247,14 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3255 | continue; | 3247 | continue; |
3256 | } | 3248 | } |
3257 | 3249 | ||
3258 | if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) { | 3250 | remote_ID = 0xffffffff; |
3259 | struct lpfc_nodelist *ndlp; | 3251 | if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR) |
3260 | ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext); | ||
3261 | remote_ID = ndlp->nlp_DID; | ||
3262 | } else { | ||
3263 | remote_ID = cmd->un.elsreq64.remoteID; | 3252 | remote_ID = cmd->un.elsreq64.remoteID; |
3253 | else { | ||
3254 | struct lpfc_nodelist *ndlp; | ||
3255 | ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext); | ||
3256 | if (ndlp) | ||
3257 | remote_ID = ndlp->nlp_DID; | ||
3264 | } | 3258 | } |
3265 | 3259 | ||
3266 | lpfc_printf_log(phba, | 3260 | lpfc_printf_log(phba, |
@@ -3272,21 +3266,22 @@ lpfc_els_timeout_handler(struct lpfc_hba *phba) | |||
3272 | 3266 | ||
3273 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | 3267 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); |
3274 | } | 3268 | } |
3275 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) | 3269 | spin_unlock_irq(&phba->hbalock); |
3276 | mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout); | ||
3277 | 3270 | ||
3278 | spin_unlock_irq(phba->host->host_lock); | 3271 | if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) |
3272 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | ||
3279 | } | 3273 | } |
3280 | 3274 | ||
3281 | void | 3275 | void |
3282 | lpfc_els_flush_cmd(struct lpfc_hba *phba) | 3276 | lpfc_els_flush_cmd(struct lpfc_vport *vport) |
3283 | { | 3277 | { |
3284 | LIST_HEAD(completions); | 3278 | LIST_HEAD(completions); |
3279 | struct lpfc_hba *phba = vport->phba; | ||
3285 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; | 3280 | struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; |
3286 | struct lpfc_iocbq *tmp_iocb, *piocb; | 3281 | struct lpfc_iocbq *tmp_iocb, *piocb; |
3287 | IOCB_t *cmd = NULL; | 3282 | IOCB_t *cmd = NULL; |
3288 | 3283 | ||
3289 | spin_lock_irq(phba->host->host_lock); | 3284 | spin_lock_irq(&phba->hbalock); |
3290 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { | 3285 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { |
3291 | cmd = &piocb->iocb; | 3286 | cmd = &piocb->iocb; |
3292 | 3287 | ||
@@ -3301,61 +3296,63 @@ lpfc_els_flush_cmd(struct lpfc_hba *phba) | |||
3301 | cmd->ulpCommand == CMD_ABORT_XRI_CN) | 3296 | cmd->ulpCommand == CMD_ABORT_XRI_CN) |
3302 | continue; | 3297 | continue; |
3303 | 3298 | ||
3299 | if (piocb->vport != vport) | ||
3300 | continue; | ||
3301 | |||
3304 | list_move_tail(&piocb->list, &completions); | 3302 | list_move_tail(&piocb->list, &completions); |
3305 | pring->txq_cnt--; | 3303 | pring->txq_cnt--; |
3306 | |||
3307 | } | 3304 | } |
3308 | 3305 | ||
3309 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { | 3306 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
3310 | cmd = &piocb->iocb; | ||
3311 | |||
3312 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) { | 3307 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) { |
3313 | continue; | 3308 | continue; |
3314 | } | 3309 | } |
3315 | 3310 | ||
3311 | if (piocb->vport != vport) | ||
3312 | continue; | ||
3313 | |||
3316 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); | 3314 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); |
3317 | } | 3315 | } |
3318 | spin_unlock_irq(phba->host->host_lock); | 3316 | spin_unlock_irq(&phba->hbalock); |
3319 | 3317 | ||
3320 | while(!list_empty(&completions)) { | 3318 | while (!list_empty(&completions)) { |
3321 | piocb = list_get_first(&completions, struct lpfc_iocbq, list); | 3319 | piocb = list_get_first(&completions, struct lpfc_iocbq, list); |
3322 | cmd = &piocb->iocb; | 3320 | cmd = &piocb->iocb; |
3323 | list_del(&piocb->list); | 3321 | list_del(&piocb->list); |
3324 | 3322 | ||
3325 | if (piocb->iocb_cmpl) { | 3323 | if (!piocb->iocb_cmpl) |
3324 | lpfc_sli_release_iocbq(phba, piocb); | ||
3325 | else { | ||
3326 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | 3326 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; |
3327 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | 3327 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; |
3328 | (piocb->iocb_cmpl) (phba, piocb, piocb); | 3328 | (piocb->iocb_cmpl) (phba, piocb, piocb); |
3329 | } else | 3329 | } |
3330 | lpfc_sli_release_iocbq(phba, piocb); | ||
3331 | } | 3330 | } |
3332 | 3331 | ||
3333 | return; | 3332 | return; |
3334 | } | 3333 | } |
3335 | 3334 | ||
3336 | void | 3335 | void |
3337 | lpfc_els_unsol_event(struct lpfc_hba * phba, | 3336 | lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
3338 | struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb) | 3337 | struct lpfc_iocbq *elsiocb) |
3339 | { | 3338 | { |
3340 | struct lpfc_sli *psli; | 3339 | struct lpfc_sli *psli; |
3341 | struct lpfc_nodelist *ndlp; | 3340 | struct lpfc_nodelist *ndlp; |
3342 | struct lpfc_dmabuf *mp; | 3341 | struct lpfc_dmabuf *mp = NULL; |
3343 | uint32_t *lp; | 3342 | uint32_t *lp; |
3344 | IOCB_t *icmd; | 3343 | IOCB_t *icmd; |
3345 | struct ls_rjt stat; | 3344 | struct ls_rjt stat; |
3346 | uint32_t cmd; | 3345 | uint32_t cmd, did, newnode, rjt_err = 0; |
3347 | uint32_t did; | ||
3348 | uint32_t newnode; | ||
3349 | uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */ | 3346 | uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */ |
3350 | uint32_t rjt_err = 0; | 3347 | struct lpfc_vport *vport = NULL; |
3351 | 3348 | ||
3352 | psli = &phba->sli; | 3349 | psli = &phba->sli; |
3353 | icmd = &elsiocb->iocb; | 3350 | icmd = &elsiocb->iocb; |
3354 | 3351 | ||
3355 | if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && | 3352 | if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && |
3356 | ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { | 3353 | ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { |
3357 | /* Not enough posted buffers; Try posting more buffers */ | ||
3358 | phba->fc_stat.NoRcvBuf++; | 3354 | phba->fc_stat.NoRcvBuf++; |
3355 | /* Not enough posted buffers; Try posting more buffers */ | ||
3359 | lpfc_post_buffer(phba, pring, 0, 1); | 3356 | lpfc_post_buffer(phba, pring, 0, 1); |
3360 | return; | 3357 | return; |
3361 | } | 3358 | } |
@@ -3366,17 +3363,17 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3366 | if (icmd->ulpBdeCount == 0) | 3363 | if (icmd->ulpBdeCount == 0) |
3367 | return; | 3364 | return; |
3368 | 3365 | ||
3369 | /* type of ELS cmd is first 32bit word in packet */ | 3366 | /* type of ELS cmd is first 32bit word in packet */ |
3370 | mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un. | 3367 | mp = lpfc_sli_ringpostbuf_get(phba, pring, |
3371 | cont64[0]. | 3368 | getPaddr(icmd->un.cont64[0].addrHigh, |
3372 | addrHigh, | 3369 | icmd->un.cont64[0].addrLow)); |
3373 | icmd->un. | ||
3374 | cont64[0].addrLow)); | ||
3375 | if (mp == 0) { | 3370 | if (mp == 0) { |
3376 | drop_cmd = 1; | 3371 | drop_cmd = 1; |
3377 | goto dropit; | 3372 | goto dropit; |
3378 | } | 3373 | } |
3379 | 3374 | ||
3375 | vport = phba->pport; | ||
3376 | |||
3380 | newnode = 0; | 3377 | newnode = 0; |
3381 | lp = (uint32_t *) mp->virt; | 3378 | lp = (uint32_t *) mp->virt; |
3382 | cmd = *lp++; | 3379 | cmd = *lp++; |
@@ -3390,7 +3387,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3390 | } | 3387 | } |
3391 | 3388 | ||
3392 | /* Check to see if link went down during discovery */ | 3389 | /* Check to see if link went down during discovery */ |
3393 | if (lpfc_els_chk_latt(phba)) { | 3390 | if (lpfc_els_chk_latt(vport)) { |
3394 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 3391 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
3395 | kfree(mp); | 3392 | kfree(mp); |
3396 | drop_cmd = 1; | 3393 | drop_cmd = 1; |
@@ -3398,7 +3395,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3398 | } | 3395 | } |
3399 | 3396 | ||
3400 | did = icmd->un.rcvels.remoteID; | 3397 | did = icmd->un.rcvels.remoteID; |
3401 | ndlp = lpfc_findnode_did(phba, did); | 3398 | ndlp = lpfc_findnode_did(vport, did); |
3402 | if (!ndlp) { | 3399 | if (!ndlp) { |
3403 | /* Cannot find existing Fabric ndlp, so allocate a new one */ | 3400 | /* Cannot find existing Fabric ndlp, so allocate a new one */ |
3404 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); | 3401 | ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); |
@@ -3409,12 +3406,12 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3409 | goto dropit; | 3406 | goto dropit; |
3410 | } | 3407 | } |
3411 | 3408 | ||
3412 | lpfc_nlp_init(phba, ndlp, did); | 3409 | lpfc_nlp_init(vport, ndlp, did); |
3413 | newnode = 1; | 3410 | newnode = 1; |
3414 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { | 3411 | if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) { |
3415 | ndlp->nlp_type |= NLP_FABRIC; | 3412 | ndlp->nlp_type |= NLP_FABRIC; |
3416 | } | 3413 | } |
3417 | lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE); | 3414 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
3418 | } | 3415 | } |
3419 | 3416 | ||
3420 | phba->fc_stat.elsRcvFrame++; | 3417 | phba->fc_stat.elsRcvFrame++; |
@@ -3422,6 +3419,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3422 | lpfc_nlp_put(elsiocb->context1); | 3419 | lpfc_nlp_put(elsiocb->context1); |
3423 | elsiocb->context1 = lpfc_nlp_get(ndlp); | 3420 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
3424 | elsiocb->context2 = mp; | 3421 | elsiocb->context2 = mp; |
3422 | elsiocb->vport = vport; | ||
3425 | 3423 | ||
3426 | if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { | 3424 | if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { |
3427 | cmd &= ELS_CMD_MASK; | 3425 | cmd &= ELS_CMD_MASK; |
@@ -3429,105 +3427,109 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3429 | /* ELS command <elsCmd> received from NPORT <did> */ | 3427 | /* ELS command <elsCmd> received from NPORT <did> */ |
3430 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 3428 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
3431 | "%d:0112 ELS command x%x received from NPORT x%x " | 3429 | "%d:0112 ELS command x%x received from NPORT x%x " |
3432 | "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state); | 3430 | "Data: x%x\n", phba->brd_no, cmd, did, |
3431 | vport->port_state); | ||
3433 | 3432 | ||
3434 | switch (cmd) { | 3433 | switch (cmd) { |
3435 | case ELS_CMD_PLOGI: | 3434 | case ELS_CMD_PLOGI: |
3436 | phba->fc_stat.elsRcvPLOGI++; | 3435 | phba->fc_stat.elsRcvPLOGI++; |
3437 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3436 | if (vport->port_state < LPFC_DISC_AUTH) { |
3438 | rjt_err = 1; | 3437 | rjt_err = 1; |
3439 | break; | 3438 | break; |
3440 | } | 3439 | } |
3441 | ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp); | 3440 | ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp); |
3442 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI); | 3441 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
3442 | NLP_EVT_RCV_PLOGI); | ||
3443 | break; | 3443 | break; |
3444 | case ELS_CMD_FLOGI: | 3444 | case ELS_CMD_FLOGI: |
3445 | phba->fc_stat.elsRcvFLOGI++; | 3445 | phba->fc_stat.elsRcvFLOGI++; |
3446 | lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode); | 3446 | lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode); |
3447 | if (newnode) | 3447 | if (newnode) |
3448 | lpfc_drop_node(phba, ndlp); | 3448 | lpfc_drop_node(vport, ndlp); |
3449 | break; | 3449 | break; |
3450 | case ELS_CMD_LOGO: | 3450 | case ELS_CMD_LOGO: |
3451 | phba->fc_stat.elsRcvLOGO++; | 3451 | phba->fc_stat.elsRcvLOGO++; |
3452 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3452 | if (vport->port_state < LPFC_DISC_AUTH) { |
3453 | rjt_err = 1; | 3453 | rjt_err = 1; |
3454 | break; | 3454 | break; |
3455 | } | 3455 | } |
3456 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO); | 3456 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO); |
3457 | break; | 3457 | break; |
3458 | case ELS_CMD_PRLO: | 3458 | case ELS_CMD_PRLO: |
3459 | phba->fc_stat.elsRcvPRLO++; | 3459 | phba->fc_stat.elsRcvPRLO++; |
3460 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3460 | if (vport->port_state < LPFC_DISC_AUTH) { |
3461 | rjt_err = 1; | 3461 | rjt_err = 1; |
3462 | break; | 3462 | break; |
3463 | } | 3463 | } |
3464 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO); | 3464 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO); |
3465 | break; | 3465 | break; |
3466 | case ELS_CMD_RSCN: | 3466 | case ELS_CMD_RSCN: |
3467 | phba->fc_stat.elsRcvRSCN++; | 3467 | phba->fc_stat.elsRcvRSCN++; |
3468 | lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode); | 3468 | lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode); |
3469 | if (newnode) | 3469 | if (newnode) |
3470 | lpfc_drop_node(phba, ndlp); | 3470 | lpfc_drop_node(vport, ndlp); |
3471 | break; | 3471 | break; |
3472 | case ELS_CMD_ADISC: | 3472 | case ELS_CMD_ADISC: |
3473 | phba->fc_stat.elsRcvADISC++; | 3473 | phba->fc_stat.elsRcvADISC++; |
3474 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3474 | if (vport->port_state < LPFC_DISC_AUTH) { |
3475 | rjt_err = 1; | 3475 | rjt_err = 1; |
3476 | break; | 3476 | break; |
3477 | } | 3477 | } |
3478 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC); | 3478 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
3479 | NLP_EVT_RCV_ADISC); | ||
3479 | break; | 3480 | break; |
3480 | case ELS_CMD_PDISC: | 3481 | case ELS_CMD_PDISC: |
3481 | phba->fc_stat.elsRcvPDISC++; | 3482 | phba->fc_stat.elsRcvPDISC++; |
3482 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3483 | if (vport->port_state < LPFC_DISC_AUTH) { |
3483 | rjt_err = 1; | 3484 | rjt_err = 1; |
3484 | break; | 3485 | break; |
3485 | } | 3486 | } |
3486 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC); | 3487 | lpfc_disc_state_machine(vport, ndlp, elsiocb, |
3488 | NLP_EVT_RCV_PDISC); | ||
3487 | break; | 3489 | break; |
3488 | case ELS_CMD_FARPR: | 3490 | case ELS_CMD_FARPR: |
3489 | phba->fc_stat.elsRcvFARPR++; | 3491 | phba->fc_stat.elsRcvFARPR++; |
3490 | lpfc_els_rcv_farpr(phba, elsiocb, ndlp); | 3492 | lpfc_els_rcv_farpr(vport, elsiocb, ndlp); |
3491 | break; | 3493 | break; |
3492 | case ELS_CMD_FARP: | 3494 | case ELS_CMD_FARP: |
3493 | phba->fc_stat.elsRcvFARP++; | 3495 | phba->fc_stat.elsRcvFARP++; |
3494 | lpfc_els_rcv_farp(phba, elsiocb, ndlp); | 3496 | lpfc_els_rcv_farp(vport, elsiocb, ndlp); |
3495 | break; | 3497 | break; |
3496 | case ELS_CMD_FAN: | 3498 | case ELS_CMD_FAN: |
3497 | phba->fc_stat.elsRcvFAN++; | 3499 | phba->fc_stat.elsRcvFAN++; |
3498 | lpfc_els_rcv_fan(phba, elsiocb, ndlp); | 3500 | lpfc_els_rcv_fan(vport, elsiocb, ndlp); |
3499 | break; | 3501 | break; |
3500 | case ELS_CMD_PRLI: | 3502 | case ELS_CMD_PRLI: |
3501 | phba->fc_stat.elsRcvPRLI++; | 3503 | phba->fc_stat.elsRcvPRLI++; |
3502 | if (phba->hba_state < LPFC_DISC_AUTH) { | 3504 | if (vport->port_state < LPFC_DISC_AUTH) { |
3503 | rjt_err = 1; | 3505 | rjt_err = 1; |
3504 | break; | 3506 | break; |
3505 | } | 3507 | } |
3506 | lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI); | 3508 | lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI); |
3507 | break; | 3509 | break; |
3508 | case ELS_CMD_LIRR: | 3510 | case ELS_CMD_LIRR: |
3509 | phba->fc_stat.elsRcvLIRR++; | 3511 | phba->fc_stat.elsRcvLIRR++; |
3510 | lpfc_els_rcv_lirr(phba, elsiocb, ndlp); | 3512 | lpfc_els_rcv_lirr(vport, elsiocb, ndlp); |
3511 | if (newnode) | 3513 | if (newnode) |
3512 | lpfc_drop_node(phba, ndlp); | 3514 | lpfc_drop_node(vport, ndlp); |
3513 | break; | 3515 | break; |
3514 | case ELS_CMD_RPS: | 3516 | case ELS_CMD_RPS: |
3515 | phba->fc_stat.elsRcvRPS++; | 3517 | phba->fc_stat.elsRcvRPS++; |
3516 | lpfc_els_rcv_rps(phba, elsiocb, ndlp); | 3518 | lpfc_els_rcv_rps(vport, elsiocb, ndlp); |
3517 | if (newnode) | 3519 | if (newnode) |
3518 | lpfc_drop_node(phba, ndlp); | 3520 | lpfc_drop_node(vport, ndlp); |
3519 | break; | 3521 | break; |
3520 | case ELS_CMD_RPL: | 3522 | case ELS_CMD_RPL: |
3521 | phba->fc_stat.elsRcvRPL++; | 3523 | phba->fc_stat.elsRcvRPL++; |
3522 | lpfc_els_rcv_rpl(phba, elsiocb, ndlp); | 3524 | lpfc_els_rcv_rpl(vport, elsiocb, ndlp); |
3523 | if (newnode) | 3525 | if (newnode) |
3524 | lpfc_drop_node(phba, ndlp); | 3526 | lpfc_drop_node(vport, ndlp); |
3525 | break; | 3527 | break; |
3526 | case ELS_CMD_RNID: | 3528 | case ELS_CMD_RNID: |
3527 | phba->fc_stat.elsRcvRNID++; | 3529 | phba->fc_stat.elsRcvRNID++; |
3528 | lpfc_els_rcv_rnid(phba, elsiocb, ndlp); | 3530 | lpfc_els_rcv_rnid(vport, elsiocb, ndlp); |
3529 | if (newnode) | 3531 | if (newnode) |
3530 | lpfc_drop_node(phba, ndlp); | 3532 | lpfc_drop_node(vport, ndlp); |
3531 | break; | 3533 | break; |
3532 | default: | 3534 | default: |
3533 | /* Unsupported ELS command, reject */ | 3535 | /* Unsupported ELS command, reject */ |
@@ -3538,7 +3540,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3538 | "%d:0115 Unknown ELS command x%x received from " | 3540 | "%d:0115 Unknown ELS command x%x received from " |
3539 | "NPORT x%x\n", phba->brd_no, cmd, did); | 3541 | "NPORT x%x\n", phba->brd_no, cmd, did); |
3540 | if (newnode) | 3542 | if (newnode) |
3541 | lpfc_drop_node(phba, ndlp); | 3543 | lpfc_drop_node(vport, ndlp); |
3542 | break; | 3544 | break; |
3543 | } | 3545 | } |
3544 | 3546 | ||
@@ -3548,7 +3550,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba, | |||
3548 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 3550 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
3549 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; | 3551 | stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; |
3550 | stat.un.b.vendorUnique = 0; | 3552 | stat.un.b.vendorUnique = 0; |
3551 | lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp); | 3553 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp); |
3552 | } | 3554 | } |
3553 | 3555 | ||
3554 | lpfc_nlp_put(elsiocb->context1); | 3556 | lpfc_nlp_put(elsiocb->context1); |
@@ -3567,5 +3569,4 @@ dropit: | |||
3567 | icmd->ulpTimeout); | 3569 | icmd->ulpTimeout); |
3568 | phba->fc_stat.elsRcvDrop++; | 3570 | phba->fc_stat.elsRcvDrop++; |
3569 | } | 3571 | } |
3570 | return; | ||
3571 | } | 3572 | } |