qed_nvmetcp_fw_funcs.c (13363B)
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 2/* Copyright 2021 Marvell. All rights reserved. */ 3 4#include <linux/kernel.h> 5#include <linux/module.h> 6#include <linux/pci.h> 7#include <linux/list.h> 8#include <linux/mm.h> 9#include <linux/types.h> 10#include <asm/byteorder.h> 11#include <linux/qed/common_hsi.h> 12#include <linux/qed/storage_common.h> 13#include <linux/qed/nvmetcp_common.h> 14#include <linux/qed/qed_nvmetcp_if.h> 15#include "qed_nvmetcp_fw_funcs.h" 16 17#define NVMETCP_NUM_SGES_IN_CACHE 0x4 18 19bool nvmetcp_is_slow_sgl(u16 num_sges, bool small_mid_sge) 20{ 21 return (num_sges > SCSI_NUM_SGES_SLOW_SGL_THR && small_mid_sge); 22} 23 24void init_scsi_sgl_context(struct scsi_sgl_params *ctx_sgl_params, 25 struct scsi_cached_sges *ctx_data_desc, 26 struct storage_sgl_task_params *sgl_params) 27{ 28 u8 num_sges_to_init = (u8)(sgl_params->num_sges > NVMETCP_NUM_SGES_IN_CACHE ? 29 NVMETCP_NUM_SGES_IN_CACHE : sgl_params->num_sges); 30 u8 sge_index; 31 32 /* sgl params */ 33 ctx_sgl_params->sgl_addr.lo = cpu_to_le32(sgl_params->sgl_phys_addr.lo); 34 ctx_sgl_params->sgl_addr.hi = cpu_to_le32(sgl_params->sgl_phys_addr.hi); 35 ctx_sgl_params->sgl_total_length = cpu_to_le32(sgl_params->total_buffer_size); 36 ctx_sgl_params->sgl_num_sges = cpu_to_le16(sgl_params->num_sges); 37 38 for (sge_index = 0; sge_index < num_sges_to_init; sge_index++) { 39 ctx_data_desc->sge[sge_index].sge_addr.lo = 40 cpu_to_le32(sgl_params->sgl[sge_index].sge_addr.lo); 41 ctx_data_desc->sge[sge_index].sge_addr.hi = 42 cpu_to_le32(sgl_params->sgl[sge_index].sge_addr.hi); 43 ctx_data_desc->sge[sge_index].sge_len = 44 cpu_to_le32(sgl_params->sgl[sge_index].sge_len); 45 } 46} 47 48static inline u32 calc_rw_task_size(struct nvmetcp_task_params *task_params, 49 enum nvmetcp_task_type task_type) 50{ 51 u32 io_size; 52 53 if (task_type == NVMETCP_TASK_TYPE_HOST_WRITE) 54 io_size = task_params->tx_io_size; 55 else 56 io_size = task_params->rx_io_size; 57 58 if (unlikely(!io_size)) 59 return 0; 60 61 return io_size; 62} 63 64static inline void init_sqe(struct nvmetcp_task_params *task_params, 65 struct storage_sgl_task_params *sgl_task_params, 66 enum nvmetcp_task_type task_type) 67{ 68 if (!task_params->sqe) 69 return; 70 71 memset(task_params->sqe, 0, sizeof(*task_params->sqe)); 72 task_params->sqe->task_id = cpu_to_le16(task_params->itid); 73 74 switch (task_type) { 75 case NVMETCP_TASK_TYPE_HOST_WRITE: { 76 u32 buf_size = 0; 77 u32 num_sges = 0; 78 79 SET_FIELD(task_params->sqe->contlen_cdbsize, 80 NVMETCP_WQE_CDB_SIZE_OR_NVMETCP_CMD, 1); 81 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_WQE_TYPE, 82 NVMETCP_WQE_TYPE_NORMAL); 83 if (task_params->tx_io_size) { 84 if (task_params->send_write_incapsule) 85 buf_size = calc_rw_task_size(task_params, task_type); 86 87 if (nvmetcp_is_slow_sgl(sgl_task_params->num_sges, 88 sgl_task_params->small_mid_sge)) 89 num_sges = NVMETCP_WQE_NUM_SGES_SLOWIO; 90 else 91 num_sges = min((u16)sgl_task_params->num_sges, 92 (u16)SCSI_NUM_SGES_SLOW_SGL_THR); 93 } 94 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_NUM_SGES, num_sges); 95 SET_FIELD(task_params->sqe->contlen_cdbsize, NVMETCP_WQE_CONT_LEN, buf_size); 96 } break; 97 98 case NVMETCP_TASK_TYPE_HOST_READ: { 99 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_WQE_TYPE, 100 NVMETCP_WQE_TYPE_NORMAL); 101 SET_FIELD(task_params->sqe->contlen_cdbsize, 102 NVMETCP_WQE_CDB_SIZE_OR_NVMETCP_CMD, 1); 103 } break; 104 105 case NVMETCP_TASK_TYPE_INIT_CONN_REQUEST: { 106 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_WQE_TYPE, 107 NVMETCP_WQE_TYPE_MIDDLE_PATH); 108 109 if (task_params->tx_io_size) { 110 SET_FIELD(task_params->sqe->contlen_cdbsize, NVMETCP_WQE_CONT_LEN, 111 task_params->tx_io_size); 112 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_NUM_SGES, 113 min((u16)sgl_task_params->num_sges, 114 (u16)SCSI_NUM_SGES_SLOW_SGL_THR)); 115 } 116 } break; 117 118 case NVMETCP_TASK_TYPE_CLEANUP: 119 SET_FIELD(task_params->sqe->flags, NVMETCP_WQE_WQE_TYPE, 120 NVMETCP_WQE_TYPE_TASK_CLEANUP); 121 122 default: 123 break; 124 } 125} 126 127/* The following function initializes of NVMeTCP task params */ 128static inline void 129init_nvmetcp_task_params(struct e5_nvmetcp_task_context *context, 130 struct nvmetcp_task_params *task_params, 131 enum nvmetcp_task_type task_type) 132{ 133 context->ystorm_st_context.state.cccid = task_params->host_cccid; 134 SET_FIELD(context->ustorm_st_context.error_flags, USTORM_NVMETCP_TASK_ST_CTX_NVME_TCP, 1); 135 context->ustorm_st_context.nvme_tcp_opaque_lo = cpu_to_le32(task_params->opq.lo); 136 context->ustorm_st_context.nvme_tcp_opaque_hi = cpu_to_le32(task_params->opq.hi); 137} 138 139/* The following function initializes default values to all tasks */ 140static inline void 141init_default_nvmetcp_task(struct nvmetcp_task_params *task_params, 142 void *pdu_header, void *nvme_cmd, 143 enum nvmetcp_task_type task_type) 144{ 145 struct e5_nvmetcp_task_context *context = task_params->context; 146 const u8 val_byte = context->mstorm_ag_context.cdu_validation; 147 u8 dw_index; 148 149 memset(context, 0, sizeof(*context)); 150 init_nvmetcp_task_params(context, task_params, 151 (enum nvmetcp_task_type)task_type); 152 153 /* Swapping requirements used below, will be removed in future FW versions */ 154 if (task_type == NVMETCP_TASK_TYPE_HOST_WRITE || 155 task_type == NVMETCP_TASK_TYPE_HOST_READ) { 156 for (dw_index = 0; 157 dw_index < QED_NVMETCP_CMN_HDR_SIZE / sizeof(u32); 158 dw_index++) 159 context->ystorm_st_context.pdu_hdr.task_hdr.reg[dw_index] = 160 cpu_to_le32(__swab32(((u32 *)pdu_header)[dw_index])); 161 162 for (dw_index = QED_NVMETCP_CMN_HDR_SIZE / sizeof(u32); 163 dw_index < QED_NVMETCP_CMD_HDR_SIZE / sizeof(u32); 164 dw_index++) 165 context->ystorm_st_context.pdu_hdr.task_hdr.reg[dw_index] = 166 cpu_to_le32(__swab32(((u32 *)nvme_cmd)[dw_index - 2])); 167 } else { 168 for (dw_index = 0; 169 dw_index < QED_NVMETCP_NON_IO_HDR_SIZE / sizeof(u32); 170 dw_index++) 171 context->ystorm_st_context.pdu_hdr.task_hdr.reg[dw_index] = 172 cpu_to_le32(__swab32(((u32 *)pdu_header)[dw_index])); 173 } 174 175 /* M-Storm Context: */ 176 context->mstorm_ag_context.cdu_validation = val_byte; 177 context->mstorm_st_context.task_type = (u8)(task_type); 178 context->mstorm_ag_context.task_cid = cpu_to_le16(task_params->conn_icid); 179 180 /* Ustorm Context: */ 181 SET_FIELD(context->ustorm_ag_context.flags1, E5_USTORM_NVMETCP_TASK_AG_CTX_R2T2RECV, 1); 182 context->ustorm_st_context.task_type = (u8)(task_type); 183 context->ustorm_st_context.cq_rss_number = task_params->cq_rss_number; 184 context->ustorm_ag_context.icid = cpu_to_le16(task_params->conn_icid); 185} 186 187/* The following function initializes the U-Storm Task Contexts */ 188static inline void 189init_ustorm_task_contexts(struct ustorm_nvmetcp_task_st_ctx *ustorm_st_context, 190 struct e5_ustorm_nvmetcp_task_ag_ctx *ustorm_ag_context, 191 u32 remaining_recv_len, 192 u32 expected_data_transfer_len, u8 num_sges, 193 bool tx_dif_conn_err_en) 194{ 195 /* Remaining data to be received in bytes. Used in validations*/ 196 ustorm_st_context->rem_rcv_len = cpu_to_le32(remaining_recv_len); 197 ustorm_ag_context->exp_data_acked = cpu_to_le32(expected_data_transfer_len); 198 ustorm_st_context->exp_data_transfer_len = cpu_to_le32(expected_data_transfer_len); 199 SET_FIELD(ustorm_st_context->reg1_map, REG1_NUM_SGES, num_sges); 200 SET_FIELD(ustorm_ag_context->flags2, E5_USTORM_NVMETCP_TASK_AG_CTX_DIF_ERROR_CF_EN, 201 tx_dif_conn_err_en ? 1 : 0); 202} 203 204/* The following function initializes Local Completion Contexts: */ 205static inline void 206set_local_completion_context(struct e5_nvmetcp_task_context *context) 207{ 208 SET_FIELD(context->ystorm_st_context.state.flags, 209 YSTORM_NVMETCP_TASK_STATE_LOCAL_COMP, 1); 210 SET_FIELD(context->ustorm_st_context.flags, 211 USTORM_NVMETCP_TASK_ST_CTX_LOCAL_COMP, 1); 212} 213 214/* Common Fastpath task init function: */ 215static inline void 216init_rw_nvmetcp_task(struct nvmetcp_task_params *task_params, 217 enum nvmetcp_task_type task_type, 218 void *pdu_header, void *nvme_cmd, 219 struct storage_sgl_task_params *sgl_task_params) 220{ 221 struct e5_nvmetcp_task_context *context = task_params->context; 222 u32 task_size = calc_rw_task_size(task_params, task_type); 223 bool slow_io = false; 224 u8 num_sges = 0; 225 226 init_default_nvmetcp_task(task_params, pdu_header, nvme_cmd, task_type); 227 228 /* Tx/Rx: */ 229 if (task_params->tx_io_size) { 230 /* if data to transmit: */ 231 init_scsi_sgl_context(&context->ystorm_st_context.state.sgl_params, 232 &context->ystorm_st_context.state.data_desc, 233 sgl_task_params); 234 slow_io = nvmetcp_is_slow_sgl(sgl_task_params->num_sges, 235 sgl_task_params->small_mid_sge); 236 num_sges = 237 (u8)(!slow_io ? min((u32)sgl_task_params->num_sges, 238 (u32)SCSI_NUM_SGES_SLOW_SGL_THR) : 239 NVMETCP_WQE_NUM_SGES_SLOWIO); 240 if (slow_io) { 241 SET_FIELD(context->ystorm_st_context.state.flags, 242 YSTORM_NVMETCP_TASK_STATE_SLOW_IO, 1); 243 } 244 } else if (task_params->rx_io_size) { 245 /* if data to receive: */ 246 init_scsi_sgl_context(&context->mstorm_st_context.sgl_params, 247 &context->mstorm_st_context.data_desc, 248 sgl_task_params); 249 num_sges = 250 (u8)(!nvmetcp_is_slow_sgl(sgl_task_params->num_sges, 251 sgl_task_params->small_mid_sge) ? 252 min((u32)sgl_task_params->num_sges, 253 (u32)SCSI_NUM_SGES_SLOW_SGL_THR) : 254 NVMETCP_WQE_NUM_SGES_SLOWIO); 255 context->mstorm_st_context.rem_task_size = cpu_to_le32(task_size); 256 } 257 258 /* Ustorm context: */ 259 init_ustorm_task_contexts(&context->ustorm_st_context, 260 &context->ustorm_ag_context, 261 /* Remaining Receive length is the Task Size */ 262 task_size, 263 /* The size of the transmitted task */ 264 task_size, 265 /* num_sges */ 266 num_sges, 267 false); 268 269 /* Set exp_data_acked */ 270 if (task_type == NVMETCP_TASK_TYPE_HOST_WRITE) { 271 if (task_params->send_write_incapsule) 272 context->ustorm_ag_context.exp_data_acked = task_size; 273 else 274 context->ustorm_ag_context.exp_data_acked = 0; 275 } else if (task_type == NVMETCP_TASK_TYPE_HOST_READ) { 276 context->ustorm_ag_context.exp_data_acked = 0; 277 } 278 279 context->ustorm_ag_context.exp_cont_len = 0; 280 init_sqe(task_params, sgl_task_params, task_type); 281} 282 283static void 284init_common_initiator_read_task(struct nvmetcp_task_params *task_params, 285 struct nvme_tcp_cmd_pdu *cmd_pdu_header, 286 struct nvme_command *nvme_cmd, 287 struct storage_sgl_task_params *sgl_task_params) 288{ 289 init_rw_nvmetcp_task(task_params, NVMETCP_TASK_TYPE_HOST_READ, 290 cmd_pdu_header, nvme_cmd, sgl_task_params); 291} 292 293void init_nvmetcp_host_read_task(struct nvmetcp_task_params *task_params, 294 struct nvme_tcp_cmd_pdu *cmd_pdu_header, 295 struct nvme_command *nvme_cmd, 296 struct storage_sgl_task_params *sgl_task_params) 297{ 298 init_common_initiator_read_task(task_params, (void *)cmd_pdu_header, 299 (void *)nvme_cmd, sgl_task_params); 300} 301 302static void 303init_common_initiator_write_task(struct nvmetcp_task_params *task_params, 304 struct nvme_tcp_cmd_pdu *cmd_pdu_header, 305 struct nvme_command *nvme_cmd, 306 struct storage_sgl_task_params *sgl_task_params) 307{ 308 init_rw_nvmetcp_task(task_params, NVMETCP_TASK_TYPE_HOST_WRITE, 309 cmd_pdu_header, nvme_cmd, sgl_task_params); 310} 311 312void init_nvmetcp_host_write_task(struct nvmetcp_task_params *task_params, 313 struct nvme_tcp_cmd_pdu *cmd_pdu_header, 314 struct nvme_command *nvme_cmd, 315 struct storage_sgl_task_params *sgl_task_params) 316{ 317 init_common_initiator_write_task(task_params, (void *)cmd_pdu_header, 318 (void *)nvme_cmd, sgl_task_params); 319} 320 321static void 322init_common_login_request_task(struct nvmetcp_task_params *task_params, 323 void *login_req_pdu_header, 324 struct storage_sgl_task_params *tx_sgl_task_params, 325 struct storage_sgl_task_params *rx_sgl_task_params) 326{ 327 struct e5_nvmetcp_task_context *context = task_params->context; 328 329 init_default_nvmetcp_task(task_params, (void *)login_req_pdu_header, NULL, 330 NVMETCP_TASK_TYPE_INIT_CONN_REQUEST); 331 332 /* Ustorm Context: */ 333 init_ustorm_task_contexts(&context->ustorm_st_context, 334 &context->ustorm_ag_context, 335 336 /* Remaining Receive length is the Task Size */ 337 task_params->rx_io_size ? 338 rx_sgl_task_params->total_buffer_size : 0, 339 340 /* The size of the transmitted task */ 341 task_params->tx_io_size ? 342 tx_sgl_task_params->total_buffer_size : 0, 343 0, /* num_sges */ 344 0); /* tx_dif_conn_err_en */ 345 346 /* SGL context: */ 347 if (task_params->tx_io_size) 348 init_scsi_sgl_context(&context->ystorm_st_context.state.sgl_params, 349 &context->ystorm_st_context.state.data_desc, 350 tx_sgl_task_params); 351 if (task_params->rx_io_size) 352 init_scsi_sgl_context(&context->mstorm_st_context.sgl_params, 353 &context->mstorm_st_context.data_desc, 354 rx_sgl_task_params); 355 356 context->mstorm_st_context.rem_task_size = 357 cpu_to_le32(task_params->rx_io_size ? 358 rx_sgl_task_params->total_buffer_size : 0); 359 init_sqe(task_params, tx_sgl_task_params, NVMETCP_TASK_TYPE_INIT_CONN_REQUEST); 360} 361 362/* The following function initializes Login task in Host mode: */ 363void init_nvmetcp_init_conn_req_task(struct nvmetcp_task_params *task_params, 364 struct nvme_tcp_icreq_pdu *init_conn_req_pdu_hdr, 365 struct storage_sgl_task_params *tx_sgl_task_params, 366 struct storage_sgl_task_params *rx_sgl_task_params) 367{ 368 init_common_login_request_task(task_params, init_conn_req_pdu_hdr, 369 tx_sgl_task_params, rx_sgl_task_params); 370} 371 372void init_cleanup_task_nvmetcp(struct nvmetcp_task_params *task_params) 373{ 374 init_sqe(task_params, NULL, NVMETCP_TASK_TYPE_CLEANUP); 375}