/** * lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB) * @phba: pointer to lpfc hba data structure. * * This routine sets up and initializes the IOCB rings in the Port Control * Block (PCB). **/ static void lpfc_config_pcb_setup(struct lpfc_hba * phba) { struct lpfc_sli *psli = &phba->sli; struct lpfc_sli_ring *pring; PCB_t *pcbp = phba->pcb; dma_addr_t pdma_addr; uint32_t offset; uint32_t iocbCnt = 0; int i; pcbp->maxRing = (psli->num_rings - 1); for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; pring->sizeCiocb = phba->sli_rev == 3 ? SLI3_IOCB_CMD_SIZE: SLI2_IOCB_CMD_SIZE; pring->sizeRiocb = phba->sli_rev == 3 ? SLI3_IOCB_RSP_SIZE: SLI2_IOCB_RSP_SIZE; /* A ring MUST have both cmd and rsp entries defined to be valid */ if ((pring->numCiocb == 0) || (pring->numRiocb == 0)) { pcbp->rdsc[i].cmdEntries = 0; pcbp->rdsc[i].rspEntries = 0; pcbp->rdsc[i].cmdAddrHigh = 0; pcbp->rdsc[i].rspAddrHigh = 0; pcbp->rdsc[i].cmdAddrLow = 0; pcbp->rdsc[i].rspAddrLow = 0; pring->cmdringaddr = NULL; pring->rspringaddr = NULL; continue; } /* Command ring setup for ring */ pring->cmdringaddr = (void *)&phba->IOCBs[iocbCnt]; pcbp->rdsc[i].cmdEntries = pring->numCiocb; offset = (uint8_t *) &phba->IOCBs[iocbCnt] - (uint8_t *) phba->slim2p.virt; pdma_addr = phba->slim2p.phys + offset; pcbp->rdsc[i].cmdAddrHigh = putPaddrHigh(pdma_addr); pcbp->rdsc[i].cmdAddrLow = putPaddrLow(pdma_addr); iocbCnt += pring->numCiocb; /* Response ring setup for ring */ pring->rspringaddr = (void *) &phba->IOCBs[iocbCnt]; pcbp->rdsc[i].rspEntries = pring->numRiocb; offset = (uint8_t *)&phba->IOCBs[iocbCnt] - (uint8_t *)phba->slim2p.virt; pdma_addr = phba->slim2p.phys + offset; pcbp->rdsc[i].rspAddrHigh = putPaddrHigh(pdma_addr); pcbp->rdsc[i].rspAddrLow = putPaddrLow(pdma_addr); iocbCnt += pring->numRiocb; } }
/** * lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ. * @phba: pointer to lpfc hba data structure. * @id: HBQ identifier. * @hbq_desc: pointer to the HBA descriptor data structure. * @hbq_entry_index: index of the HBQ entry data structures. * @pmb: pointer to the driver internal queue element for mailbox command. * * The configure HBQ (Host Buffer Queue) mailbox command is used to configure * an HBQ. The configuration binds events that require buffers to a particular * ring and HBQ based on a selection profile. * * This routine prepares the mailbox command for configuring an HBQ. **/ void lpfc_config_hbq(struct lpfc_hba *phba, uint32_t id, struct lpfc_hbq_init *hbq_desc, uint32_t hbq_entry_index, LPFC_MBOXQ_t *pmb) { int i; MAILBOX_t *mb = &pmb->mb; struct config_hbq_var *hbqmb = &mb->un.varCfgHbq; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); hbqmb->hbqId = id; hbqmb->entry_count = hbq_desc->entry_count; /* # entries in HBQ */ hbqmb->recvNotify = hbq_desc->rn; /* Receive * Notification */ hbqmb->numMask = hbq_desc->mask_count; /* # R_CTL/TYPE masks * # in words 0-19 */ hbqmb->profile = hbq_desc->profile; /* Selection profile: * 0 = all, * 7 = logentry */ hbqmb->ringMask = hbq_desc->ring_mask; /* Binds HBQ to a ring * e.g. Ring0=b0001, * ring2=b0100 */ hbqmb->headerLen = hbq_desc->headerLen; /* 0 if not profile 4 * or 5 */ hbqmb->logEntry = hbq_desc->logEntry; /* Set to 1 if this * HBQ will be used * for LogEntry * buffers */ hbqmb->hbqaddrLow = putPaddrLow(phba->hbqslimp.phys) + hbq_entry_index * sizeof(struct lpfc_hbq_entry); hbqmb->hbqaddrHigh = putPaddrHigh(phba->hbqslimp.phys); mb->mbxCommand = MBX_CONFIG_HBQ; mb->mbxOwner = OWN_HOST; /* Copy info for profiles 2,3,5. Other * profiles this area is reserved */ if (hbq_desc->profile == 2) lpfc_build_hbq_profile2(hbqmb, hbq_desc); else if (hbq_desc->profile == 3) lpfc_build_hbq_profile3(hbqmb, hbq_desc); else if (hbq_desc->profile == 5) lpfc_build_hbq_profile5(hbqmb, hbq_desc); /* Return if no rctl / type masks for this HBQ */ if (!hbq_desc->mask_count) return; /* Otherwise we setup specific rctl / type masks for this HBQ */ for (i = 0; i < hbq_desc->mask_count; i++) { hbqmb->hbqMasks[i].tmatch = hbq_desc->hbqMasks[i].tmatch; hbqmb->hbqMasks[i].tmask = hbq_desc->hbqMasks[i].tmask; hbqmb->hbqMasks[i].rctlmatch = hbq_desc->hbqMasks[i].rctlmatch; hbqmb->hbqMasks[i].rctlmask = hbq_desc->hbqMasks[i].rctlmask; } return; }
/** * lpfc_reg_rpi - Prepare a mailbox command for registering remote login * @phba: pointer to lpfc hba data structure. * @vpi: virtual N_Port identifier. * @did: remote port identifier. * @param: pointer to memory holding the server parameters. * @pmb: pointer to the driver internal queue element for mailbox command. * @flag: action flag to be passed back for the complete function. * * The registration login mailbox command is used to register an N_Port or * F_Port login. This registration allows the HBA to cache the remote N_Port * service parameters internally and thereby make the appropriate FC-2 * decisions. The remote port service parameters are handed off by the driver * to the HBA using a descriptor entry that directly identifies a buffer in * host memory. In exchange, the HBA returns an RPI identifier. * * This routine prepares the mailbox command for registering remote port login. * The function allocates DMA buffer for passing the service parameters to the * HBA with the mailbox command. * * Return codes * 0 - Success * 1 - DMA memory allocation failed **/ int lpfc_reg_rpi(struct lpfc_hba *phba, uint16_t vpi, uint32_t did, uint8_t *param, LPFC_MBOXQ_t *pmb, uint32_t flag) { MAILBOX_t *mb = &pmb->u.mb; uint8_t *sparam; struct lpfc_dmabuf *mp; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); mb->un.varRegLogin.rpi = 0; if (phba->sli_rev == LPFC_SLI_REV4) { mb->un.varRegLogin.rpi = lpfc_sli4_alloc_rpi(phba); if (mb->un.varRegLogin.rpi == LPFC_RPI_ALLOC_ERROR) return 1; } mb->un.varRegLogin.vpi = vpi + phba->vpi_base; mb->un.varRegLogin.did = did; mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ mb->mbxOwner = OWN_HOST; /* Get a buffer to hold NPorts Service Parameters */ mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); if (mp) mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); if (!mp || !mp->virt) { kfree(mp); mb->mbxCommand = MBX_REG_LOGIN64; /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, "0302 REG_LOGIN: no buffers, VPI:%d DID:x%x, " "flag x%x\n", vpi, did, flag); return (1); } INIT_LIST_HEAD(&mp->list); sparam = mp->virt; /* Copy param's into a new buffer */ memcpy(sparam, param, sizeof (struct serv_parm)); /* save address for completion */ pmb->context1 = (uint8_t *) mp; mb->mbxCommand = MBX_REG_LOGIN64; mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); return (0); }
int lpfc_reg_login(struct lpfc_hba * phba, uint32_t did, uint8_t * param, LPFC_MBOXQ_t * pmb, uint32_t flag) { uint8_t *sparam; struct lpfc_dmabuf *mp; MAILBOX_t *mb; struct lpfc_sli *psli; psli = &phba->sli; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); mb->un.varRegLogin.rpi = 0; mb->un.varRegLogin.did = did; mb->un.varWords[30] = flag; /* Set flag to issue action on cmpl */ mb->mbxOwner = OWN_HOST; /* Get a buffer to hold NPorts Service Parameters */ if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { if (mp) kfree(mp); mb->mbxCommand = MBX_REG_LOGIN64; /* REG_LOGIN: no buffers */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, "%d:0302 REG_LOGIN: no buffers Data x%x x%x\n", phba->brd_no, (uint32_t) did, (uint32_t) flag); return (1); } INIT_LIST_HEAD(&mp->list); sparam = mp->virt; /* Copy param's into a new buffer */ memcpy(sparam, param, sizeof (struct serv_parm)); /* save address for completion */ pmb->context1 = (uint8_t *) mp; mb->mbxCommand = MBX_REG_LOGIN64; mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); mb->un.varRegLogin.un.sp64.addrHigh = putPaddrHigh(mp->phys); mb->un.varRegLogin.un.sp64.addrLow = putPaddrLow(mp->phys); return (0); }
/** * lpfc_dump_static_vport - Dump HBA's static vport information. * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @offset: offset for dumping vport info. * * The dump mailbox command provides a method for the device driver to obtain * various types of information from the HBA device. * * This routine prepares the mailbox command for dumping list of static * vports to be created. **/ int lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, uint16_t offset) { MAILBOX_t *mb; struct lpfc_dmabuf *mp; mb = &pmb->u.mb; /* Setup to dump vport info region */ memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); mb->mbxCommand = MBX_DUMP_MEMORY; mb->un.varDmp.type = DMP_NV_PARAMS; mb->un.varDmp.entry_index = offset; mb->un.varDmp.region_id = DMP_REGION_VPORT; mb->mbxOwner = OWN_HOST; /* For SLI3 HBAs data is embedded in mailbox */ if (phba->sli_rev != LPFC_SLI_REV4) { mb->un.varDmp.cv = 1; mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t); return 0; } /* For SLI4 HBAs driver need to allocate memory */ mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); if (mp) mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys); if (!mp || !mp->virt) { kfree(mp); lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, "2605 lpfc_dump_static_vport: memory" " allocation failed\n"); return 1; } memset(mp->virt, 0, LPFC_BPL_SIZE); INIT_LIST_HEAD(&mp->list); /* save address for completion */ pmb->context2 = (uint8_t *) mp; mb->un.varWords[3] = putPaddrLow(mp->phys); mb->un.varWords[4] = putPaddrHigh(mp->phys); mb->un.varDmp.sli4_length = sizeof(struct static_vport_info); return 0; }
int lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { struct lpfc_dmabuf *mp; MAILBOX_t *mb; struct lpfc_sli *psli; psli = &phba->sli; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); mb->mbxOwner = OWN_HOST; /* Get a buffer to hold the HBAs Service Parameters */ if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) || ((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) { if (mp) kfree(mp); mb->mbxCommand = MBX_READ_SPARM64; /* READ_SPARAM: no buffers */ lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, "%d:0301 READ_SPARAM: no buffers\n", phba->brd_no); return (1); } INIT_LIST_HEAD(&mp->list); mb->mbxCommand = MBX_READ_SPARM64; mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (struct serv_parm); mb->un.varRdSparm.un.sp64.addrHigh = putPaddrHigh(mp->phys); mb->un.varRdSparm.un.sp64.addrLow = putPaddrLow(mp->phys); /* save address for completion */ pmb->context1 = mp; return (0); }
/** * lpfc_read_la: Prepare a mailbox command for reading HBA link attention. * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * @mp: DMA buffer memory for reading the link attention information into. * * The read link attention mailbox command is issued to read the Link Event * Attention information indicated by the HBA port when the Link Event bit * of the Host Attention (HSTATT) register is set to 1. A Link Event * Attention occurs based on an exception detected at the Fibre Channel link * interface. * * This routine prepares the mailbox command for reading HBA link attention * information. A DMA memory has been set aside and address passed to the * HBA through @mp for the HBA to DMA link attention information into the * memory as part of the execution of the mailbox command. * * Return codes * 0 - Success (currently always return 0) **/ int lpfc_read_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, struct lpfc_dmabuf *mp) { MAILBOX_t *mb; struct lpfc_sli *psli; psli = &phba->sli; mb = &pmb->mb; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); INIT_LIST_HEAD(&mp->list); mb->mbxCommand = MBX_READ_LA64; mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128; mb->un.varReadLA.un.lilpBde64.addrHigh = putPaddrHigh(mp->phys); mb->un.varReadLA.un.lilpBde64.addrLow = putPaddrLow(mp->phys); /* Save address for later completion and set the owner to host so that * the FW knows this mailbox is available for processing. */ pmb->context1 = (uint8_t *) mp; mb->mbxOwner = OWN_HOST; return (0); }
/** * lpfc_config_port: Prepare a mailbox command for configuring port. * @phba: pointer to lpfc hba data structure. * @pmb: pointer to the driver internal queue element for mailbox command. * * The configure port mailbox command is used to identify the Port Control * Block (PCB) in the driver memory. After this command is issued, the * driver must not access the mailbox in the HBA without first resetting * the HBA. The HBA may copy the PCB information to internal storage for * subsequent use; the driver can not change the PCB information unless it * resets the HBA. * * This routine prepares the mailbox command for configuring port. **/ void lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { MAILBOX_t __iomem *mb_slim = (MAILBOX_t __iomem *) phba->MBslimaddr; MAILBOX_t *mb = &pmb->mb; dma_addr_t pdma_addr; uint32_t bar_low, bar_high; size_t offset; struct lpfc_hgp hgp; int i; uint32_t pgp_offset; memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); mb->mbxCommand = MBX_CONFIG_PORT; mb->mbxOwner = OWN_HOST; mb->un.varCfgPort.pcbLen = sizeof(PCB_t); offset = (uint8_t *)phba->pcb - (uint8_t *)phba->slim2p.virt; pdma_addr = phba->slim2p.phys + offset; mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); /* Always Host Group Pointer is in SLIM */ mb->un.varCfgPort.hps = 1; /* If HBA supports SLI=3 ask for it */ if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { if (phba->cfg_enable_bg) mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */ mb->un.varCfgPort.cerbm = 1; /* Request HBQs */ mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */ mb->un.varCfgPort.cinb = 1; /* Interrupt Notification Block */ mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count(); if (phba->max_vpi && phba->cfg_enable_npiv && phba->vpd.sli3Feat.cmv) { mb->un.varCfgPort.max_vpi = phba->max_vpi; mb->un.varCfgPort.cmv = 1; } else mb->un.varCfgPort.max_vpi = phba->max_vpi = 0; } else phba->sli_rev = 2; mb->un.varCfgPort.sli_mode = phba->sli_rev; /* Now setup pcb */ phba->pcb->type = TYPE_NATIVE_SLI2; phba->pcb->feature = FEATURE_INITIAL_SLI2; /* Setup Mailbox pointers */ phba->pcb->mailBoxSize = sizeof(MAILBOX_t); offset = (uint8_t *)phba->mbox - (uint8_t *)phba->slim2p.virt; pdma_addr = phba->slim2p.phys + offset; phba->pcb->mbAddrHigh = putPaddrHigh(pdma_addr); phba->pcb->mbAddrLow = putPaddrLow(pdma_addr); /* * Setup Host Group ring pointer. * * For efficiency reasons, the ring get/put pointers can be * placed in adapter memory (SLIM) rather than in host memory. * This allows firmware to avoid PCI reads/writes when updating * and checking pointers. * * The firmware recognizes the use of SLIM memory by comparing * the address of the get/put pointers structure with that of * the SLIM BAR (BAR0). * * Caution: be sure to use the PCI config space value of BAR0/BAR1 * (the hardware's view of the base address), not the OS's * value of pci_resource_start() as the OS value may be a cookie * for ioremap/iomap. */ pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low); pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high); /* * Set up HGP - Port Memory * * The port expects the host get/put pointers to reside in memory * following the "non-diagnostic" mode mailbox (32 words, 0x80 bytes) * area of SLIM. In SLI-2 mode, there's an additional 16 reserved * words (0x40 bytes). This area is not reserved if HBQs are * configured in SLI-3. * * CR0Put - SLI2(no HBQs) = 0xc0, With HBQs = 0x80 * RR0Get 0xc4 0x84 * CR1Put 0xc8 0x88 * RR1Get 0xcc 0x8c * CR2Put 0xd0 0x90 * RR2Get 0xd4 0x94 * CR3Put 0xd8 0x98 * RR3Get 0xdc 0x9c * * Reserved 0xa0-0xbf * If HBQs configured: * HBQ 0 Put ptr 0xc0 * HBQ 1 Put ptr 0xc4 * HBQ 2 Put ptr 0xc8 * ...... * HBQ(M-1)Put Pointer 0xc0+(M-1)*4 * */ if (phba->sli_rev == 3) { phba->host_gp = &mb_slim->us.s3.host[0]; phba->hbq_put = &mb_slim->us.s3.hbq_put[0]; } else { phba->host_gp = &mb_slim->us.s2.host[0]; phba->hbq_put = NULL; } /* mask off BAR0's flag bits 0 - 3 */ phba->pcb->hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) + (void __iomem *)phba->host_gp - (void __iomem *)phba->MBslimaddr; if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64) phba->pcb->hgpAddrHigh = bar_high; else phba->pcb->hgpAddrHigh = 0; /* write HGP data to SLIM at the required longword offset */ memset(&hgp, 0, sizeof(struct lpfc_hgp)); for (i=0; i < phba->sli.num_rings; i++) { lpfc_memcpy_to_slim(phba->host_gp + i, &hgp, sizeof(*phba->host_gp)); } /* Setup Port Group offset */ if (phba->sli_rev == 3) pgp_offset = offsetof(struct lpfc_sli2_slim, mbx.us.s3_pgp.port); else
memset(&hgp, 0, sizeof(struct lpfc_hgp)); for (i=0; i < phba->sli.num_rings; i++) { lpfc_memcpy_to_slim(phba->host_gp + i, &hgp, sizeof(*phba->host_gp)); } /* Setup Port Group offset */ if (phba->sli_rev == 3) pgp_offset = offsetof(struct lpfc_sli2_slim, mbx.us.s3_pgp.port); else pgp_offset = offsetof(struct lpfc_sli2_slim, mbx.us.s2.port); pdma_addr = phba->slim2p.phys + pgp_offset; phba->pcb->pgpAddrHigh = putPaddrHigh(pdma_addr); phba->pcb->pgpAddrLow = putPaddrLow(pdma_addr); /* Use callback routine to setp rings in the pcb */ lpfc_config_pcb_setup(phba); /* special handling for LC HBAs */ if (lpfc_is_LC_HBA(phba->pcidev->device)) { uint32_t hbainit[5]; lpfc_hba_init(phba, hbainit); memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20); } /* Swap PCB if needed */ lpfc_sli_pcimem_bcopy(phba->pcb, phba->pcb, sizeof(PCB_t));
void lpfc_config_port(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) { MAILBOX_t *mb = &pmb->mb; dma_addr_t pdma_addr; uint32_t bar_low, bar_high; size_t offset; HGP hgp; void __iomem *to_slim; memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); mb->mbxCommand = MBX_CONFIG_PORT; mb->mbxOwner = OWN_HOST; mb->un.varCfgPort.pcbLen = sizeof(PCB_t); offset = (uint8_t *)&phba->slim2p->pcb - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); /* Now setup pcb */ phba->slim2p->pcb.type = TYPE_NATIVE_SLI2; phba->slim2p->pcb.feature = FEATURE_INITIAL_SLI2; /* Setup Mailbox pointers */ phba->slim2p->pcb.mailBoxSize = sizeof(MAILBOX_t); offset = (uint8_t *)&phba->slim2p->mbx - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; phba->slim2p->pcb.mbAddrHigh = putPaddrHigh(pdma_addr); phba->slim2p->pcb.mbAddrLow = putPaddrLow(pdma_addr); /* * Setup Host Group ring pointer. * * For efficiency reasons, the ring get/put pointers can be * placed in adapter memory (SLIM) rather than in host memory. * This allows firmware to avoid PCI reads/writes when updating * and checking pointers. * * The firmware recognizes the use of SLIM memory by comparing * the address of the get/put pointers structure with that of * the SLIM BAR (BAR0). * * Caution: be sure to use the PCI config space value of BAR0/BAR1 * (the hardware's view of the base address), not the OS's * value of pci_resource_start() as the OS value may be a cookie * for ioremap/iomap. */ pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_0, &bar_low); pci_read_config_dword(phba->pcidev, PCI_BASE_ADDRESS_1, &bar_high); /* mask off BAR0's flag bits 0 - 3 */ phba->slim2p->pcb.hgpAddrLow = (bar_low & PCI_BASE_ADDRESS_MEM_MASK) + (SLIMOFF*sizeof(uint32_t)); if (bar_low & PCI_BASE_ADDRESS_MEM_TYPE_64) phba->slim2p->pcb.hgpAddrHigh = bar_high; else phba->slim2p->pcb.hgpAddrHigh = 0; /* write HGP data to SLIM at the required longword offset */ memset(&hgp, 0, sizeof(HGP)); to_slim = phba->MBslimaddr + (SLIMOFF*sizeof (uint32_t)); lpfc_memcpy_to_slim(to_slim, &hgp, sizeof (HGP)); /* Setup Port Group ring pointer */ offset = (uint8_t *)&phba->slim2p->mbx.us.s2.port - (uint8_t *)phba->slim2p; pdma_addr = phba->slim2p_mapping + offset; phba->slim2p->pcb.pgpAddrHigh = putPaddrHigh(pdma_addr); phba->slim2p->pcb.pgpAddrLow = putPaddrLow(pdma_addr); /* Use callback routine to setp rings in the pcb */ lpfc_config_pcb_setup(phba); /* special handling for LC HBAs */ if (lpfc_is_LC_HBA(phba->pcidev->device)) { uint32_t hbainit[5]; lpfc_hba_init(phba, hbainit); memcpy(&mb->un.varCfgPort.hbainit, hbainit, 20); } /* Swap PCB if needed */ lpfc_sli_pcimem_bcopy(&phba->slim2p->pcb, &phba->slim2p->pcb, sizeof (PCB_t)); lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0405 Service Level Interface (SLI) 2 selected\n", phba->brd_no); }