On Sat, Apr 11, 2020 at 08:32:38PM -0700, James Smart wrote: > This patch continues the libefc_sli SLI-4 library population. > > This patch adds routines to create mailbox commands used during > adapter initialization and adds APIs to issue mailbox commands to the > adapter through the bootstrap mailbox register. > > Signed-off-by: Ram Vegesna <ram.vegesna@xxxxxxxxxxxx> > Signed-off-by: James Smart <jsmart2021@xxxxxxxxx> > > --- > v3: > Return defined return values EFC_SUCCESS/FAIL > Added 64G link speed support. > Defined return values for sli_cqe_mq. > --- > drivers/scsi/elx/libefc_sli/sli4.c | 1216 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 1216 insertions(+) > > diff --git a/drivers/scsi/elx/libefc_sli/sli4.c b/drivers/scsi/elx/libefc_sli/sli4.c > index 0365d7943468..6ecb0f1ad19b 100644 > --- a/drivers/scsi/elx/libefc_sli/sli4.c > +++ b/drivers/scsi/elx/libefc_sli/sli4.c > @@ -3103,3 +3103,1219 @@ sli_fc_rqe_rqid_and_index(struct sli4 *sli4, u8 *cqe, > > return rc; > } > + > +/* Wait for the bootstrap mailbox to report "ready" */ > +static int > +sli_bmbx_wait(struct sli4 *sli4, u32 msec) > +{ > + u32 val = 0; > + > + do { > + mdelay(1); /* 1 ms */ Will sli_bmbx_wait() be executed in atomic context? If not, something like this here is recommended: end = jiffies + msecs_to_jiffies(msec); do { val = readl(sli4->reg[0] + SLI4_BMBX_REG); if (val & SLI4_BMBX_RDY) return EFC_SUCCESS; usleep_range(1000, 2000); } while (time_before(jiffies, end)); return EFC_FAIL; > + val = readl(sli4->reg[0] + SLI4_BMBX_REG); > + msec--; > + } while (msec && !(val & SLI4_BMBX_RDY)); > + > + val = (!(val & SLI4_BMBX_RDY)); > + return val; > +} > + > +/* Write bootstrap mailbox */ > +static int > +sli_bmbx_write(struct sli4 *sli4) > +{ > + u32 val = 0; No need to pre-initialize val. > + > + /* write buffer location to bootstrap mailbox register */ > + val = SLI4_BMBX_WRITE_HI(sli4->bmbx.phys); > + writel(val, (sli4->reg[0] + SLI4_BMBX_REG)); Is the access to the register serialized by a lock? > + > + if (sli_bmbx_wait(sli4, SLI4_BMBX_DELAY_US)) { > + efc_log_crit(sli4, "BMBX WRITE_HI failed\n"); > + return EFC_FAIL; > + } > + val = SLI4_BMBX_WRITE_LO(sli4->bmbx.phys); > + writel(val, (sli4->reg[0] + SLI4_BMBX_REG)); > + > + /* wait for SLI Port to set ready bit */ > + return sli_bmbx_wait(sli4, SLI4_BMBX_TIMEOUT_MSEC); > +} > + > +/* Submit a command to the bootstrap mailbox and check the status */ > +int > +sli_bmbx_command(struct sli4 *sli4) > +{ > + void *cqe = (u8 *)sli4->bmbx.virt + SLI4_BMBX_SIZE; > + > + if (sli_fw_error_status(sli4) > 0) { > + efc_log_crit(sli4, "Chip is in an error state -Mailbox command rejected"); > + efc_log_crit(sli4, " status=%#x error1=%#x error2=%#x\n", > + sli_reg_read_status(sli4), > + sli_reg_read_err1(sli4), > + sli_reg_read_err2(sli4)); > + return EFC_FAIL; > + } > + > + if (sli_bmbx_write(sli4)) { > + efc_log_crit(sli4, "bootstrap mailbox write fail phys=%p reg=%#x\n", > + (void *)sli4->bmbx.phys, > + readl(sli4->reg[0] + SLI4_BMBX_REG)); > + return EFC_FAIL; > + } > + > + /* check completion queue entry status */ > + if (le32_to_cpu(((struct sli4_mcqe *)cqe)->dw3_flags) & > + SLI4_MCQE_VALID) { > + return sli_cqe_mq(sli4, cqe); > + } > + efc_log_crit(sli4, "invalid or wrong type\n"); > + return EFC_FAIL; > +} > + > +/* Write a CONFIG_LINK command to the provided buffer */ > +int > +sli_cmd_config_link(struct sli4 *sli4, void *buf, size_t size) > +{ > + struct sli4_cmd_config_link *config_link = buf; > + > + memset(buf, 0, size); > + > + config_link->hdr.command = MBX_CMD_CONFIG_LINK; > + > + /* Port interprets zero in a field as "use default value" */ > + > + return EFC_SUCCESS; > +} > + > +/* Write a DOWN_LINK command to the provided buffer */ > +int > +sli_cmd_down_link(struct sli4 *sli4, void *buf, size_t size) > +{ > + struct sli4_mbox_command_header *hdr = buf; > + > + memset(buf, 0, size); > + > + hdr->command = MBX_CMD_DOWN_LINK; > + > + /* Port interprets zero in a field as "use default value" */ > + > + return EFC_SUCCESS; > +} > + > +/* Write a DUMP Type 4 command to the provided buffer */ > +int > +sli_cmd_dump_type4(struct sli4 *sli4, void *buf, > + size_t size, u16 wki) > +{ > + struct sli4_cmd_dump4 *cmd = buf; > + > + memset(buf, 0, size); > + > + cmd->hdr.command = MBX_CMD_DUMP; > + cmd->type_dword = cpu_to_le32(0x4); > + cmd->wki_selection = cpu_to_le16(wki); > + return EFC_SUCCESS; > +} > + > +/* Write a COMMON_READ_TRANSCEIVER_DATA command */ > +int > +sli_cmd_common_read_transceiver_data(struct sli4 *sli4, void *buf, > + size_t size, u32 page_num, > + struct efc_dma *dma) > +{ > + struct sli4_rqst_cmn_read_transceiver_data *req = NULL; > + u32 psize; > + > + if (!dma) > + psize = SLI_CONFIG_PYLD_LENGTH(cmn_read_transceiver_data); > + else > + psize = dma->size; > + > + req = sli_config_cmd_init(sli4, buf, size, > + psize, dma); > + if (!req) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&req->hdr, CMN_READ_TRANS_DATA, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, CFG_RQST_PYLD_LEN(cmn_read_transceiver_data)); > + > + req->page_number = cpu_to_le32(page_num); > + req->port = cpu_to_le32(sli4->port_number); > + > + return EFC_SUCCESS; > +} > + > +/* Write a READ_LINK_STAT command to the provided buffer */ > +int > +sli_cmd_read_link_stats(struct sli4 *sli4, void *buf, size_t size, > + u8 req_ext_counters, > + u8 clear_overflow_flags, > + u8 clear_all_counters) > +{ > + struct sli4_cmd_read_link_stats *cmd = buf; > + u32 flags; > + > + memset(buf, 0, size); > + > + cmd->hdr.command = MBX_CMD_READ_LNK_STAT; > + > + flags = 0; > + if (req_ext_counters) > + flags |= SLI4_READ_LNKSTAT_REC; > + if (clear_all_counters) > + flags |= SLI4_READ_LNKSTAT_CLRC; > + if (clear_overflow_flags) > + flags |= SLI4_READ_LNKSTAT_CLOF; > + > + cmd->dw1_flags = cpu_to_le32(flags); > + return EFC_SUCCESS; > +} > + > +/* Write a READ_STATUS command to the provided buffer */ > +int > +sli_cmd_read_status(struct sli4 *sli4, void *buf, size_t size, > + u8 clear_counters) > +{ > + struct sli4_cmd_read_status *cmd = buf; > + u32 flags = 0; > + > + memset(buf, 0, size); > + > + cmd->hdr.command = MBX_CMD_READ_STATUS; > + if (clear_counters) > + flags |= SLI4_READSTATUS_CLEAR_COUNTERS; > + else > + flags &= ~SLI4_READSTATUS_CLEAR_COUNTERS; > + > + cmd->dw1_flags = cpu_to_le32(flags); > + return EFC_SUCCESS; > +} > + > +/* Write an INIT_LINK command to the provided buffer */ > +int > +sli_cmd_init_link(struct sli4 *sli4, void *buf, size_t size, > + u32 speed, u8 reset_alpa) > +{ > + struct sli4_cmd_init_link *init_link = buf; > + u32 flags = 0; > + > + memset(buf, 0, size); > + > + init_link->hdr.command = MBX_CMD_INIT_LINK; > + > + init_link->sel_reset_al_pa_dword = > + cpu_to_le32(reset_alpa); > + flags &= ~SLI4_INIT_LINK_F_LOOPBACK; > + > + init_link->link_speed_sel_code = cpu_to_le32(speed); > + switch (speed) { > + case FC_LINK_SPEED_1G: > + case FC_LINK_SPEED_2G: > + case FC_LINK_SPEED_4G: > + case FC_LINK_SPEED_8G: > + case FC_LINK_SPEED_16G: > + case FC_LINK_SPEED_32G: > + case FC_LINK_SPEED_64G: > + flags |= SLI4_INIT_LINK_F_FIXED_SPEED; > + break; > + case FC_LINK_SPEED_10G: > + efc_log_info(sli4, "unsupported FC speed %d\n", speed); > + init_link->flags0 = cpu_to_le32(flags); > + return EFC_FAIL; > + } > + > + switch (sli4->topology) { > + case SLI4_READ_CFG_TOPO_FC: > + /* Attempt P2P but failover to FC-AL */ > + flags |= SLI4_INIT_LINK_F_FAIL_OVER; > + flags |= SLI4_INIT_LINK_F_P2P_FAIL_OVER; > + break; > + case SLI4_READ_CFG_TOPO_FC_AL: > + flags |= SLI4_INIT_LINK_F_FCAL_ONLY; > + if (speed == FC_LINK_SPEED_16G || speed == FC_LINK_SPEED_32G) { > + efc_log_info(sli4, "unsupported FC-AL speed %d\n", > + speed); > + init_link->flags0 = cpu_to_le32(flags); > + return EFC_FAIL; > + } > + break; > + case SLI4_READ_CFG_TOPO_FC_DA: > + flags |= SLI4_INIT_LINK_F_P2P_ONLY; > + break; > + default: > + > + efc_log_info(sli4, "unsupported topology %#x\n", > + sli4->topology); > + > + init_link->flags0 = cpu_to_le32(flags); > + return EFC_FAIL; > + } > + > + flags &= (~SLI4_INIT_LINK_F_UNFAIR); > + flags &= (~SLI4_INIT_LINK_F_NO_LIRP); > + flags &= (~SLI4_INIT_LINK_F_LOOP_VALID_CHK); > + flags &= (~SLI4_INIT_LINK_F_NO_LISA); > + flags &= (~SLI4_INIT_LINK_F_PICK_HI_ALPA); The brackets are not needed. > + init_link->flags0 = cpu_to_le32(flags); > + > + return EFC_SUCCESS; > +} > + > +/* Write an INIT_VFI command to the provided buffer */ > +int > +sli_cmd_init_vfi(struct sli4 *sli4, void *buf, size_t size, > + u16 vfi, u16 fcfi, u16 vpi) > +{ > + struct sli4_cmd_init_vfi *init_vfi = buf; > + u16 flags = 0; > + > + memset(buf, 0, size); > + > + init_vfi->hdr.command = MBX_CMD_INIT_VFI; > + > + init_vfi->vfi = cpu_to_le16(vfi); > + init_vfi->fcfi = cpu_to_le16(fcfi); > + > + /* > + * If the VPI is valid, initialize it at the same time as > + * the VFI > + */ > + if (vpi != U16_MAX) { > + flags |= SLI4_INIT_VFI_FLAG_VP; > + init_vfi->flags0_word = cpu_to_le16(flags); > + init_vfi->vpi = cpu_to_le16(vpi); > + } > + > + return EFC_SUCCESS; > +} > + > +/* Write an INIT_VPI command to the provided buffer */ > +int > +sli_cmd_init_vpi(struct sli4 *sli4, void *buf, size_t size, > + u16 vpi, u16 vfi) > +{ > + struct sli4_cmd_init_vpi *init_vpi = buf; > + > + memset(buf, 0, size); > + > + init_vpi->hdr.command = MBX_CMD_INIT_VPI; > + init_vpi->vpi = cpu_to_le16(vpi); > + init_vpi->vfi = cpu_to_le16(vfi); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_post_xri(struct sli4 *sli4, void *buf, size_t size, > + u16 xri_base, u16 xri_count) > +{ > + struct sli4_cmd_post_xri *post_xri = buf; > + u16 xri_count_flags = 0; > + > + memset(buf, 0, size); > + > + post_xri->hdr.command = MBX_CMD_POST_XRI; > + post_xri->xri_base = cpu_to_le16(xri_base); > + xri_count_flags = (xri_count & SLI4_POST_XRI_COUNT); The brackets are not needed. > + xri_count_flags |= SLI4_POST_XRI_FLAG_ENX; > + xri_count_flags |= SLI4_POST_XRI_FLAG_VAL; > + post_xri->xri_count_flags = cpu_to_le16(xri_count_flags); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_release_xri(struct sli4 *sli4, void *buf, size_t size, > + u8 num_xri) > +{ > + struct sli4_cmd_release_xri *release_xri = buf; > + > + memset(buf, 0, size); Just as reminder, I think this memset() pattern should only operator on cmd size and not over the whole buffer if the firmware can handle it. > + > + release_xri->hdr.command = MBX_CMD_RELEASE_XRI; > + release_xri->xri_count_word = cpu_to_le16(num_xri & > + SLI4_RELEASE_XRI_COUNT); > + > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_read_config(struct sli4 *sli4, void *buf, size_t size) > +{ > + struct sli4_cmd_read_config *read_config = buf; > + > + memset(buf, 0, size); > + > + read_config->hdr.command = MBX_CMD_READ_CONFIG; > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_read_nvparms(struct sli4 *sli4, void *buf, size_t size) > +{ > + struct sli4_cmd_read_nvparms *read_nvparms = buf; > + > + memset(buf, 0, size); > + > + read_nvparms->hdr.command = MBX_CMD_READ_NVPARMS; > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_write_nvparms(struct sli4 *sli4, void *buf, size_t size, > + u8 *wwpn, u8 *wwnn, u8 hard_alpa, > + u32 preferred_d_id) > +{ > + struct sli4_cmd_write_nvparms *write_nvparms = buf; > + > + memset(buf, 0, size); > + > + write_nvparms->hdr.command = MBX_CMD_WRITE_NVPARMS; > + memcpy(write_nvparms->wwpn, wwpn, 8); > + memcpy(write_nvparms->wwnn, wwnn, 8); > + > + write_nvparms->hard_alpa_d_id = > + cpu_to_le32((preferred_d_id << 8) | hard_alpa); > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_read_rev(struct sli4 *sli4, void *buf, size_t size, > + struct efc_dma *vpd) > +{ > + struct sli4_cmd_read_rev *read_rev = buf; > + > + memset(buf, 0, size); > + > + read_rev->hdr.command = MBX_CMD_READ_REV; > + > + if (vpd && vpd->size) { > + read_rev->flags0_word |= cpu_to_le16(SLI4_READ_REV_FLAG_VPD); > + > + read_rev->available_length_dword = > + cpu_to_le32(vpd->size & > + SLI4_READ_REV_AVAILABLE_LENGTH); > + > + read_rev->hostbuf.low = > + cpu_to_le32(lower_32_bits(vpd->phys)); > + read_rev->hostbuf.high = > + cpu_to_le32(upper_32_bits(vpd->phys)); > + } > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_read_sparm64(struct sli4 *sli4, void *buf, size_t size, > + struct efc_dma *dma, > + u16 vpi) > +{ > + struct sli4_cmd_read_sparm64 *read_sparm64 = buf; > + > + memset(buf, 0, size); > + > + if (vpi == U16_MAX) { > + efc_log_err(sli4, "special VPI not supported!!!\n"); > + return EFC_FAIL; > + } > + > + if (!dma || !dma->phys) { > + efc_log_err(sli4, "bad DMA buffer\n"); > + return EFC_FAIL; > + } > + > + read_sparm64->hdr.command = MBX_CMD_READ_SPARM64; > + > + read_sparm64->bde_64.bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (dma->size & SLI4_BDE_MASK_BUFFER_LEN)); > + read_sparm64->bde_64.u.data.low = > + cpu_to_le32(lower_32_bits(dma->phys)); > + read_sparm64->bde_64.u.data.high = > + cpu_to_le32(upper_32_bits(dma->phys)); > + > + read_sparm64->vpi = cpu_to_le16(vpi); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_read_topology(struct sli4 *sli4, void *buf, size_t size, > + struct efc_dma *dma) > +{ > + struct sli4_cmd_read_topology *read_topo = buf; > + > + memset(buf, 0, size); > + > + read_topo->hdr.command = MBX_CMD_READ_TOPOLOGY; > + > + if (dma && dma->size) { > + if (dma->size < SLI4_MIN_LOOP_MAP_BYTES) { > + efc_log_err(sli4, "loop map buffer too small %zx\n", > + dma->size); > + return EFC_FAIL; > + } Shouldn't this fail also when dma or dma->size is invalid? if (!dma || !(dma->size && dma->size < SLI4_MIN_LOOP_MAP_BYTES)) return EFC_FAIL; And why is this test not before memset()? > + > + memset(dma->virt, 0, dma->size); > + > + read_topo->bde_loop_map.bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (dma->size & SLI4_BDE_MASK_BUFFER_LEN)); > + read_topo->bde_loop_map.u.data.low = > + cpu_to_le32(lower_32_bits(dma->phys)); > + read_topo->bde_loop_map.u.data.high = > + cpu_to_le32(upper_32_bits(dma->phys)); > + } > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_reg_fcfi(struct sli4 *sli4, void *buf, size_t size, > + u16 index, > + struct sli4_cmd_rq_cfg rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG]) > +{ > + struct sli4_cmd_reg_fcfi *reg_fcfi = buf; > + u32 i; > + > + memset(buf, 0, size); > + > + reg_fcfi->hdr.command = MBX_CMD_REG_FCFI; > + > + reg_fcfi->fcf_index = cpu_to_le16(index); > + > + for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) { > + switch (i) { > + case 0: > + reg_fcfi->rqid0 = rq_cfg[0].rq_id; > + break; > + case 1: > + reg_fcfi->rqid1 = rq_cfg[1].rq_id; > + break; > + case 2: > + reg_fcfi->rqid2 = rq_cfg[2].rq_id; > + break; > + case 3: > + reg_fcfi->rqid3 = rq_cfg[3].rq_id; > + break; > + } > + reg_fcfi->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask; > + reg_fcfi->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match; > + reg_fcfi->rq_cfg[i].type_mask = rq_cfg[i].type_mask; > + reg_fcfi->rq_cfg[i].type_match = rq_cfg[i].type_match; > + } > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_reg_fcfi_mrq(struct sli4 *sli4, void *buf, size_t size, > + u8 mode, u16 fcf_index, > + u8 rq_selection_policy, u8 mrq_bit_mask, > + u16 num_mrqs, > + struct sli4_cmd_rq_cfg rq_cfg[SLI4_CMD_REG_FCFI_NUM_RQ_CFG]) > +{ > + struct sli4_cmd_reg_fcfi_mrq *reg_fcfi_mrq = buf; > + u32 i; > + u32 mrq_flags = 0; > + > + memset(buf, 0, size); > + > + reg_fcfi_mrq->hdr.command = MBX_CMD_REG_FCFI_MRQ; > + if (mode == SLI4_CMD_REG_FCFI_SET_FCFI_MODE) { > + reg_fcfi_mrq->fcf_index = cpu_to_le16(fcf_index); > + goto done; > + } > + > + for (i = 0; i < SLI4_CMD_REG_FCFI_NUM_RQ_CFG; i++) { > + reg_fcfi_mrq->rq_cfg[i].r_ctl_mask = rq_cfg[i].r_ctl_mask; > + reg_fcfi_mrq->rq_cfg[i].r_ctl_match = rq_cfg[i].r_ctl_match; > + reg_fcfi_mrq->rq_cfg[i].type_mask = rq_cfg[i].type_mask; > + reg_fcfi_mrq->rq_cfg[i].type_match = rq_cfg[i].type_match; > + > + switch (i) { > + case 3: > + reg_fcfi_mrq->rqid3 = rq_cfg[i].rq_id; > + break; > + case 2: > + reg_fcfi_mrq->rqid2 = rq_cfg[i].rq_id; > + break; > + case 1: > + reg_fcfi_mrq->rqid1 = rq_cfg[i].rq_id; > + break; > + case 0: > + reg_fcfi_mrq->rqid0 = rq_cfg[i].rq_id; > + break; > + } > + } > + > + mrq_flags = num_mrqs & SLI4_REGFCFI_MRQ_MASK_NUM_PAIRS; > + mrq_flags |= (mrq_bit_mask << 8); > + mrq_flags |= (rq_selection_policy << 12); > + reg_fcfi_mrq->dw9_mrqflags = cpu_to_le32(mrq_flags); > +done: > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_reg_rpi(struct sli4 *sli4, void *buf, size_t size, > + u32 nport_id, u16 rpi, u16 vpi, > + struct efc_dma *dma, u8 update, > + u8 enable_t10_pi) > +{ > + struct sli4_cmd_reg_rpi *reg_rpi = buf; > + u32 rportid_flags = 0; > + > + memset(buf, 0, size); > + > + reg_rpi->hdr.command = MBX_CMD_REG_RPI; > + > + reg_rpi->rpi = cpu_to_le16(rpi); > + > + rportid_flags = nport_id & SLI4_REGRPI_REMOTE_N_PORTID; > + > + if (update) > + rportid_flags |= SLI4_REGRPI_UPD; > + else > + rportid_flags &= ~SLI4_REGRPI_UPD; > + > + if (enable_t10_pi) > + rportid_flags |= SLI4_REGRPI_ETOW; > + else > + rportid_flags &= ~SLI4_REGRPI_ETOW; > + > + reg_rpi->dw2_rportid_flags = cpu_to_le32(rportid_flags); > + > + reg_rpi->bde_64.bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (SLI4_REG_RPI_BUF_LEN & SLI4_BDE_MASK_BUFFER_LEN)); > + reg_rpi->bde_64.u.data.low = > + cpu_to_le32(lower_32_bits(dma->phys)); > + reg_rpi->bde_64.u.data.high = > + cpu_to_le32(upper_32_bits(dma->phys)); > + > + reg_rpi->vpi = cpu_to_le16(vpi); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_reg_vfi(struct sli4 *sli4, void *buf, size_t size, > + u16 vfi, u16 fcfi, struct efc_dma dma, > + u16 vpi, __be64 sli_wwpn, u32 fc_id) > +{ > + struct sli4_cmd_reg_vfi *reg_vfi = buf; > + > + memset(buf, 0, size); > + > + reg_vfi->hdr.command = MBX_CMD_REG_VFI; > + > + reg_vfi->vfi = cpu_to_le16(vfi); > + > + reg_vfi->fcfi = cpu_to_le16(fcfi); > + > + reg_vfi->sparm.bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (SLI4_REG_RPI_BUF_LEN & SLI4_BDE_MASK_BUFFER_LEN)); > + reg_vfi->sparm.u.data.low = > + cpu_to_le32(lower_32_bits(dma.phys)); > + reg_vfi->sparm.u.data.high = > + cpu_to_le32(upper_32_bits(dma.phys)); > + > + reg_vfi->e_d_tov = cpu_to_le32(sli4->e_d_tov); > + reg_vfi->r_a_tov = cpu_to_le32(sli4->r_a_tov); > + > + reg_vfi->dw0w1_flags |= cpu_to_le16(SLI4_REGVFI_VP); > + reg_vfi->vpi = cpu_to_le16(vpi); > + memcpy(reg_vfi->wwpn, &sli_wwpn, sizeof(reg_vfi->wwpn)); > + reg_vfi->dw10_lportid_flags = cpu_to_le32(fc_id); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_reg_vpi(struct sli4 *sli4, void *buf, size_t size, > + u32 fc_id, __be64 sli_wwpn, u16 vpi, u16 vfi, > + bool update) > +{ > + struct sli4_cmd_reg_vpi *reg_vpi = buf; > + u32 flags = 0; > + > + memset(buf, 0, size); > + > + reg_vpi->hdr.command = MBX_CMD_REG_VPI; > + > + flags = (fc_id & SLI4_REGVPI_LOCAL_N_PORTID); > + if (update) > + flags |= SLI4_REGVPI_UPD; > + else > + flags &= ~SLI4_REGVPI_UPD; > + > + reg_vpi->dw2_lportid_flags = cpu_to_le32(flags); > + memcpy(reg_vpi->wwpn, &sli_wwpn, sizeof(reg_vpi->wwpn)); > + reg_vpi->vpi = cpu_to_le16(vpi); > + reg_vpi->vfi = cpu_to_le16(vfi); > + > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_request_features(struct sli4 *sli4, void *buf, size_t size, > + u32 features_mask, bool query) > +{ > + struct sli4_cmd_request_features *req_features = buf; > + > + memset(buf, 0, size); > + > + req_features->hdr.command = MBX_CMD_RQST_FEATURES; > + > + if (query) > + req_features->dw1_qry = cpu_to_le32(SLI4_REQFEAT_QRY); > + > + req_features->cmd = cpu_to_le32(features_mask); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_unreg_fcfi(struct sli4 *sli4, void *buf, size_t size, > + u16 indicator) > +{ > + struct sli4_cmd_unreg_fcfi *unreg_fcfi = buf; > + > + memset(buf, 0, size); > + > + unreg_fcfi->hdr.command = MBX_CMD_UNREG_FCFI; > + > + unreg_fcfi->fcfi = cpu_to_le16(indicator); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_unreg_rpi(struct sli4 *sli4, void *buf, size_t size, > + u16 indicator, > + enum sli4_resource which, u32 fc_id) > +{ > + struct sli4_cmd_unreg_rpi *unreg_rpi = buf; > + u32 flags = 0; > + > + memset(buf, 0, size); > + > + unreg_rpi->hdr.command = MBX_CMD_UNREG_RPI; > + > + switch (which) { > + case SLI_RSRC_RPI: > + flags |= UNREG_RPI_II_RPI; > + if (fc_id == U32_MAX) > + break; > + > + flags |= UNREG_RPI_DP; > + unreg_rpi->dw2_dest_n_portid = > + cpu_to_le32(fc_id & UNREG_RPI_DEST_N_PORTID_MASK); > + break; > + case SLI_RSRC_VPI: > + flags |= UNREG_RPI_II_VPI; > + break; > + case SLI_RSRC_VFI: > + flags |= UNREG_RPI_II_VFI; > + break; > + case SLI_RSRC_FCFI: > + flags |= UNREG_RPI_II_FCFI; > + break; > + default: > + efc_log_info(sli4, "unknown type %#x\n", which); > + return EFC_FAIL; > + } > + > + unreg_rpi->dw1w1_flags = cpu_to_le16(flags); > + unreg_rpi->index = cpu_to_le16(indicator); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_unreg_vfi(struct sli4 *sli4, void *buf, size_t size, > + u16 index, u32 which) > +{ > + struct sli4_cmd_unreg_vfi *unreg_vfi = buf; > + > + memset(buf, 0, size); > + > + unreg_vfi->hdr.command = MBX_CMD_UNREG_VFI; > + switch (which) { > + case SLI4_UNREG_TYPE_DOMAIN: > + unreg_vfi->index = cpu_to_le16(index); > + break; > + case SLI4_UNREG_TYPE_FCF: > + unreg_vfi->index = cpu_to_le16(index); > + break; > + case SLI4_UNREG_TYPE_ALL: > + unreg_vfi->index = cpu_to_le16(U32_MAX); > + break; > + default: > + return EFC_FAIL; > + } > + > + if (which != SLI4_UNREG_TYPE_DOMAIN) > + unreg_vfi->dw2_flags = > + cpu_to_le16(UNREG_VFI_II_FCFI); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_unreg_vpi(struct sli4 *sli4, void *buf, size_t size, > + u16 indicator, u32 which) > +{ > + struct sli4_cmd_unreg_vpi *unreg_vpi = buf; > + u32 flags = 0; > + > + memset(buf, 0, size); > + > + unreg_vpi->hdr.command = MBX_CMD_UNREG_VPI; > + unreg_vpi->index = cpu_to_le16(indicator); > + switch (which) { > + case SLI4_UNREG_TYPE_PORT: > + flags |= UNREG_VPI_II_VPI; > + break; > + case SLI4_UNREG_TYPE_DOMAIN: > + flags |= UNREG_VPI_II_VFI; > + break; > + case SLI4_UNREG_TYPE_FCF: > + flags |= UNREG_VPI_II_FCFI; > + break; > + case SLI4_UNREG_TYPE_ALL: > + /* override indicator */ > + unreg_vpi->index = cpu_to_le16(U32_MAX); > + flags |= UNREG_VPI_II_FCFI; > + break; > + default: > + return EFC_FAIL; > + } > + > + unreg_vpi->dw2w0_flags = cpu_to_le16(flags); > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_common_modify_eq_delay(struct sli4 *sli4, void *buf, size_t size, > + struct sli4_queue *q, int num_q, u32 shift, > + u32 delay_mult) > +{ > + struct sli4_rqst_cmn_modify_eq_delay *req = NULL; > + int i; > + > + req = sli_config_cmd_init(sli4, buf, size, > + SLI_CONFIG_PYLD_LENGTH(cmn_modify_eq_delay), > + NULL); > + if (!req) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&req->hdr, CMN_MODIFY_EQ_DELAY, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, CFG_RQST_PYLD_LEN(cmn_modify_eq_delay)); > + req->num_eq = cpu_to_le32(num_q); > + > + for (i = 0; i < num_q; i++) { > + req->eq_delay_record[i].eq_id = cpu_to_le32(q[i].id); > + req->eq_delay_record[i].phase = cpu_to_le32(shift); > + req->eq_delay_record[i].delay_multiplier = > + cpu_to_le32(delay_mult); > + } > + > + return EFC_SUCCESS; > +} > + > +void > +sli4_cmd_lowlevel_set_watchdog(struct sli4 *sli4, void *buf, > + size_t size, u16 timeout) > +{ > + struct sli4_rqst_lowlevel_set_watchdog *req = NULL; > + > + req = sli_config_cmd_init(sli4, buf, size, > + SLI_CONFIG_PYLD_LENGTH(lowlevel_set_watchdog), > + NULL); > + if (!req) > + return; > + > + sli_cmd_fill_hdr(&req->hdr, SLI4_OPC_LOWLEVEL_SET_WATCHDOG, > + SLI4_SUBSYSTEM_LOWLEVEL, CMD_V0, > + CFG_RQST_PYLD_LEN(lowlevel_set_watchdog)); > + req->watchdog_timeout = cpu_to_le16(timeout); > +} > + > +static int > +sli_cmd_common_get_cntl_attributes(struct sli4 *sli4, void *buf, size_t size, > + struct efc_dma *dma) > +{ > + struct sli4_rqst_hdr *hdr = NULL; > + > + hdr = sli_config_cmd_init(sli4, buf, size, CFG_RQST_CMDSZ(hdr), dma); > + if (!hdr) > + return EFC_FAIL; > + > + hdr->opcode = CMN_GET_CNTL_ATTRIBUTES; > + hdr->subsystem = SLI4_SUBSYSTEM_COMMON; > + hdr->request_length = cpu_to_le32(dma->size); > + > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_common_get_cntl_addl_attributes(struct sli4 *sli4, void *buf, > + size_t size, struct efc_dma *dma) > +{ > + struct sli4_rqst_hdr *hdr = NULL; > + > + hdr = sli_config_cmd_init(sli4, buf, size, CFG_RQST_CMDSZ(hdr), dma); > + if (!hdr) > + return EFC_FAIL; > + > + hdr->opcode = CMN_GET_CNTL_ADDL_ATTRS; > + hdr->subsystem = SLI4_SUBSYSTEM_COMMON; > + hdr->request_length = cpu_to_le32(dma->size); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_nop(struct sli4 *sli4, void *buf, > + size_t size, uint64_t context) > +{ > + struct sli4_rqst_cmn_nop *nop = NULL; > + > + nop = sli_config_cmd_init(sli4, buf, size, > + SLI_CONFIG_PYLD_LENGTH(cmn_nop), NULL); > + if (!nop) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&nop->hdr, CMN_NOP, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, CFG_RQST_PYLD_LEN(cmn_nop)); > + > + memcpy(&nop->context, &context, sizeof(context)); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_get_resource_extent_info(struct sli4 *sli4, void *buf, > + size_t size, u16 rtype) > +{ > + struct sli4_rqst_cmn_get_resource_extent_info *extent = NULL; > + > + extent = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_get_resource_extent_info), > + NULL); > + if (extent) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&extent->hdr, CMN_GET_RSC_EXTENT_INFO, > + SLI4_SUBSYSTEM_COMMON, CMD_V0, > + CFG_RQST_PYLD_LEN(cmn_get_resource_extent_info)); > + > + extent->resource_type = cpu_to_le16(rtype); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_get_sli4_parameters(struct sli4 *sli4, void *buf, > + size_t size) > +{ > + struct sli4_rqst_hdr *hdr = NULL; > + > + hdr = sli_config_cmd_init(sli4, buf, size, > + SLI_CONFIG_PYLD_LENGTH(cmn_get_sli4_params), > + NULL); > + if (!hdr) > + return EFC_FAIL; > + > + hdr->opcode = CMN_GET_SLI4_PARAMS; > + hdr->subsystem = SLI4_SUBSYSTEM_COMMON; > + hdr->request_length = CFG_RQST_PYLD_LEN(cmn_get_sli4_params); > + > + return EFC_SUCCESS; > +} > + > +static int > +sli_cmd_common_get_port_name(struct sli4 *sli4, void *buf, size_t size) > +{ > + struct sli4_rqst_cmn_get_port_name *pname; > + > + pname = sli_config_cmd_init(sli4, buf, size, > + SLI_CONFIG_PYLD_LENGTH(cmn_get_port_name), > + NULL); > + if (!pname) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&pname->hdr, CMN_GET_PORT_NAME, SLI4_SUBSYSTEM_COMMON, > + CMD_V1, CFG_RQST_PYLD_LEN(cmn_get_port_name)); > + > + /* Set the port type value (ethernet=0, FC=1) for V1 commands */ > + pname->port_type = PORT_TYPE_FC; > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_write_object(struct sli4 *sli4, void *buf, size_t size, > + u16 noc, > + u16 eof, u32 desired_write_length, > + u32 offset, char *object_name, > + struct efc_dma *dma) > +{ > + struct sli4_rqst_cmn_write_object *wr_obj = NULL; > + struct sli4_bde *bde; > + u32 dwflags = 0; > + > + wr_obj = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_write_object) + > + sizeof(*bde), NULL); > + if (!wr_obj) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&wr_obj->hdr, CMN_WRITE_OBJECT, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, > + CFG_RQST_PYLD_LEN_VAR(cmn_write_object, sizeof(*bde))); > + > + if (noc) > + dwflags |= SLI4_RQ_DES_WRITE_LEN_NOC; > + if (eof) > + dwflags |= SLI4_RQ_DES_WRITE_LEN_EOF; > + dwflags |= (desired_write_length & SLI4_RQ_DES_WRITE_LEN); > + > + wr_obj->desired_write_len_dword = cpu_to_le32(dwflags); > + > + wr_obj->write_offset = cpu_to_le32(offset); > + strncpy(wr_obj->object_name, object_name, > + sizeof(wr_obj->object_name)); > + wr_obj->host_buffer_descriptor_count = cpu_to_le32(1); > + > + bde = (struct sli4_bde *)wr_obj->host_buffer_descriptor; > + > + /* Setup to transfer xfer_size bytes to device */ > + bde->bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (desired_write_length & SLI4_BDE_MASK_BUFFER_LEN)); > + bde->u.data.low = cpu_to_le32(lower_32_bits(dma->phys)); > + bde->u.data.high = cpu_to_le32(upper_32_bits(dma->phys)); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_delete_object(struct sli4 *sli4, void *buf, size_t size, > + char *object_name) > +{ > + struct sli4_rqst_cmn_delete_object *req = NULL; > + > + req = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_delete_object), NULL); > + if (!req) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&req->hdr, CMN_DELETE_OBJECT, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, CFG_RQST_PYLD_LEN(cmn_delete_object)); > + > + strncpy(req->object_name, object_name, sizeof(req->object_name)); > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_read_object(struct sli4 *sli4, void *buf, size_t size, > + u32 desired_read_length, u32 offset, > + char *object_name, struct efc_dma *dma) > +{ > + struct sli4_rqst_cmn_read_object *rd_obj = NULL; > + struct sli4_bde *bde; > + > + rd_obj = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_read_object) + > + sizeof(*bde), NULL); > + if (!rd_obj) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&rd_obj->hdr, CMN_READ_OBJECT, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, > + CFG_RQST_PYLD_LEN_VAR(cmn_read_object, sizeof(*bde))); > + rd_obj->desired_read_length_dword = > + cpu_to_le32(desired_read_length & SLI4_REQ_DESIRE_READLEN); > + > + rd_obj->read_offset = cpu_to_le32(offset); > + strncpy(rd_obj->object_name, object_name, > + sizeof(rd_obj->object_name)); Does the string a NUL termination? > + rd_obj->host_buffer_descriptor_count = cpu_to_le32(1); > + > + bde = (struct sli4_bde *)rd_obj->host_buffer_descriptor; > + > + /* Setup to transfer xfer_size bytes to device */ > + bde->bde_type_buflen = > + cpu_to_le32((BDE_TYPE_BDE_64 << BDE_TYPE_SHIFT) | > + (desired_read_length & SLI4_BDE_MASK_BUFFER_LEN)); > + if (dma) { > + bde->u.data.low = cpu_to_le32(lower_32_bits(dma->phys)); > + bde->u.data.high = cpu_to_le32(upper_32_bits(dma->phys)); > + } else { > + bde->u.data.low = 0; > + bde->u.data.high = 0; > + } > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_dmtf_exec_clp_cmd(struct sli4 *sli4, void *buf, size_t size, > + struct efc_dma *cmd, > + struct efc_dma *resp) > +{ > + struct sli4_rqst_dmtf_exec_clp_cmd *clp_cmd = NULL; > + > + clp_cmd = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(dmtf_exec_clp_cmd), NULL); > + if (!clp_cmd) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&clp_cmd->hdr, DMTF_EXEC_CLP_CMD, SLI4_SUBSYSTEM_DMTF, > + CMD_V0, CFG_RQST_PYLD_LEN(dmtf_exec_clp_cmd)); > + > + clp_cmd->cmd_buf_length = cpu_to_le32(cmd->size); > + clp_cmd->cmd_buf_addr_low = cpu_to_le32(lower_32_bits(cmd->phys)); > + clp_cmd->cmd_buf_addr_high = cpu_to_le32(upper_32_bits(cmd->phys)); > + clp_cmd->resp_buf_length = cpu_to_le32(resp->size); > + clp_cmd->resp_buf_addr_low = cpu_to_le32(lower_32_bits(resp->phys)); > + clp_cmd->resp_buf_addr_high = cpu_to_le32(upper_32_bits(resp->phys)); whitespace damage > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_set_dump_location(struct sli4 *sli4, void *buf, > + size_t size, bool query, > + bool is_buffer_list, > + struct efc_dma *buffer, u8 fdb) > +{ > + struct sli4_rqst_cmn_set_dump_location *set_dump_loc = NULL; > + u32 buffer_length_flag = 0; > + > + set_dump_loc = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_set_dump_location), > + NULL); > + if (!set_dump_loc) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&set_dump_loc->hdr, CMN_SET_DUMP_LOCATION, > + SLI4_SUBSYSTEM_COMMON, CMD_V0, > + CFG_RQST_PYLD_LEN(cmn_set_dump_location)); > + > + if (is_buffer_list) > + buffer_length_flag |= SLI4_CMN_SET_DUMP_BLP; > + > + if (query) > + buffer_length_flag |= SLI4_CMN_SET_DUMP_QRY; > + > + if (fdb) > + buffer_length_flag |= SLI4_CMN_SET_DUMP_FDB; > + > + if (buffer) { > + set_dump_loc->buf_addr_low = > + cpu_to_le32(lower_32_bits(buffer->phys)); > + set_dump_loc->buf_addr_high = > + cpu_to_le32(upper_32_bits(buffer->phys)); > + > + buffer_length_flag |= (buffer->len & > + SLI4_CMN_SET_DUMP_BUFFER_LEN); > + } else { > + set_dump_loc->buf_addr_low = 0; > + set_dump_loc->buf_addr_high = 0; > + set_dump_loc->buffer_length_dword = 0; > + } > + set_dump_loc->buffer_length_dword = cpu_to_le32(buffer_length_flag); > + return EFC_SUCCESS; > +} > + > +int > +sli_cmd_common_set_features(struct sli4 *sli4, void *buf, size_t size, > + u32 feature, > + u32 param_len, > + void *parameter) > +{ > + struct sli4_rqst_cmn_set_features *cmd = NULL; > + > + cmd = sli_config_cmd_init(sli4, buf, size, > + CFG_RQST_CMDSZ(cmn_set_features), NULL); > + if (!cmd) > + return EFC_FAIL; > + > + sli_cmd_fill_hdr(&cmd->hdr, CMN_SET_FEATURES, SLI4_SUBSYSTEM_COMMON, > + CMD_V0, CFG_RQST_PYLD_LEN(cmn_set_features)); > + > + cmd->feature = cpu_to_le32(feature); > + cmd->param_len = cpu_to_le32(param_len); > + memcpy(cmd->params, parameter, param_len); > + > + return EFC_SUCCESS; > +} > + > +int > +sli_cqe_mq(struct sli4 *sli4, void *buf) > +{ > + struct sli4_mcqe *mcqe = buf; > + u32 dwflags = le32_to_cpu(mcqe->dw3_flags); > + /* > + * Firmware can split mbx completions into two MCQEs: first with only > + * the "consumed" bit set and a second with the "complete" bit set. > + * Thus, ignore MCQE unless "complete" is set. > + */ > + if (!(dwflags & SLI4_MCQE_COMPLETED)) > + return SLI4_MCQE_STATUS_NOT_COMPLETED; > + > + if (le16_to_cpu(mcqe->completion_status)) { > + efc_log_info(sli4, "status(st=%#x ext=%#x con=%d cmp=%d ae=%d val=%d)\n", > + le16_to_cpu(mcqe->completion_status), > + le16_to_cpu(mcqe->extended_status), > + (dwflags & SLI4_MCQE_CONSUMED), > + (dwflags & SLI4_MCQE_COMPLETED), > + (dwflags & SLI4_MCQE_AE), > + (dwflags & SLI4_MCQE_VALID)); > + } > + > + return le16_to_cpu(mcqe->completion_status); > +} > + > +int > +sli_cqe_async(struct sli4 *sli4, void *buf) > +{ > + struct sli4_acqe *acqe = buf; > + int rc = EFC_FAIL; > + > + if (!buf) { > + efc_log_err(sli4, "bad parameter sli4=%p buf=%p\n", sli4, buf); > + return EFC_FAIL; > + } > + > + switch (acqe->event_code) { > + case SLI4_ACQE_EVENT_CODE_LINK_STATE: > + efc_log_info(sli4, "Unsupported by FC link, evt code:%#x\n", > + acqe->event_code); > + break; > + case SLI4_ACQE_EVENT_CODE_GRP_5: > + efc_log_info(sli4, "ACQE GRP5\n"); > + break; > + case SLI4_ACQE_EVENT_CODE_SLI_PORT_EVENT: > + efc_log_info(sli4, "ACQE SLI Port, type=0x%x, data1,2=0x%08x,0x%08x\n", > + acqe->event_type, > + le32_to_cpu(acqe->event_data[0]), > + le32_to_cpu(acqe->event_data[1])); > + break; > + case SLI4_ACQE_EVENT_CODE_FC_LINK_EVENT: > + rc = sli_fc_process_link_attention(sli4, buf); > + break; > + default: > + efc_log_info(sli4, "ACQE unknown=%#x\n", > + acqe->event_code); > + } > + > + return rc; > +} > -- > 2.16.4 > Thanks, Daniel