2026-01-21 18:59:54 +08:00

668 lines
22 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Huawei Fabric Channel Linux driver
* Copyright(c) 2018 Huawei Technologies Co., Ltd
*
*/
#include "hifc_module.h"
#include "hifc_service.h"
void hifc_build_common_wqe_ctrls(struct hifcoe_wqe_ctrl_s *v_ctrl_sl,
unsigned char v_task_len)
{
/* "BDSL" field of CtrlS - defines the size of BDS,
* which varies from 0 to 2040 bytes (8 bits of 8 bytes' chunk)
*/
v_ctrl_sl->ch.wd0.bdsl = 0;
/*
* "DrvSL" field of CtrlS - defines the size of DrvS, which varies from
* 0 to 24 bytes
*/
v_ctrl_sl->ch.wd0.drv_sl = 0;
/* a.
* b1 - linking WQE, which will be only used in linked page architecture
* instead of ring, it's a special control WQE which does not contain
* any buffer or inline data information, and will only be consumed by
* hardware. The size is aligned to WQEBB/WQE b0 - normal WQE, either
* normal SEG WQE or inline data WQE
*/
v_ctrl_sl->ch.wd0.wf = 0;
/*
* "CF" field of CtrlS - Completion Format - defines the format of CS.
* a.b0 - Status information is embedded inside of Completion Section
* b.b1 - Completion Section keeps SGL, where Status information
* should be written. (For the definition of SGLs see ?4.1* .)
*/
v_ctrl_sl->ch.wd0.cf = 0;
/*
* "TSL" field of CtrlS - defines the size of TS, which varies from 0
* to 248 bytes
*/
v_ctrl_sl->ch.wd0.tsl = v_task_len;
/*
* Variable length SGE (vSGE). The size of SGE is 16 bytes. The vSGE
* format is of two types, which are defined by "VA " field of CtrlS.
* "VA" stands for Virtual Address: o b0. SGE comprises 64-bits buffer's
* pointer and 31-bits Length, each SGE can only support up to 2G-1B,
* it can guarantee each single SGE length can not exceed 2GB by nature,
* A byte count value of zero means a 0byte data transfer.o b1.
* SGE comprises 64-bits buffer's pointer, 31-bits Length and 30-bits
* Key of the Translation table ,each SGE can only support up to 2G-1B,
* it can guarantee each single SGE length can notexceed 2GB by nature,
* A byte count value of zero means a 0byte data transfer
*/
v_ctrl_sl->ch.wd0.va = 0;
/*
* "DF" field of CtrlS - Data Format - defines the format of BDS
* a. b0 - BDS carries the list of SGEs (SGL)
* b. b1 - BDS carries the inline data
*/
v_ctrl_sl->ch.wd0.df = 0;
/*
* "CR" - Completion is Required - marks CQE generation request per WQE
*/
v_ctrl_sl->ch.wd0.cr = 1;
/*
* "DIFSL" field of CtrlS - defines the size of DIFS, which varies from
* 0 to 56 bytes
*/
v_ctrl_sl->ch.wd0.dif_sl = 0;
/*
* "CSL" field of CtrlS - defines the size of CS, which varies from 0 to
* 24 bytes
*/
v_ctrl_sl->ch.wd0.csl = 0;
/* "CtrlSL" - C describes the size of CtrlS in 8 bytes chunks.
*The value Zero is not valid
*/
v_ctrl_sl->ch.wd0.ctrl_sl = 1;
/* "O" - Owner - marks ownership of WQE */
v_ctrl_sl->ch.wd0.owner = 0;
}
void hifc_build_trd_twr_wqe_ctrls(struct unf_frame_pkg_s *v_pkg,
struct hifcoe_sqe_s *v_sqe)
{
/* "BDSL" field of CtrlS - defines the size of BDS, which varies from
* 0 to 2040 bytes (8 bits of 8 bytes' chunk)
*/
/* TrdWqe carry 2 SGE defaultly, 4DW per SGE, the value is 4 because
* unit is 2DW, in double SGL mode, bdsl is 2
*/
v_sqe->ctrl_sl.ch.wd0.bdsl = HIFC_T_RD_WR_WQE_CTR_BDSL_SIZE;
/*
* "DrvSL" field of CtrlS - defines the size of DrvS, which varies from
* 0 to 24 bytes DrvSL config for 0
*/
v_sqe->ctrl_sl.ch.wd0.drv_sl = 0;
/* a. b1 - linking WQE, which will be only used in linked page
* architecture instead of ring, it's a special control WQE which does
* not contain any buffer or inline data information, and will only be
* consumed by hardware. The size is aligned to WQEBB/WQE b0 - normal
* WQE, either normal SEG WQE or inline data WQE
*/
/* normal wqe */
v_sqe->ctrl_sl.ch.wd0.wf = 0;
/*
* "CF" field of CtrlS - Completion Format - defines the format of CS.
* a.b0 - Status information is embedded inside of Completion Section
* b.b1 - Completion Section keeps SGL, where Status information
* should be written. (For the definition of SGLs see ?4.1.)
*/
/* by SCQE mode, the value is ignored */
v_sqe->ctrl_sl.ch.wd0.cf = 0;
/* "TSL" field of CtrlS - defines the size of TS, which varies from 0 to
* 248 bytes
*/
/* TSL is configured by 56 bytes */
v_sqe->ctrl_sl.ch.wd0.tsl = sizeof(struct hifcoe_sqe_ts_s) /
HIFC_WQE_SECTION_CHUNK_SIZE;
/*
* Variable length SGE (vSGE). The size of SGE is 16 bytes. The vSGE
* format is of two types, which are defined by "VA" field of CtrlS.
* "VA" stands for Virtual Address: o b0. SGE comprises 64-bits buffer's
* pointer and 31-bits Length, each SGE can only support up to 2G-1B, it
* can guarantee each single SGE length can not exceed 2GB by nature, A
* byte count value of zero means a 0byte data transfer. o b1. SGE
* comprises 64-bits buffer's pointer, 31-bits Length and 30-bits Key of
* the Translation table , each SGE can only support up to 2G-1B, it can
* guarantee each single SGE length can not exceed 2GB by nature, A byte
* count value of zero means a 0byte data transfer
*/
v_sqe->ctrl_sl.ch.wd0.va = 0;
/*
* "DF" field of CtrlS - Data Format - defines the format of BDS
* a. b0 - BDS carries the list of SGEs (SGL)
* b. b1 - BDS carries the inline data
*/
v_sqe->ctrl_sl.ch.wd0.df = 0;
/* "CR" - Completion is Required marks CQE generation request per WQE */
/* by SCQE mode, this value is ignored */
v_sqe->ctrl_sl.ch.wd0.cr = 1;
/*
* "DIFSL" field of CtrlS - defines the size of DIFS, which varies from
* 0 to 56 bytes.
*/
v_sqe->ctrl_sl.ch.wd0.dif_sl = 0;
/*
* "CSL" field of CtrlS - defines the size of CS, which varies from 0 to
* 24 bytes
*/
v_sqe->ctrl_sl.ch.wd0.csl = 0;
/* "CtrlSL" - C describes the size of CtrlS in 8 bytes chunks.
* The value Zero is not valid.
*/
v_sqe->ctrl_sl.ch.wd0.ctrl_sl = HIFC_T_RD_WR_WQE_CTR_CTRLSL_SIZE;
/* "O" - Owner - marks ownership of WQE */
v_sqe->ctrl_sl.ch.wd0.owner = 0;
}
void hifc_build_service_wqe_ts_common(struct hifcoe_sqe_ts_s *v_sqe_ts,
unsigned int rport_index,
unsigned short local_xid,
unsigned short remote_xid,
unsigned short data_len)
{
v_sqe_ts->local_xid = local_xid;
v_sqe_ts->wd0.conn_id = (unsigned short)rport_index;
v_sqe_ts->wd0.remote_xid = remote_xid;
v_sqe_ts->cont.els_gs_elsrsp_comm.data_len = data_len;
}
void hifc_build_els_gs_wqe_sge(struct hifcoe_sqe_s *v_sqe, void *v_buf_addr,
unsigned long long v_phy_addr,
unsigned int buf_len,
unsigned int xid, void *v_hba)
{
unsigned long long els_rsp_phy_addr;
struct hifcoe_variable_sge_s *psge = NULL;
/* Fill in SGE and convert it to big-endian. */
psge = &v_sqe->sge[0];
els_rsp_phy_addr = v_phy_addr;
psge->buf_addr_hi = HIFC_HIGH_32_BITS(els_rsp_phy_addr);
psge->buf_addr_lo = HIFC_LOW_32_BITS(els_rsp_phy_addr);
psge->wd0.buf_len = buf_len;
psge->wd0.r_flag = 0;
psge->wd1.extension_flag = HIFC_WQE_SGE_NOT_EXTEND_FLAG;
psge->wd1.buf_addr_gpa = (psge->buf_addr_lo >> 16);
psge->wd1.xid = (xid & 0x3fff);
psge->wd1.last_flag = HIFC_WQE_SGE_LAST_FLAG;
hifc_cpu_to_big32(psge, sizeof(*psge));
/* Converts the payload of an FC frame into a big end. */
hifc_cpu_to_big32(v_buf_addr, buf_len);
}
void hifc_build_els_wqe_ts_rsp(struct hifcoe_sqe_s *v_sqe, void *v_sq_info,
void *v_frame_pld, unsigned short type,
unsigned short cmnd, unsigned int v_scqn)
{
struct unf_pril_payload_s *pri_acc_pld = NULL;
struct hifcoe_sqe_els_rsp_s *els_rsp = NULL;
struct hifcoe_sqe_ts_s *sqe_ts = NULL;
struct hifc_parent_sq_info_s *sq_info = NULL;
struct hifc_hba_s *hba = NULL;
UNF_CHECK_VALID(0x5015, UNF_TRUE, v_sqe, return);
UNF_CHECK_VALID(0x5015, UNF_TRUE, v_frame_pld, return);
UNF_CHECK_VALID(0x5015, UNF_TRUE, v_sq_info, return);
sqe_ts = &v_sqe->ts_sl;
els_rsp = &sqe_ts->cont.els_rsp;
sqe_ts->task_type = HIFC_SQE_ELS_RSP;
/* The default chip does not need to update parameters. */
els_rsp->wd1.para_update = 0x0;
sq_info = (struct hifc_parent_sq_info_s *)v_sq_info;
hba = (struct hifc_hba_s *)sq_info->phba;
/* When the PLOGI request is sent, the microcode needs to be instructed
* to clear the I/O related to the link to avoid data inconsistency
* caused by the disorder of the IO.
*/
if (((cmnd == ELS_LOGO) || (cmnd == ELS_PLOGI)) && hba) {
els_rsp->wd1.clr_io = 1;
els_rsp->wd6.reset_exch_start = hba->exit_base;
els_rsp->wd6.reset_exch_end = hba->exit_base +
(hba->exit_count - 1);
els_rsp->wd7.scqn = v_scqn;
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"Port(0x%x) send cmd(0x%x) to RPort(0x%x),rport index(0x%x), notify clean io start 0x%x, end 0x%x, scqn 0x%x.",
sq_info->local_port_id,
cmnd,
sq_info->remote_port_id,
sq_info->rport_index,
els_rsp->wd6.reset_exch_start,
els_rsp->wd6.reset_exch_end,
v_scqn);
return;
}
if (type == ELS_RJT)
return;
/*
* Enter WQE in the PrliAcc negotiation parameter, and fill in the
* Update flag in WQE.
*/
if (cmnd == ELS_PRLI) {
/* The chip updates the PLOGI ACC negotiation parameters. */
els_rsp->wd2.seq_cnt = sq_info->plogi_coparams.seq_cnt;
els_rsp->wd2.e_d_tov = sq_info->plogi_coparams.ed_tov;
els_rsp->wd2.tx_mfs = sq_info->plogi_coparams.tx_mfs;
els_rsp->e_d_tov_timer_val =
sq_info->plogi_coparams.ed_tov_timer_val;
/* The chip updates the PRLI ACC parameter. */
pri_acc_pld = (struct unf_pril_payload_s *)v_frame_pld;
els_rsp->wd4.xfer_dis = HIFC_GET_PRLI_PARAM_WXFER(
pri_acc_pld->parms);
els_rsp->wd4.conf = HIFC_GET_PRLI_PARAM_CONF(
pri_acc_pld->parms);
els_rsp->wd4.rec = HIFC_GET_PRLI_PARAM_REC(pri_acc_pld->parms);
els_rsp->wd1.para_update = 0x03;
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"Port(0x%x) save rport index(0x%x) login parms,seqcnt:0x%x,e_d_tov:0x%x,txmfs:0x%x,e_d_tovtimerval:0x%x,xfer_dis:0x%x, conf:0x%x,rec:0x%x.",
sq_info->local_port_id,
sq_info->rport_index, els_rsp->wd2.seq_cnt,
els_rsp->wd2.e_d_tov, els_rsp->wd2.tx_mfs,
els_rsp->e_d_tov_timer_val, els_rsp->wd4.xfer_dis,
els_rsp->wd4.conf, els_rsp->wd4.rec);
}
}
void hifc_build_els_wqe_ts_req(struct hifcoe_sqe_s *v_sqe, void *v_sq_info,
unsigned short cmnd, unsigned int v_scqn,
void *v_frame_pld)
{
struct hifcoe_sqe_ts_s *v_sqe_ts = NULL;
struct hifcoe_sqe_t_els_gs_s *els_req = NULL;
struct hifc_parent_sq_info_s *sq_info = NULL;
struct hifc_hba_s *hba = NULL;
struct unf_rec_pld_s *rec_pld = NULL;
v_sqe_ts = &v_sqe->ts_sl;
v_sqe_ts->task_type = HIFC_SQE_ELS_CMND;
els_req = &v_sqe_ts->cont.t_els_gs;
sq_info = (struct hifc_parent_sq_info_s *)v_sq_info;
hba = (struct hifc_hba_s *)sq_info->phba;
/*
* When the PLOGI request is sent, the microcode needs to be instructed
* to clear the I/O related to the link to avoid data inconsistency
* caused by the disorder of the IO.
*/
if (((cmnd == ELS_LOGO) || (cmnd == ELS_PLOGI)) && hba) {
els_req->wd4.clr_io = 1;
els_req->wd6.reset_exch_start = hba->exit_base;
els_req->wd6.reset_exch_end = hba->exit_base +
(hba->exit_count - 1);
els_req->wd7.scqn = v_scqn;
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"Port(0x%x) Rport(0x%x) SID(0x%x) send %s to DID(0x%x), notify clean io start 0x%x, end 0x%x, scqn 0x%x.",
hba->port_cfg.port_id, sq_info->rport_index,
sq_info->local_port_id,
(cmnd == ELS_PLOGI) ? "PLOGI" : "LOGO",
sq_info->remote_port_id,
els_req->wd6.reset_exch_start,
els_req->wd6.reset_exch_end,
v_scqn);
return;
}
/* The chip updates the PLOGI ACC negotiation parameters. */
if (cmnd == ELS_PRLI) {
els_req->wd5.seq_cnt = sq_info->plogi_coparams.seq_cnt;
els_req->wd5.e_d_tov = sq_info->plogi_coparams.ed_tov;
els_req->wd5.tx_mfs = sq_info->plogi_coparams.tx_mfs;
els_req->e_d_tov_timer_val =
sq_info->plogi_coparams.ed_tov_timer_val;
els_req->wd4.rec_support = hba->port_cfg.tape_support ? 1 : 0;
els_req->wd4.para_update = 0x01;
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_INFO,
"Port(0x%x) save rport index(0x%x) login parms,seqcnt:0x%x, e_d_tov:0x%x,txmfs:0x%x,e_d_tovtimerval:0x%x.",
sq_info->local_port_id, sq_info->rport_index,
els_req->wd5.seq_cnt, els_req->wd5.e_d_tov,
els_req->wd5.tx_mfs,
els_req->e_d_tov_timer_val);
}
if (cmnd == ELS_ECHO)
els_req->echo_flag = UNF_TRUE;
if (cmnd == ELS_REC) {
rec_pld = (struct unf_rec_pld_s *)v_frame_pld;
els_req->wd4.rec_flag = 1;
rec_pld->ox_id += hba->exit_base;
els_req->wd4.orign_oxid = rec_pld->ox_id;
HIFC_TRACE(UNF_EVTLOG_DRIVER_INFO, UNF_LOG_LOGIN_ATT, UNF_MAJOR,
"Port(0x%x) Rport(0x%x) SID(0x%x) send Rec to DID(0x%x), origin_oxid 0x%x",
hba->port_cfg.port_id, sq_info->rport_index,
sq_info->local_port_id,
sq_info->remote_port_id,
els_req->wd4.orign_oxid);
}
}
void hifc_build_els_wqe_ts_magic_num(struct hifcoe_sqe_s *v_sqe,
unsigned short els_cmnd_type,
unsigned int v_magic_num)
{
struct hifcoe_sqe_t_els_gs_s *els_req;
struct hifcoe_sqe_els_rsp_s *els_rsp;
if (els_cmnd_type == ELS_ACC || els_cmnd_type == ELS_RJT) {
els_rsp = &v_sqe->ts_sl.cont.els_rsp;
els_rsp->magic_num = v_magic_num;
} else {
els_req = &v_sqe->ts_sl.cont.t_els_gs;
els_req->magic_num = v_magic_num;
}
}
void hifc_build_gs_wqe_ts_req(struct hifcoe_sqe_s *v_sqe,
unsigned int magic_num)
{
struct hifcoe_sqe_ts_s *v_sqe_ts = NULL;
struct hifcoe_sqe_t_els_gs_s *gs_req = NULL;
v_sqe_ts = &v_sqe->ts_sl;
v_sqe_ts->task_type = HIFC_SQE_GS_CMND;
gs_req = &v_sqe_ts->cont.t_els_gs;
gs_req->magic_num = magic_num;
}
void hifc_build_bls_wqe_ts_req(struct hifcoe_sqe_s *v_sqe,
unsigned int abts_param,
unsigned int magic_num)
{
struct hifcoe_sqe_abts_s *abts_ts;
v_sqe->ts_sl.task_type = HIFC_SQE_BLS_CMND;
abts_ts = &v_sqe->ts_sl.cont.abts;
abts_ts->fh_parm_abts = abts_param;
abts_ts->magic_num = magic_num;
}
void hifc_build_service_wqe_root_ts(void *v_hba,
struct hifc_root_sqe_s *v_rt_sqe,
unsigned int rx_id, unsigned int rport_id,
unsigned int scq_num)
{
unsigned char data_cos = 0;
unsigned int port_id = 0;
unsigned int service_type = 0;
struct hifc_hba_s *hba = NULL;
struct hifc_parent_queue_info_s *parent_queue_info = NULL;
hba = (struct hifc_hba_s *)v_hba;
port_id = HIFC_GET_HBA_PORT_ID(hba);
service_type = HIFC_GET_SERVICE_TYPE(hba);
if (rport_id >= UNF_HIFC_MAXRPORT_NUM) {
data_cos = HIFC_GET_PACKET_COS(service_type);
} else {
parent_queue_info =
&hba->parent_queue_mgr->parent_queues[rport_id];
data_cos = parent_queue_info->queue_data_cos;
}
v_rt_sqe->task_section.fc_dw0.exch_id = rx_id;
v_rt_sqe->task_section.fc_dw0.host_id = 0;
v_rt_sqe->task_section.fc_dw0.port_id = port_id;
v_rt_sqe->task_section.fc_dw0.off_load = HIFC_NO_OFFLOAD;
v_rt_sqe->task_section.fc_dw3.rport_index = HIFC_LSW(rport_id);
v_rt_sqe->task_section.fc_dw3.scq_num = HIFC_LSW(scq_num);
v_rt_sqe->task_section.fc_dw4.service_type = UNF_GET_SHIFTMASK(
service_type, 0, 0x1f);
v_rt_sqe->task_section.fc_dw4.pkt_type = HIFC_GET_PACKET_TYPE(
service_type);
v_rt_sqe->task_section.fc_dw4.pkt_cos = data_cos;
}
void hifc_build_service_wqe_root_sge(struct hifc_root_sqe_s *v_rt_sqe,
void *v_buf_addr,
unsigned long long v_phy_addr,
unsigned int buf_len,
void *v_hba)
{
unsigned long long frame_phy_addr;
/* Enter the SGE and convert it to the big-endian mode. */
frame_phy_addr = v_phy_addr;
v_rt_sqe->sge.buf_addr_hi = HIFC_HIGH_32_BITS(frame_phy_addr);
v_rt_sqe->sge.buf_addr_lo = HIFC_LOW_32_BITS(frame_phy_addr);
v_rt_sqe->sge.wd0.buf_len = buf_len;
v_rt_sqe->sge.wd0.ext_flag = 0;
v_rt_sqe->sge.wd1.rsvd = 0;
hifc_cpu_to_big32(&v_rt_sqe->sge, sizeof(v_rt_sqe->sge));
/* Converting FC Frames into big Ends */
hifc_cpu_to_big32(v_buf_addr, buf_len);
}
void hifc_build_service_wqe_ctx_sge(struct hifc_root_sqe_s *v_rt_sqe,
unsigned long long v_ctxt_addr,
unsigned int buf_len)
{
/* The SGE is filled in and converted to the big-endian mode. */
v_rt_sqe->ctx_sge.buf_addr_hi = HIFC_HIGH_32_BITS(v_ctxt_addr);
v_rt_sqe->ctx_sge.buf_addr_lo = HIFC_LOW_32_BITS(v_ctxt_addr);
v_rt_sqe->ctx_sge.wd0.buf_len = buf_len;
v_rt_sqe->ctx_sge.wd0.ext_flag = 0;
v_rt_sqe->ctx_sge.wd1.rsvd = 0;
hifc_cpu_to_big32(&v_rt_sqe->ctx_sge, sizeof(v_rt_sqe->ctx_sge));
}
void hifc_build_els_wqe_root_offload(struct hifc_root_sqe_s *v_rt_sqe,
dma_addr_t ctxt_addr,
unsigned int xid)
{
/* update Task Section DW0.OFFLOAD */
v_rt_sqe->task_section.fc_dw0.off_load = HIFC_HAVE_OFFLOAD;
/* update Context GPA DW1~2 */
v_rt_sqe->task_section.fc_dw1.context_gpa_hi =
HIFC_HIGH_32_BITS(ctxt_addr);
v_rt_sqe->task_section.fc_dw2.context_gpa_lo =
HIFC_LOW_32_BITS(ctxt_addr);
/* fill Context DW4 */
v_rt_sqe->task_section.fc_dw4.parent_xid = xid;
v_rt_sqe->task_section.fc_dw4.csize = HIFC_CNTX_SIZE_T_256B;
/* The sqe of the offload request has two sge. The first is the packet,
* and the second is the ctx.
*/
v_rt_sqe->ctrl_section.ch.wd0.bdsl =
2 * HIFC_BYTES_TO_QW_NUM(sizeof(struct hifc_root_sge_s));
}
void hifc_build_service_wqe_ctrl_section(struct hifcoe_wqe_ctrl_s *v_wqe_cs,
unsigned int ts_size,
unsigned int bdsi)
{
v_wqe_cs->ch.wd0.bdsl = bdsi;
v_wqe_cs->ch.wd0.drv_sl = 0;
v_wqe_cs->ch.wd0.rsvd0 = 0;
v_wqe_cs->ch.wd0.wf = 0;
v_wqe_cs->ch.wd0.cf = 0;
v_wqe_cs->ch.wd0.tsl = ts_size;
v_wqe_cs->ch.wd0.va = 0;
v_wqe_cs->ch.wd0.df = 0;
v_wqe_cs->ch.wd0.cr = 1;
v_wqe_cs->ch.wd0.dif_sl = 0;
v_wqe_cs->ch.wd0.csl = 0;
/* divided by 8 */
v_wqe_cs->ch.wd0.ctrl_sl = HIFC_BYTES_TO_QW_NUM(sizeof(*v_wqe_cs));
v_wqe_cs->ch.wd0.owner = 0;
}
void hifc_build_wqe_owner_pmsn(struct hifcoe_wqe_ctrl_s *v_wqe_cs,
unsigned short owner,
unsigned short pmsn)
{
v_wqe_cs->qsf.wqe_sn = pmsn;
v_wqe_cs->qsf.dump_wqe_sn = v_wqe_cs->qsf.wqe_sn;
v_wqe_cs->ch.wd0.owner = (unsigned int)owner;
}
void hifc_convert_parent_wqe_to_big_endian(struct hifcoe_sqe_s *v_sqe)
{
if (likely((v_sqe->ts_sl.task_type != HIFCOE_TASK_T_TRESP) &&
(v_sqe->ts_sl.task_type != HIFCOE_TASK_T_TMF_RESP))) {
/*
* Convert Control Secton and Task Section to big-endian. Before
* the SGE enters the queue, the upper-layer driver converts the
* SGE and Task Section to the big-endian mode.
*/
hifc_cpu_to_big32(&v_sqe->ctrl_sl, sizeof(v_sqe->ctrl_sl));
hifc_cpu_to_big32(&v_sqe->ts_sl, sizeof(v_sqe->ts_sl));
} else {
/*
* The HIFCOE_TASK_T_TRESP may use the SGE as the Task Section
* to convert the entire SQE into a large end.
*/
hifc_cpu_to_big32(v_sqe, sizeof(struct hifcoe_sqe_tresp_s));
}
}
void hifc_convert_root_wqe_to_big_endian(struct hifc_root_sqe_s *v_sqe)
{
hifc_cpu_to_big32(&v_sqe->ctrl_section, sizeof(v_sqe->ctrl_section));
hifc_cpu_to_big32(&v_sqe->task_section, sizeof(v_sqe->task_section));
}
void hifc_build_cmdqe_common(union hifc_cmdqe_u *cmdqe,
enum hifcoe_task_type_e task_type,
unsigned short rx_id)
{
cmdqe->common.wd0.task_type = task_type;
cmdqe->common.wd0.rx_id = rx_id;
cmdqe->common.wd0.rsvd0 = 0;
}
#define HIFC_STANDARD_SIRT_ENABLE 1
#define HIFC_STANDARD_SIRT_DISABLE 0
#define HIFC_UNKNOWN_ID 0xFFFF
void hifc_build_icmnd_wqe_ts_header(struct unf_frame_pkg_s *v_pkg,
struct hifcoe_sqe_s *v_sqe,
unsigned char task_type,
unsigned short exit_base,
unsigned char v_port_idx)
{
v_sqe->ts_sl.local_xid = UNF_GET_OXID(v_pkg) + exit_base;
v_sqe->ts_sl.task_type = task_type;
v_sqe->ts_sl.wd0.conn_id =
(unsigned short)(v_pkg->private[PKG_PRIVATE_XCHG_RPORT_INDEX]);
v_sqe->ts_sl.wd0.remote_xid = HIFC_UNKNOWN_ID;
}
void hifc_build_icmnd_wqe_ts(void *v_hba, struct unf_frame_pkg_s *v_pkg,
struct hifcoe_sqe_ts_s *v_sqe_ts)
{
struct hifcoe_sqe_icmnd_s *icmd = &v_sqe_ts->cont.icmnd;
void *phy_add = NULL;
struct hifc_hba_s *hba = NULL;
hba = (struct hifc_hba_s *)v_hba;
v_sqe_ts->cdb_type = 0;
memcpy(icmd->fcp_cmnd_iu, v_pkg->fcp_cmnd,
sizeof(struct unf_fcp_cmnd_s));
icmd->magic_num = UNF_GETXCHGALLOCTIME(v_pkg);
if (v_pkg->unf_rsp_pload_bl.buffer_ptr) {
phy_add = (void *)v_pkg->unf_rsp_pload_bl.buf_dma_addr;
icmd->rsp_gpa_hi = HIFC_HIGH_32_BITS(phy_add);
icmd->rsp_gpa_lo = HIFC_LOW_32_BITS(phy_add);
} else {
HIFC_TRACE(UNF_EVTLOG_IO_ERR, UNF_LOG_IO_ATT, UNF_ERR,
"[err]INI Build WQE sense buffer should not be null,sid_did (0x%x_0x%x) oxid(0x%x) pkg type(0x%x) hot pool tag(0x%x).",
v_pkg->frame_head.csctl_sid,
v_pkg->frame_head.rctl_did,
UNF_GET_OXID(v_pkg),
v_pkg->type, UNF_GET_XCHG_TAG(v_pkg));
}
if (v_sqe_ts->task_type != HIFC_SQE_FCP_ITMF) {
icmd->info.tmf.w0.bs.reset_exch_start = hba->exit_base;
icmd->info.tmf.w0.bs.reset_exch_end = hba->exit_base +
hba->exit_count - 1;
icmd->info.tmf.w1.bs.reset_did = UNF_GET_DID(v_pkg);
/* delivers the marker status flag to the microcode. */
icmd->info.tmf.w1.bs.marker_sts = 1;
HIFC_GET_RESET_TYPE(UNF_GET_TASK_MGMT_FLAGS(
v_pkg->fcp_cmnd->control),
icmd->info.tmf.w1.bs.reset_type);
icmd->info.tmf.w2.bs.reset_sid = UNF_GET_SID(v_pkg);
memcpy(icmd->info.tmf.reset_lun, v_pkg->fcp_cmnd->lun,
sizeof(icmd->info.tmf.reset_lun));
}
}
void hifc_build_srq_wqe_ctrls(struct hifcoe_rqe_s *v_rqe,
unsigned short owner,
unsigned short pmsn)
{
struct hifcoe_wqe_ctrl_ch_s *wqe_ctrls = NULL;
wqe_ctrls = &v_rqe->ctrl_sl.ch;
wqe_ctrls->wd0.owner = owner;
wqe_ctrls->wd0.ctrl_sl = sizeof(struct hifcoe_wqe_ctrl_s) >> 3;
wqe_ctrls->wd0.csl = 1;
wqe_ctrls->wd0.dif_sl = 0;
wqe_ctrls->wd0.cr = 1;
wqe_ctrls->wd0.df = 0;
wqe_ctrls->wd0.va = 0;
wqe_ctrls->wd0.tsl = 0;
wqe_ctrls->wd0.cf = 0;
wqe_ctrls->wd0.wf = 0;
wqe_ctrls->wd0.drv_sl = sizeof(struct hifcoe_rqe_drv_s) >> 3;
wqe_ctrls->wd0.bdsl = sizeof(struct hifcoe_constant_sge_s) >> 3;
v_rqe->ctrl_sl.wd0.wqe_msn = pmsn;
v_rqe->ctrl_sl.wd0.dump_wqe_msn = v_rqe->ctrl_sl.wd0.wqe_msn;
}