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