diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:36 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:05:45 -0400 |
commit | 2e0fef85e098f6794956b8b80b111179fbb4cbb7 (patch) | |
tree | f632090be67f95e9a637eeb044938ba1591e848f /drivers/scsi/lpfc/lpfc_els.c | |
parent | 4c2baaaf2ba4875d1d2d59b3b3e1216d3277b17a (diff) |
[SCSI] lpfc: NPIV: split ports
The driver is reorganized to separate the handling of the adapter from
the handling of the FC port. Adapter handling includes submissions of
command requests, receiving responses, and managing adapter resources.
The FC port includes the discovery engine, login handling, and the
mapping of a Scsi_Host on the "port". Although not a large functional
change, as it touches core structures and functions, resulting in a
large text delta.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
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 | } |