18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* QLogic FCoE Offload Driver 38c2ecf20Sopenharmony_ci * Copyright (c) 2016-2018 Cavium Inc. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include "drv_fcoe_fw_funcs.h" 68c2ecf20Sopenharmony_ci#include "drv_scsi_fw_funcs.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define FCOE_RX_ID (0xFFFFu) 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_cistatic inline void init_common_sqe(struct fcoe_task_params *task_params, 118c2ecf20Sopenharmony_ci enum fcoe_sqe_request_type request_type) 128c2ecf20Sopenharmony_ci{ 138c2ecf20Sopenharmony_ci memset(task_params->sqe, 0, sizeof(*(task_params->sqe))); 148c2ecf20Sopenharmony_ci SET_FIELD(task_params->sqe->flags, FCOE_WQE_REQ_TYPE, 158c2ecf20Sopenharmony_ci request_type); 168c2ecf20Sopenharmony_ci task_params->sqe->task_id = task_params->itid; 178c2ecf20Sopenharmony_ci} 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciint init_initiator_rw_fcoe_task(struct fcoe_task_params *task_params, 208c2ecf20Sopenharmony_ci struct scsi_sgl_task_params *sgl_task_params, 218c2ecf20Sopenharmony_ci struct regpair sense_data_buffer_phys_addr, 228c2ecf20Sopenharmony_ci u32 task_retry_id, 238c2ecf20Sopenharmony_ci u8 fcp_cmd_payload[32]) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci struct e4_fcoe_task_context *ctx = task_params->context; 268c2ecf20Sopenharmony_ci const u8 val_byte = ctx->ystorm_ag_context.byte0; 278c2ecf20Sopenharmony_ci struct e4_ustorm_fcoe_task_ag_ctx *u_ag_ctx; 288c2ecf20Sopenharmony_ci struct ystorm_fcoe_task_st_ctx *y_st_ctx; 298c2ecf20Sopenharmony_ci struct tstorm_fcoe_task_st_ctx *t_st_ctx; 308c2ecf20Sopenharmony_ci struct mstorm_fcoe_task_st_ctx *m_st_ctx; 318c2ecf20Sopenharmony_ci u32 io_size, val; 328c2ecf20Sopenharmony_ci bool slow_sgl; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci memset(ctx, 0, sizeof(*(ctx))); 358c2ecf20Sopenharmony_ci ctx->ystorm_ag_context.byte0 = val_byte; 368c2ecf20Sopenharmony_ci slow_sgl = scsi_is_slow_sgl(sgl_task_params->num_sges, 378c2ecf20Sopenharmony_ci sgl_task_params->small_mid_sge); 388c2ecf20Sopenharmony_ci io_size = (task_params->task_type == FCOE_TASK_TYPE_WRITE_INITIATOR ? 398c2ecf20Sopenharmony_ci task_params->tx_io_size : task_params->rx_io_size); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* Ystorm ctx */ 428c2ecf20Sopenharmony_ci y_st_ctx = &ctx->ystorm_st_context; 438c2ecf20Sopenharmony_ci y_st_ctx->data_2_trns_rem = cpu_to_le32(io_size); 448c2ecf20Sopenharmony_ci y_st_ctx->task_rety_identifier = cpu_to_le32(task_retry_id); 458c2ecf20Sopenharmony_ci y_st_ctx->task_type = (u8)task_params->task_type; 468c2ecf20Sopenharmony_ci memcpy(&y_st_ctx->tx_info_union.fcp_cmd_payload, 478c2ecf20Sopenharmony_ci fcp_cmd_payload, sizeof(struct fcoe_fcp_cmd_payload)); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* Tstorm ctx */ 508c2ecf20Sopenharmony_ci t_st_ctx = &ctx->tstorm_st_context; 518c2ecf20Sopenharmony_ci t_st_ctx->read_only.dev_type = (u8)(task_params->is_tape_device == 1 ? 528c2ecf20Sopenharmony_ci FCOE_TASK_DEV_TYPE_TAPE : 538c2ecf20Sopenharmony_ci FCOE_TASK_DEV_TYPE_DISK); 548c2ecf20Sopenharmony_ci t_st_ctx->read_only.cid = cpu_to_le32(task_params->conn_cid); 558c2ecf20Sopenharmony_ci val = cpu_to_le32(task_params->cq_rss_number); 568c2ecf20Sopenharmony_ci t_st_ctx->read_only.glbl_q_num = val; 578c2ecf20Sopenharmony_ci t_st_ctx->read_only.fcp_cmd_trns_size = cpu_to_le32(io_size); 588c2ecf20Sopenharmony_ci t_st_ctx->read_only.task_type = (u8)task_params->task_type; 598c2ecf20Sopenharmony_ci SET_FIELD(t_st_ctx->read_write.flags, 608c2ecf20Sopenharmony_ci FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_EXP_FIRST_FRAME, 1); 618c2ecf20Sopenharmony_ci t_st_ctx->read_write.rx_id = cpu_to_le16(FCOE_RX_ID); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* Ustorm ctx */ 648c2ecf20Sopenharmony_ci u_ag_ctx = &ctx->ustorm_ag_context; 658c2ecf20Sopenharmony_ci u_ag_ctx->global_cq_num = cpu_to_le32(task_params->cq_rss_number); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* Mstorm buffer for sense/rsp data placement */ 688c2ecf20Sopenharmony_ci m_st_ctx = &ctx->mstorm_st_context; 698c2ecf20Sopenharmony_ci val = cpu_to_le32(sense_data_buffer_phys_addr.hi); 708c2ecf20Sopenharmony_ci m_st_ctx->rsp_buf_addr.hi = val; 718c2ecf20Sopenharmony_ci val = cpu_to_le32(sense_data_buffer_phys_addr.lo); 728c2ecf20Sopenharmony_ci m_st_ctx->rsp_buf_addr.lo = val; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (task_params->task_type == FCOE_TASK_TYPE_WRITE_INITIATOR) { 758c2ecf20Sopenharmony_ci /* Ystorm ctx */ 768c2ecf20Sopenharmony_ci y_st_ctx->expect_first_xfer = 1; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* Set the amount of super SGEs. Can be up to 4. */ 798c2ecf20Sopenharmony_ci SET_FIELD(y_st_ctx->sgl_mode, 808c2ecf20Sopenharmony_ci YSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE, 818c2ecf20Sopenharmony_ci (slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL)); 828c2ecf20Sopenharmony_ci init_scsi_sgl_context(&y_st_ctx->sgl_params, 838c2ecf20Sopenharmony_ci &y_st_ctx->data_desc, 848c2ecf20Sopenharmony_ci sgl_task_params); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci /* Mstorm ctx */ 878c2ecf20Sopenharmony_ci SET_FIELD(m_st_ctx->flags, 888c2ecf20Sopenharmony_ci MSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE, 898c2ecf20Sopenharmony_ci (slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL)); 908c2ecf20Sopenharmony_ci m_st_ctx->sgl_params.sgl_num_sges = 918c2ecf20Sopenharmony_ci cpu_to_le16(sgl_task_params->num_sges); 928c2ecf20Sopenharmony_ci } else { 938c2ecf20Sopenharmony_ci /* Tstorm ctx */ 948c2ecf20Sopenharmony_ci SET_FIELD(t_st_ctx->read_write.flags, 958c2ecf20Sopenharmony_ci FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_RX_SGL_MODE, 968c2ecf20Sopenharmony_ci (slow_sgl ? SCSI_TX_SLOW_SGL : SCSI_FAST_SGL)); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Mstorm ctx */ 998c2ecf20Sopenharmony_ci m_st_ctx->data_2_trns_rem = cpu_to_le32(io_size); 1008c2ecf20Sopenharmony_ci init_scsi_sgl_context(&m_st_ctx->sgl_params, 1018c2ecf20Sopenharmony_ci &m_st_ctx->data_desc, 1028c2ecf20Sopenharmony_ci sgl_task_params); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* Init Sqe */ 1068c2ecf20Sopenharmony_ci init_common_sqe(task_params, SEND_FCOE_CMD); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ciint init_initiator_midpath_unsolicited_fcoe_task( 1128c2ecf20Sopenharmony_ci struct fcoe_task_params *task_params, 1138c2ecf20Sopenharmony_ci struct fcoe_tx_mid_path_params *mid_path_fc_header, 1148c2ecf20Sopenharmony_ci struct scsi_sgl_task_params *tx_sgl_task_params, 1158c2ecf20Sopenharmony_ci struct scsi_sgl_task_params *rx_sgl_task_params, 1168c2ecf20Sopenharmony_ci u8 fw_to_place_fc_header) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct e4_fcoe_task_context *ctx = task_params->context; 1198c2ecf20Sopenharmony_ci const u8 val_byte = ctx->ystorm_ag_context.byte0; 1208c2ecf20Sopenharmony_ci struct e4_ustorm_fcoe_task_ag_ctx *u_ag_ctx; 1218c2ecf20Sopenharmony_ci struct ystorm_fcoe_task_st_ctx *y_st_ctx; 1228c2ecf20Sopenharmony_ci struct tstorm_fcoe_task_st_ctx *t_st_ctx; 1238c2ecf20Sopenharmony_ci struct mstorm_fcoe_task_st_ctx *m_st_ctx; 1248c2ecf20Sopenharmony_ci u32 val; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci memset(ctx, 0, sizeof(*(ctx))); 1278c2ecf20Sopenharmony_ci ctx->ystorm_ag_context.byte0 = val_byte; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Init Ystorm */ 1308c2ecf20Sopenharmony_ci y_st_ctx = &ctx->ystorm_st_context; 1318c2ecf20Sopenharmony_ci init_scsi_sgl_context(&y_st_ctx->sgl_params, 1328c2ecf20Sopenharmony_ci &y_st_ctx->data_desc, 1338c2ecf20Sopenharmony_ci tx_sgl_task_params); 1348c2ecf20Sopenharmony_ci SET_FIELD(y_st_ctx->sgl_mode, 1358c2ecf20Sopenharmony_ci YSTORM_FCOE_TASK_ST_CTX_TX_SGL_MODE, SCSI_FAST_SGL); 1368c2ecf20Sopenharmony_ci y_st_ctx->data_2_trns_rem = cpu_to_le32(task_params->tx_io_size); 1378c2ecf20Sopenharmony_ci y_st_ctx->task_type = (u8)task_params->task_type; 1388c2ecf20Sopenharmony_ci memcpy(&y_st_ctx->tx_info_union.tx_params.mid_path, 1398c2ecf20Sopenharmony_ci mid_path_fc_header, sizeof(struct fcoe_tx_mid_path_params)); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* Init Mstorm */ 1428c2ecf20Sopenharmony_ci m_st_ctx = &ctx->mstorm_st_context; 1438c2ecf20Sopenharmony_ci init_scsi_sgl_context(&m_st_ctx->sgl_params, 1448c2ecf20Sopenharmony_ci &m_st_ctx->data_desc, 1458c2ecf20Sopenharmony_ci rx_sgl_task_params); 1468c2ecf20Sopenharmony_ci SET_FIELD(m_st_ctx->flags, 1478c2ecf20Sopenharmony_ci MSTORM_FCOE_TASK_ST_CTX_MP_INCLUDE_FC_HEADER, 1488c2ecf20Sopenharmony_ci fw_to_place_fc_header); 1498c2ecf20Sopenharmony_ci m_st_ctx->data_2_trns_rem = cpu_to_le32(task_params->rx_io_size); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Init Tstorm */ 1528c2ecf20Sopenharmony_ci t_st_ctx = &ctx->tstorm_st_context; 1538c2ecf20Sopenharmony_ci t_st_ctx->read_only.cid = cpu_to_le32(task_params->conn_cid); 1548c2ecf20Sopenharmony_ci val = cpu_to_le32(task_params->cq_rss_number); 1558c2ecf20Sopenharmony_ci t_st_ctx->read_only.glbl_q_num = val; 1568c2ecf20Sopenharmony_ci t_st_ctx->read_only.task_type = (u8)task_params->task_type; 1578c2ecf20Sopenharmony_ci SET_FIELD(t_st_ctx->read_write.flags, 1588c2ecf20Sopenharmony_ci FCOE_TSTORM_FCOE_TASK_ST_CTX_READ_WRITE_EXP_FIRST_FRAME, 1); 1598c2ecf20Sopenharmony_ci t_st_ctx->read_write.rx_id = cpu_to_le16(FCOE_RX_ID); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci /* Init Ustorm */ 1628c2ecf20Sopenharmony_ci u_ag_ctx = &ctx->ustorm_ag_context; 1638c2ecf20Sopenharmony_ci u_ag_ctx->global_cq_num = cpu_to_le32(task_params->cq_rss_number); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* Init SQE */ 1668c2ecf20Sopenharmony_ci init_common_sqe(task_params, SEND_FCOE_MIDPATH); 1678c2ecf20Sopenharmony_ci task_params->sqe->additional_info_union.burst_length = 1688c2ecf20Sopenharmony_ci tx_sgl_task_params->total_buffer_size; 1698c2ecf20Sopenharmony_ci SET_FIELD(task_params->sqe->flags, 1708c2ecf20Sopenharmony_ci FCOE_WQE_NUM_SGES, tx_sgl_task_params->num_sges); 1718c2ecf20Sopenharmony_ci SET_FIELD(task_params->sqe->flags, FCOE_WQE_SGL_MODE, 1728c2ecf20Sopenharmony_ci SCSI_FAST_SGL); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci return 0; 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciint init_initiator_abort_fcoe_task(struct fcoe_task_params *task_params) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci init_common_sqe(task_params, SEND_FCOE_ABTS_REQUEST); 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ciint init_initiator_cleanup_fcoe_task(struct fcoe_task_params *task_params) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci init_common_sqe(task_params, FCOE_EXCHANGE_CLEANUP); 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciint init_initiator_sequence_recovery_fcoe_task( 1908c2ecf20Sopenharmony_ci struct fcoe_task_params *task_params, u32 desired_offset) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci init_common_sqe(task_params, FCOE_SEQUENCE_RECOVERY); 1938c2ecf20Sopenharmony_ci task_params->sqe->additional_info_union.seq_rec_updated_offset = 1948c2ecf20Sopenharmony_ci desired_offset; 1958c2ecf20Sopenharmony_ci return 0; 1968c2ecf20Sopenharmony_ci} 197