/** * 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); }