vserver 2.0 rc7
[linux-2.6.git] / drivers / scsi / lpfc / lpfc_mbox.c
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 }