xref: /linux/drivers/scsi/lpfc/lpfc_mbox.c (revision 776cfebb430c7b22c208b1b17add97f354d97cab)
1 /*******************************************************************
2  * This file is part of the Emulex Linux Device Driver for         *
3  * Enterprise Fibre Channel Host Bus Adapters.                     *
4  * Refer to the README file included with this package for         *
5  * driver version and adapter support.                             *
6  * Copyright (C) 2004 Emulex Corporation.                          *
7  * www.emulex.com                                                  *
8  *                                                                 *
9  * This program is free software; you can redistribute it and/or   *
10  * modify it under the terms of the GNU General Public License     *
11  * as published by the Free Software Foundation; either version 2  *
12  * of the License, or (at your option) any later version.          *
13  *                                                                 *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of  *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *
17  * GNU General Public License for more details, a copy of which    *
18  * can be found in the file COPYING included with this package.    *
19  *******************************************************************/
20 
21 /*
22  * $Id: lpfc_mbox.c 1.85 2005/04/13 11:59:11EDT sf_support Exp  $
23  */
24 
25 #include <linux/blkdev.h>
26 #include <linux/pci.h>
27 #include <linux/interrupt.h>
28 
29 #include "lpfc_hw.h"
30 #include "lpfc_sli.h"
31 #include "lpfc_disc.h"
32 #include "lpfc_scsi.h"
33 #include "lpfc.h"
34 #include "lpfc_logmsg.h"
35 #include "lpfc_crtn.h"
36 #include "lpfc_compat.h"
37 
38 /**********************************************/
39 
40 /*                mailbox command             */
41 /**********************************************/
42 void
43 lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
44 {
45 	MAILBOX_t *mb;
46 	void *ctx;
47 
48 	mb = &pmb->mb;
49 	ctx = pmb->context2;
50 
51 	/* Setup to dump VPD region */
52 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
53 	mb->mbxCommand = MBX_DUMP_MEMORY;
54 	mb->un.varDmp.cv = 1;
55 	mb->un.varDmp.type = DMP_NV_PARAMS;
56 	mb->un.varDmp.entry_index = offset;
57 	mb->un.varDmp.region_id = DMP_REGION_VPD;
58 	mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t));
59 	mb->un.varDmp.co = 0;
60 	mb->un.varDmp.resp_offset = 0;
61 	pmb->context2 = ctx;
62 	mb->mbxOwner = OWN_HOST;
63 	return;
64 }
65 
66 /**********************************************/
67 /*  lpfc_read_nv  Issue a READ NVPARAM        */
68 /*                mailbox command             */
69 /**********************************************/
70 void
71 lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
72 {
73 	MAILBOX_t *mb;
74 
75 	mb = &pmb->mb;
76 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
77 	mb->mbxCommand = MBX_READ_NV;
78 	mb->mbxOwner = OWN_HOST;
79 	return;
80 }
81 
82 /**********************************************/
83 /*  lpfc_read_la  Issue a READ LA             */
84 /*                mailbox command             */
85 /**********************************************/
86 int
87 lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp)
88 {
89 	MAILBOX_t *mb;
90 	struct lpfc_sli *psli;
91 
92 	psli = &phba->sli;
93 	mb = &pmb->mb;
94 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
95 
96 	INIT_LIST_HEAD(&mp->list);
97 	mb->mbxCommand = MBX_READ_LA64;
98 	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
99 	mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys);
100 	mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys);
101 
102 	/* Save address for later completion and set the owner to host so that
103 	 * the FW knows this mailbox is available for processing.
104 	 */
105 	pmb->context1 = (uint8_t *) mp;
106 	mb->mbxOwner = OWN_HOST;
107 	return (0);
108 }
109 
110 /**********************************************/
111 /*  lpfc_clear_la  Issue a CLEAR LA           */
112 /*                 mailbox command            */
113 /**********************************************/
114 void
115 lpfc_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
116 {
117 	MAILBOX_t *mb;
118 
119 	mb = &pmb->mb;
120 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
121 
122 	mb->un.varClearLA.eventTag = phba->fc_eventTag;
123 	mb->mbxCommand = MBX_CLEAR_LA;
124 	mb->mbxOwner = OWN_HOST;
125 	return;
126 }
127 
128 /**************************************************/
129 /*  lpfc_config_link  Issue a CONFIG LINK         */
130 /*                    mailbox command             */
131 /**************************************************/
132 void
133 lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
134 {
135 	MAILBOX_t *mb = &pmb->mb;
136 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
137 
138 	/* NEW_FEATURE
139 	 * SLI-2, Coalescing Response Feature.
140 	 */
141 	if (phba->cfg_cr_delay) {
142 		mb->un.varCfgLnk.cr = 1;
143 		mb->un.varCfgLnk.ci = 1;
144 		mb->un.varCfgLnk.cr_delay = phba->cfg_cr_delay;
145 		mb->un.varCfgLnk.cr_count = phba->cfg_cr_count;
146 	}
147 
148 	mb->un.varCfgLnk.myId = phba->fc_myDID;
149 	mb->un.varCfgLnk.edtov = phba->fc_edtov;
150 	mb->un.varCfgLnk.arbtov = phba->fc_arbtov;
151 	mb->un.varCfgLnk.ratov = phba->fc_ratov;
152 	mb->un.varCfgLnk.rttov = phba->fc_rttov;
153 	mb->un.varCfgLnk.altov = phba->fc_altov;
154 	mb->un.varCfgLnk.crtov = phba->fc_crtov;
155 	mb->un.varCfgLnk.citov = phba->fc_citov;
156 
157 	if (phba->cfg_ack0)
158 		mb->un.varCfgLnk.ack0_enable = 1;
159 
160 	mb->mbxCommand = MBX_CONFIG_LINK;
161 	mb->mbxOwner = OWN_HOST;
162 	return;
163 }
164 
165 /**********************************************/
166 /*  lpfc_init_link  Issue an INIT LINK        */
167 /*                  mailbox command           */
168 /**********************************************/
169 void
170 lpfc_init_link(struct lpfc_hba * phba,
171 	       LPFC_MBOXQ_t * pmb, uint32_t topology, uint32_t linkspeed)
172 {
173 	lpfc_vpd_t *vpd;
174 	struct lpfc_sli *psli;
175 	MAILBOX_t *mb;
176 
177 	mb = &pmb->mb;
178 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
179 
180 	psli = &phba->sli;
181 	switch (topology) {
182 	case FLAGS_TOPOLOGY_MODE_LOOP_PT:
183 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
184 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
185 		break;
186 	case FLAGS_TOPOLOGY_MODE_PT_PT:
187 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
188 		break;
189 	case FLAGS_TOPOLOGY_MODE_LOOP:
190 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
191 		break;
192 	case FLAGS_TOPOLOGY_MODE_PT_LOOP:
193 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
194 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
195 		break;
196 	}
197 
198 	/* NEW_FEATURE
199 	 * Setting up the link speed
200 	 */
201 	vpd = &phba->vpd;
202 	if (vpd->rev.feaLevelHigh >= 0x02){
203 		switch(linkspeed){
204 			case LINK_SPEED_1G:
205 			case LINK_SPEED_2G:
206 			case LINK_SPEED_4G:
207 				mb->un.varInitLnk.link_flags |=
208 							FLAGS_LINK_SPEED;
209 				mb->un.varInitLnk.link_speed = linkspeed;
210 			break;
211 			case LINK_SPEED_AUTO:
212 			default:
213 				mb->un.varInitLnk.link_speed =
214 							LINK_SPEED_AUTO;
215 			break;
216 		}
217 
218 	}
219 	else
220 		mb->un.varInitLnk.link_speed = LINK_SPEED_AUTO;
221 
222 	mb->mbxCommand = (volatile uint8_t)MBX_INIT_LINK;
223 	mb->mbxOwner = OWN_HOST;
224 	mb->un.varInitLnk.fabric_AL_PA = phba->fc_pref_ALPA;
225 	return;
226 }
227 
228 /**********************************************/
229 /*  lpfc_read_sparam  Issue a READ SPARAM     */
230 /*                    mailbox command         */
231 /**********************************************/
232 int
233 lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
234 {
235 	struct lpfc_dmabuf *mp;
236 	MAILBOX_t *mb;
237 	struct lpfc_sli *psli;
238 
239 	psli = &phba->sli;
240 	mb = &pmb->mb;
241 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
242 
243 	mb->mbxOwner = OWN_HOST;
244 
245 	/* Get a buffer to hold the HBAs Service Parameters */
246 
247 	if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
248 	    ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
249 		if (mp)
250 			kfree(mp);
251 		mb->mbxCommand = MBX_READ_SPARM64;
252 		/* READ_SPARAM: no buffers */
253 		lpfc_printf_log(phba,
254 			        KERN_WARNING,
255 			        LOG_MBOX,
256 			        "%d:0301 READ_SPARAM: no buffers\n",
257 			        phba->brd_no);
258 		return (1);
259 	}
260 	INIT_LIST_HEAD(&mp->list);
261 	mb->mbxCommand = MBX_READ_SPARM64;
262 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
263 	mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys);
264 	mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys);
265 
266 	/* save address for completion */
267 	pmb->context1 = mp;
268 
269 	return (0);
270 }
271 
272 /********************************************/
273 /*  lpfc_unreg_did  Issue a UNREG_DID       */
274 /*                  mailbox command         */
275 /********************************************/
276 void
277 lpfc_unreg_did(struct lpfc_hba * phba, uint32_t did, LPFC_MBOXQ_t * pmb)
278 {
279 	MAILBOX_t *mb;
280 
281 	mb = &pmb->mb;
282 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
283 
284 	mb->un.varUnregDID.did = did;
285 
286 	mb->mbxCommand = MBX_UNREG_D_ID;
287 	mb->mbxOwner = OWN_HOST;
288 	return;
289 }
290 
291 /***********************************************/
292 
293 /*                  command to write slim      */
294 /***********************************************/
295 void
296 lpfc_set_slim(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint32_t addr,
297 	      uint32_t value)
298 {
299 	MAILBOX_t *mb;
300 
301 	mb = &pmb->mb;
302 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
303 
304 	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
305 	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
306 
307 	/*
308 	 * Always turn on DELAYED ABTS for ELS timeouts
309 	 */
310 	if ((addr == 0x052198) && (value == 0))
311 		value = 1;
312 
313 	mb->un.varWords[0] = addr;
314 	mb->un.varWords[1] = value;
315 
316 	mb->mbxCommand = MBX_SET_SLIM;
317 	mb->mbxOwner = OWN_HOST;
318 	return;
319 }
320 
321 /**********************************************/
322 /*  lpfc_read_nv  Issue a READ CONFIG         */
323 /*                mailbox command             */
324 /**********************************************/
325 void
326 lpfc_read_config(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
327 {
328 	MAILBOX_t *mb;
329 
330 	mb = &pmb->mb;
331 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
332 
333 	mb->mbxCommand = MBX_READ_CONFIG;
334 	mb->mbxOwner = OWN_HOST;
335 	return;
336 }
337 
338 /********************************************/
339 /*  lpfc_reg_login  Issue a REG_LOGIN       */
340 /*                  mailbox command         */
341 /********************************************/
342 int
343 lpfc_reg_login(struct lpfc_hba * phba,
344 	       uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag)
345 {
346 	uint8_t *sparam;
347 	struct lpfc_dmabuf *mp;
348 	MAILBOX_t *mb;
349 	struct lpfc_sli *psli;
350 
351 	psli = &phba->sli;
352 	mb = &pmb->mb;
353 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
354 
355 	mb->un.varRegLogin.rpi = 0;
356 	mb->un.varRegLogin.did = did;
357 	mb->un.varWords[30] = flag;	/* Set flag to issue action on cmpl */
358 
359 	mb->mbxOwner = OWN_HOST;
360 
361 	/* Get a buffer to hold NPorts Service Parameters */
362 	if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) ||
363 	    ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
364 		if (mp)
365 			kfree(mp);
366 
367 		mb->mbxCommand = MBX_REG_LOGIN64;
368 		/* REG_LOGIN: no buffers */
369 		lpfc_printf_log(phba,
370 			       KERN_WARNING,
371 			       LOG_MBOX,
372 			       "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n",
373 			       phba->brd_no,
374 			       (uint32_t) did, (uint32_t) flag);
375 		return (1);
376 	}
377 	INIT_LIST_HEAD(&mp->list);
378 	sparam = mp->virt;
379 
380 	/* Copy param's into a new buffer */
381 	memcpy(sparam, param, sizeof (struct serv_parm));
382 
383 	/* save address for completion */
384 	pmb->context1 = (uint8_t *) mp;
385 
386 	mb->mbxCommand = MBX_REG_LOGIN64;
387 	mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm);
388 	mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys);
389 	mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys);
390 
391 	return (0);
392 }
393 
394 /**********************************************/
395 /*  lpfc_unreg_login  Issue a UNREG_LOGIN     */
396 /*                    mailbox command         */
397 /**********************************************/
398 void
399 lpfc_unreg_login(struct lpfc_hba * phba, uint32_t rpi, LPFC_MBOXQ_t * pmb)
400 {
401 	MAILBOX_t *mb;
402 
403 	mb = &pmb->mb;
404 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
405 
406 	mb->un.varUnregLogin.rpi = (uint16_t) rpi;
407 	mb->un.varUnregLogin.rsvd1 = 0;
408 
409 	mb->mbxCommand = MBX_UNREG_LOGIN;
410 	mb->mbxOwner = OWN_HOST;
411 	return;
412 }
413 
414 static void
415 lpfc_config_pcb_setup(struct lpfc_hba * phba)
416 {
417 	struct lpfc_sli *psli = &phba->sli;
418 	struct lpfc_sli_ring *pring;
419 	PCB_t *pcbp = &phba->slim2p->pcb;
420 	dma_addr_t pdma_addr;
421 	uint32_t offset;
422 	uint32_t iocbCnt;
423 	int i;
424 
425 	psli->MBhostaddr = (uint32_t *)&phba->slim2p->mbx;
426 	pcbp->maxRing = (psli->num_rings - 1);
427 
428 	iocbCnt = 0;
429 	for (i = 0; i < psli->num_rings; i++) {
430 		pring = &psli->ring[i];
431 		/* A ring MUST have both cmd and rsp entries defined to be
432 		   valid */
433 		if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) {
434 			pcbp->rdsc[i].cmdEntries = 0;
435 			pcbp->rdsc[i].rspEntries = 0;
436 			pcbp->rdsc[i].cmdAddrHigh = 0;
437 			pcbp->rdsc[i].rspAddrHigh = 0;
438 			pcbp->rdsc[i].cmdAddrLow = 0;
439 			pcbp->rdsc[i].rspAddrLow = 0;
440 			pring->cmdringaddr = NULL;
441 			pring->rspringaddr = NULL;
442 			continue;
443 		}
444 		/* Command ring setup for ring */
445 		pring->cmdringaddr =
446 		    (void *)&phba->slim2p->IOCBs[iocbCnt];
447 		pcbp->rdsc[i].cmdEntries = pring->numCiocb;
448 
449 		offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
450 			 (uint8_t *)phba->slim2p;
451 		pdma_addr = phba->slim2p_mapping + offset;
452 		pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr);
453 		pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr);
454 		iocbCnt += pring->numCiocb;
455 
456 		/* Response ring setup for ring */
457 		pring->rspringaddr =
458 		    (void *)&phba->slim2p->IOCBs[iocbCnt];
459 
460 		pcbp->rdsc[i].rspEntries = pring->numRiocb;
461 		offset = (uint8_t *)&phba->slim2p->IOCBs[iocbCnt] -
462 			 (uint8_t *)phba->slim2p;
463 		pdma_addr = phba->slim2p_mapping + offset;
464 		pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr);
465 		pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr);
466 		iocbCnt += pring->numRiocb;
467 	}
468 }
469 
470 void
471 lpfc_read_rev(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
472 {
473 	MAILBOX_t *mb;
474 
475 	mb = &pmb->mb;
476 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
477 	mb->un.varRdRev.cv = 1;
478 	mb->mbxCommand = MBX_READ_REV;
479 	mb->mbxOwner = OWN_HOST;
480 	return;
481 }
482 
483 void
484 lpfc_config_ring(struct lpfc_hba * phba, int ring, LPFC_MBOXQ_t * pmb)
485 {
486 	int i;
487 	MAILBOX_t *mb = &pmb->mb;
488 	struct lpfc_sli *psli;
489 	struct lpfc_sli_ring *pring;
490 
491 	memset(pmb, 0, sizeof (LPFC_MBOXQ_t));
492 
493 	mb->un.varCfgRing.ring = ring;
494 	mb->un.varCfgRing.maxOrigXchg = 0;
495 	mb->un.varCfgRing.maxRespXchg = 0;
496 	mb->un.varCfgRing.recvNotify = 1;
497 
498 	psli = &phba->sli;
499 	pring = &psli->ring[ring];
500 	mb->un.varCfgRing.numMask = pring->num_mask;
501 	mb->mbxCommand = MBX_CONFIG_RING;
502 	mb->mbxOwner = OWN_HOST;
503 
504 	/* Is this ring configured for a specific profile */
505 	if (pring->prt[0].profile) {
506 		mb->un.varCfgRing.profile = pring->prt[0].profile;
507 		return;
508 	}
509 
510 	/* Otherwise we setup specific rctl / type masks for this ring */
511 	for (i = 0; i < pring->num_mask; i++) {
512 		mb->un.varCfgRing.rrRegs[i].rval = pring->prt[i].rctl;
513 		if (mb->un.varCfgRing.rrRegs[i].rval != FC_ELS_REQ)
514 			mb->un.varCfgRing.rrRegs[i].rmask = 0xff;
515 		else
516 			mb->un.varCfgRing.rrRegs[i].rmask = 0xfe;
517 		mb->un.varCfgRing.rrRegs[i].tval = pring->prt[i].type;
518 		mb->un.varCfgRing.rrRegs[i].tmask = 0xff;
519 	}
520 
521 	return;
522 }
523 
524 void
525 lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
526 {
527 	MAILBOX_t *mb = &pmb->mb;
528 	dma_addr_t pdma_addr;
529 	uint32_t bar_low, bar_high;
530 	size_t offset;
531 	HGP hgp;
532 	void __iomem *to_slim;
533 
534 	memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
535 	mb->mbxCommand = MBX_CONFIG_PORT;
536 	mb->mbxOwner = OWN_HOST;
537 
538 	mb->un.varCfgPort.pcbLen = sizeof(PCB_t);
539 
540 	offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p;
541 	pdma_addr = phba->slim2p_mapping + offset;
542 	mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
543 	mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
544 
545 	/* Now setup pcb */
546 	phba->slim2p->pcb.type = TYPE_NATIVE_SLI2;
547 	phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2;
548 
549 	/* Setup Mailbox pointers */
550 	phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t);
551 	offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p;
552 	pdma_addr = phba->slim2p_mapping + offset;
553 	phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr);
554 	phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr);
555 
556 	/*
557 	 * Setup Host Group ring pointer.
558 	 *
559 	 * For efficiency reasons, the ring get/put pointers can be
560 	 * placed in adapter memory (SLIM) rather than in host memory.
561 	 * This allows firmware to avoid PCI reads/writes when updating
562 	 * and checking pointers.
563 	 *
564 	 * The firmware recognizes the use of SLIM memory by comparing
565 	 * the address of the get/put pointers structure with that of
566 	 * the SLIM BAR (BAR0).
567 	 *
568 	 * Caution: be sure to use the PCI config space value of BAR0/BAR1
569 	 * (the hardware's view of the base address), not the OS's
570 	 * value of pci_resource_start() as the OS value may be a cookie
571 	 * for ioremap/iomap.
572 	 */
573 
574 
575 	pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low);
576 	pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high);
577 
578 
579 	/* mask off BAR0's flag bits 0 - 3 */
580 	phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) +
581 					(SLIMOFF*sizeof(uint32_t));
582 	if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64)
583 		phba->slim2p->pcb.hgpAddrHigh = bar_high;
584 	else
585 		phba->slim2p->pcb.hgpAddrHigh = 0;
586 	/* write HGP data to SLIM at the required longword offset */
587 	memset(&hgp, 0, sizeof(HGP));
588 	to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t));
589 	lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP));
590 
591 	/* Setup Port Group ring pointer */
592 	offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port -
593 		 (uint8_t *)phba->slim2p;
594 	pdma_addr = phba->slim2p_mapping + offset;
595 	phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr);
596 	phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr);
597 
598 	/* Use callback routine to setp rings in the pcb */
599 	lpfc_config_pcb_setup(phba);
600 
601 	/* special handling for LC HBAs */
602 	if (lpfc_is_LC_HBA(phba->pcidev->device)) {
603 		uint32_t hbainit[5];
604 
605 		lpfc_hba_init(phba, hbainit);
606 
607 		memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20);
608 	}
609 
610 	/* Swap PCB if needed */
611 	lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb,
612 								sizeof (PCB_t));
613 
614 	lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
615 		        "%d:0405 Service Level Interface (SLI) 2 selected\n",
616 		        phba->brd_no);
617 }
618 
619 void
620 lpfc_mbox_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
621 {
622 	struct lpfc_sli *psli;
623 
624 	psli = &phba->sli;
625 
626 	list_add_tail(&mbq->list, &psli->mboxq);
627 
628 	psli->mboxq_cnt++;
629 
630 	return;
631 }
632 
633 LPFC_MBOXQ_t *
634 lpfc_mbox_get(struct lpfc_hba * phba)
635 {
636 	LPFC_MBOXQ_t *mbq = NULL;
637 	struct lpfc_sli *psli = &phba->sli;
638 
639 	list_remove_head((&psli->mboxq), mbq, LPFC_MBOXQ_t,
640 			 list);
641 	if (mbq) {
642 		psli->mboxq_cnt--;
643 	}
644 
645 	return mbq;
646 }
647