qedi_fw_api.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* QLogic iSCSI Offload Driver
  3. * Copyright (c) 2016 Cavium Inc.
  4. */
  5. #include <linux/types.h>
  6. #include <asm/byteorder.h>
  7. #include "qedi_hsi.h"
  8. #include <linux/qed/qed_if.h>
  9. #include "qedi_fw_iscsi.h"
  10. #include "qedi_fw_scsi.h"
  11. #define SCSI_NUM_SGES_IN_CACHE 0x4
  12. static bool scsi_is_slow_sgl(u16 num_sges, bool small_mid_sge)
  13. {
  14. return (num_sges > SCSI_NUM_SGES_SLOW_SGL_THR && small_mid_sge);
  15. }
  16. static
  17. void init_scsi_sgl_context(struct scsi_sgl_params *ctx_sgl_params,
  18. struct scsi_cached_sges *ctx_data_desc,
  19. struct scsi_sgl_task_params *sgl_task_params)
  20. {
  21. u8 sge_index;
  22. u8 num_sges;
  23. u32 val;
  24. num_sges = (sgl_task_params->num_sges > SCSI_NUM_SGES_IN_CACHE) ?
  25. SCSI_NUM_SGES_IN_CACHE : sgl_task_params->num_sges;
  26. /* sgl params */
  27. val = cpu_to_le32(sgl_task_params->sgl_phys_addr.lo);
  28. ctx_sgl_params->sgl_addr.lo = val;
  29. val = cpu_to_le32(sgl_task_params->sgl_phys_addr.hi);
  30. ctx_sgl_params->sgl_addr.hi = val;
  31. val = cpu_to_le32(sgl_task_params->total_buffer_size);
  32. ctx_sgl_params->sgl_total_length = val;
  33. ctx_sgl_params->sgl_num_sges = cpu_to_le16(sgl_task_params->num_sges);
  34. for (sge_index = 0; sge_index < num_sges; sge_index++) {
  35. val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_addr.lo);
  36. ctx_data_desc->sge[sge_index].sge_addr.lo = val;
  37. val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_addr.hi);
  38. ctx_data_desc->sge[sge_index].sge_addr.hi = val;
  39. val = cpu_to_le32(sgl_task_params->sgl[sge_index].sge_len);
  40. ctx_data_desc->sge[sge_index].sge_len = val;
  41. }
  42. }
  43. static u32 calc_rw_task_size(struct iscsi_task_params *task_params,
  44. enum iscsi_task_type task_type,
  45. struct scsi_sgl_task_params *sgl_task_params,
  46. struct scsi_dif_task_params *dif_task_params)
  47. {
  48. u32 io_size;
  49. if (task_type == ISCSI_TASK_TYPE_INITIATOR_WRITE ||
  50. task_type == ISCSI_TASK_TYPE_TARGET_READ)
  51. io_size = task_params->tx_io_size;
  52. else
  53. io_size = task_params->rx_io_size;
  54. if (!io_size)
  55. return 0;
  56. if (!dif_task_params)
  57. return io_size;
  58. return !dif_task_params->dif_on_network ?
  59. io_size : sgl_task_params->total_buffer_size;
  60. }
  61. static void
  62. init_dif_context_flags(struct iscsi_dif_flags *ctx_dif_flags,
  63. struct scsi_dif_task_params *dif_task_params)
  64. {
  65. if (!dif_task_params)
  66. return;
  67. SET_FIELD(ctx_dif_flags->flags, ISCSI_DIF_FLAGS_PROT_INTERVAL_SIZE_LOG,
  68. dif_task_params->dif_block_size_log);
  69. SET_FIELD(ctx_dif_flags->flags, ISCSI_DIF_FLAGS_DIF_TO_PEER,
  70. dif_task_params->dif_on_network ? 1 : 0);
  71. SET_FIELD(ctx_dif_flags->flags, ISCSI_DIF_FLAGS_HOST_INTERFACE,
  72. dif_task_params->dif_on_host ? 1 : 0);
  73. }
  74. static void init_sqe(struct iscsi_task_params *task_params,
  75. struct scsi_sgl_task_params *sgl_task_params,
  76. struct scsi_dif_task_params *dif_task_params,
  77. struct iscsi_common_hdr *pdu_header,
  78. struct scsi_initiator_cmd_params *cmd_params,
  79. enum iscsi_task_type task_type,
  80. bool is_cleanup)
  81. {
  82. if (!task_params->sqe)
  83. return;
  84. memset(task_params->sqe, 0, sizeof(*task_params->sqe));
  85. task_params->sqe->task_id = cpu_to_le16(task_params->itid);
  86. if (is_cleanup) {
  87. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_WQE_TYPE,
  88. ISCSI_WQE_TYPE_TASK_CLEANUP);
  89. return;
  90. }
  91. switch (task_type) {
  92. case ISCSI_TASK_TYPE_INITIATOR_WRITE:
  93. {
  94. u32 buf_size = 0;
  95. u32 num_sges = 0;
  96. init_dif_context_flags(&task_params->sqe->prot_flags,
  97. dif_task_params);
  98. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_WQE_TYPE,
  99. ISCSI_WQE_TYPE_NORMAL);
  100. if (task_params->tx_io_size) {
  101. buf_size = calc_rw_task_size(task_params, task_type,
  102. sgl_task_params,
  103. dif_task_params);
  104. if (scsi_is_slow_sgl(sgl_task_params->num_sges,
  105. sgl_task_params->small_mid_sge))
  106. num_sges = ISCSI_WQE_NUM_SGES_SLOWIO;
  107. else
  108. num_sges = min(sgl_task_params->num_sges,
  109. (u16)SCSI_NUM_SGES_SLOW_SGL_THR);
  110. }
  111. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_NUM_SGES,
  112. num_sges);
  113. SET_FIELD(task_params->sqe->contlen_cdbsize, ISCSI_WQE_CONT_LEN,
  114. buf_size);
  115. if (GET_FIELD(pdu_header->hdr_second_dword,
  116. ISCSI_CMD_HDR_TOTAL_AHS_LEN))
  117. SET_FIELD(task_params->sqe->contlen_cdbsize,
  118. ISCSI_WQE_CDB_SIZE,
  119. cmd_params->extended_cdb_sge.sge_len);
  120. }
  121. break;
  122. case ISCSI_TASK_TYPE_INITIATOR_READ:
  123. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_WQE_TYPE,
  124. ISCSI_WQE_TYPE_NORMAL);
  125. if (GET_FIELD(pdu_header->hdr_second_dword,
  126. ISCSI_CMD_HDR_TOTAL_AHS_LEN))
  127. SET_FIELD(task_params->sqe->contlen_cdbsize,
  128. ISCSI_WQE_CDB_SIZE,
  129. cmd_params->extended_cdb_sge.sge_len);
  130. break;
  131. case ISCSI_TASK_TYPE_LOGIN_RESPONSE:
  132. case ISCSI_TASK_TYPE_MIDPATH:
  133. {
  134. bool advance_statsn = true;
  135. if (task_type == ISCSI_TASK_TYPE_LOGIN_RESPONSE)
  136. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_WQE_TYPE,
  137. ISCSI_WQE_TYPE_LOGIN);
  138. else
  139. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_WQE_TYPE,
  140. ISCSI_WQE_TYPE_MIDDLE_PATH);
  141. if (task_type == ISCSI_TASK_TYPE_MIDPATH) {
  142. u8 opcode = GET_FIELD(pdu_header->hdr_first_byte,
  143. ISCSI_COMMON_HDR_OPCODE);
  144. if (opcode != ISCSI_OPCODE_TEXT_RESPONSE &&
  145. (opcode != ISCSI_OPCODE_NOP_IN ||
  146. pdu_header->itt == ISCSI_TTT_ALL_ONES))
  147. advance_statsn = false;
  148. }
  149. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_RESPONSE,
  150. advance_statsn ? 1 : 0);
  151. if (task_params->tx_io_size) {
  152. SET_FIELD(task_params->sqe->contlen_cdbsize,
  153. ISCSI_WQE_CONT_LEN, task_params->tx_io_size);
  154. if (scsi_is_slow_sgl(sgl_task_params->num_sges,
  155. sgl_task_params->small_mid_sge))
  156. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_NUM_SGES,
  157. ISCSI_WQE_NUM_SGES_SLOWIO);
  158. else
  159. SET_FIELD(task_params->sqe->flags, ISCSI_WQE_NUM_SGES,
  160. min(sgl_task_params->num_sges,
  161. (u16)SCSI_NUM_SGES_SLOW_SGL_THR));
  162. }
  163. }
  164. break;
  165. default:
  166. break;
  167. }
  168. }
  169. static void init_default_iscsi_task(struct iscsi_task_params *task_params,
  170. struct data_hdr *pdu_header,
  171. enum iscsi_task_type task_type)
  172. {
  173. struct iscsi_task_context *context;
  174. u32 val;
  175. u16 index;
  176. u8 val_byte;
  177. context = task_params->context;
  178. val_byte = context->mstorm_ag_context.cdu_validation;
  179. memset(context, 0, sizeof(*context));
  180. context->mstorm_ag_context.cdu_validation = val_byte;
  181. for (index = 0; index <
  182. ARRAY_SIZE(context->ystorm_st_context.pdu_hdr.data.data);
  183. index++) {
  184. val = cpu_to_le32(pdu_header->data[index]);
  185. context->ystorm_st_context.pdu_hdr.data.data[index] = val;
  186. }
  187. context->mstorm_st_context.task_type = task_type;
  188. context->mstorm_ag_context.task_cid =
  189. cpu_to_le16(task_params->conn_icid);
  190. SET_FIELD(context->ustorm_ag_context.flags1,
  191. USTORM_ISCSI_TASK_AG_CTX_R2T2RECV, 1);
  192. context->ustorm_st_context.task_type = task_type;
  193. context->ustorm_st_context.cq_rss_number = task_params->cq_rss_number;
  194. context->ustorm_ag_context.icid = cpu_to_le16(task_params->conn_icid);
  195. }
  196. static
  197. void init_initiator_rw_cdb_ystorm_context(struct ystorm_iscsi_task_st_ctx *ystc,
  198. struct scsi_initiator_cmd_params *cmd)
  199. {
  200. union iscsi_task_hdr *ctx_pdu_hdr = &ystc->pdu_hdr;
  201. u32 val;
  202. if (!cmd->extended_cdb_sge.sge_len)
  203. return;
  204. SET_FIELD(ctx_pdu_hdr->ext_cdb_cmd.hdr_second_dword,
  205. ISCSI_EXT_CDB_CMD_HDR_CDB_SIZE,
  206. cmd->extended_cdb_sge.sge_len);
  207. val = cpu_to_le32(cmd->extended_cdb_sge.sge_addr.lo);
  208. ctx_pdu_hdr->ext_cdb_cmd.cdb_sge.sge_addr.lo = val;
  209. val = cpu_to_le32(cmd->extended_cdb_sge.sge_addr.hi);
  210. ctx_pdu_hdr->ext_cdb_cmd.cdb_sge.sge_addr.hi = val;
  211. val = cpu_to_le32(cmd->extended_cdb_sge.sge_len);
  212. ctx_pdu_hdr->ext_cdb_cmd.cdb_sge.sge_len = val;
  213. }
  214. static
  215. void init_ustorm_task_contexts(struct ustorm_iscsi_task_st_ctx *ustorm_st_cxt,
  216. struct ustorm_iscsi_task_ag_ctx *ustorm_ag_cxt,
  217. u32 remaining_recv_len, u32 expected_data_transfer_len,
  218. u8 num_sges, bool tx_dif_conn_err_en)
  219. {
  220. u32 val;
  221. ustorm_st_cxt->rem_rcv_len = cpu_to_le32(remaining_recv_len);
  222. ustorm_ag_cxt->exp_data_acked = cpu_to_le32(expected_data_transfer_len);
  223. val = cpu_to_le32(expected_data_transfer_len);
  224. ustorm_st_cxt->exp_data_transfer_len = val;
  225. SET_FIELD(ustorm_st_cxt->reg1.reg1_map, ISCSI_REG1_NUM_SGES, num_sges);
  226. SET_FIELD(ustorm_ag_cxt->flags2,
  227. USTORM_ISCSI_TASK_AG_CTX_DIF_ERROR_CF_EN,
  228. tx_dif_conn_err_en ? 1 : 0);
  229. }
  230. static
  231. void set_rw_exp_data_acked_and_cont_len(struct iscsi_task_context *context,
  232. struct iscsi_conn_params *conn_params,
  233. enum iscsi_task_type task_type,
  234. u32 task_size,
  235. u32 exp_data_transfer_len,
  236. u8 total_ahs_length)
  237. {
  238. u32 max_unsolicited_data = 0, val;
  239. if (total_ahs_length &&
  240. (task_type == ISCSI_TASK_TYPE_INITIATOR_WRITE ||
  241. task_type == ISCSI_TASK_TYPE_INITIATOR_READ))
  242. SET_FIELD(context->ustorm_st_context.flags2,
  243. USTORM_ISCSI_TASK_ST_CTX_AHS_EXIST, 1);
  244. switch (task_type) {
  245. case ISCSI_TASK_TYPE_INITIATOR_WRITE:
  246. if (!conn_params->initial_r2t)
  247. max_unsolicited_data = conn_params->first_burst_length;
  248. else if (conn_params->immediate_data)
  249. max_unsolicited_data =
  250. min(conn_params->first_burst_length,
  251. conn_params->max_send_pdu_length);
  252. context->ustorm_ag_context.exp_data_acked =
  253. cpu_to_le32(total_ahs_length == 0 ?
  254. min(exp_data_transfer_len,
  255. max_unsolicited_data) :
  256. ((u32)(total_ahs_length +
  257. ISCSI_AHS_CNTL_SIZE)));
  258. break;
  259. case ISCSI_TASK_TYPE_TARGET_READ:
  260. val = cpu_to_le32(exp_data_transfer_len);
  261. context->ustorm_ag_context.exp_data_acked = val;
  262. break;
  263. case ISCSI_TASK_TYPE_INITIATOR_READ:
  264. context->ustorm_ag_context.exp_data_acked =
  265. cpu_to_le32((total_ahs_length == 0 ? 0 :
  266. total_ahs_length +
  267. ISCSI_AHS_CNTL_SIZE));
  268. break;
  269. case ISCSI_TASK_TYPE_TARGET_WRITE:
  270. val = cpu_to_le32(task_size);
  271. context->ustorm_ag_context.exp_cont_len = val;
  272. break;
  273. default:
  274. break;
  275. }
  276. }
  277. static
  278. void init_rtdif_task_context(struct rdif_task_context *rdif_context,
  279. struct tdif_task_context *tdif_context,
  280. struct scsi_dif_task_params *dif_task_params,
  281. enum iscsi_task_type task_type)
  282. {
  283. u32 val;
  284. if (!dif_task_params->dif_on_network || !dif_task_params->dif_on_host)
  285. return;
  286. if (task_type == ISCSI_TASK_TYPE_TARGET_WRITE ||
  287. task_type == ISCSI_TASK_TYPE_INITIATOR_READ) {
  288. rdif_context->app_tag_value =
  289. cpu_to_le16(dif_task_params->application_tag);
  290. rdif_context->partial_crc_value = cpu_to_le16(0xffff);
  291. val = cpu_to_le32(dif_task_params->initial_ref_tag);
  292. rdif_context->initial_ref_tag = val;
  293. rdif_context->app_tag_mask =
  294. cpu_to_le16(dif_task_params->application_tag_mask);
  295. SET_FIELD(rdif_context->flags0, RDIF_TASK_CONTEXT_CRC_SEED,
  296. dif_task_params->crc_seed ? 1 : 0);
  297. SET_FIELD(rdif_context->flags0,
  298. RDIF_TASK_CONTEXT_HOST_GUARD_TYPE,
  299. dif_task_params->host_guard_type);
  300. SET_FIELD(rdif_context->flags0,
  301. RDIF_TASK_CONTEXT_PROTECTION_TYPE,
  302. dif_task_params->protection_type);
  303. SET_FIELD(rdif_context->flags0,
  304. RDIF_TASK_CONTEXT_INITIAL_REF_TAG_VALID, 1);
  305. SET_FIELD(rdif_context->flags0,
  306. RDIF_TASK_CONTEXT_KEEP_REF_TAG_CONST,
  307. dif_task_params->keep_ref_tag_const ? 1 : 0);
  308. SET_FIELD(rdif_context->flags1,
  309. RDIF_TASK_CONTEXT_VALIDATE_APP_TAG,
  310. (dif_task_params->validate_app_tag &&
  311. dif_task_params->dif_on_network) ? 1 : 0);
  312. SET_FIELD(rdif_context->flags1,
  313. RDIF_TASK_CONTEXT_VALIDATE_GUARD,
  314. (dif_task_params->validate_guard &&
  315. dif_task_params->dif_on_network) ? 1 : 0);
  316. SET_FIELD(rdif_context->flags1,
  317. RDIF_TASK_CONTEXT_VALIDATE_REF_TAG,
  318. (dif_task_params->validate_ref_tag &&
  319. dif_task_params->dif_on_network) ? 1 : 0);
  320. SET_FIELD(rdif_context->flags1,
  321. RDIF_TASK_CONTEXT_HOST_INTERFACE,
  322. dif_task_params->dif_on_host ? 1 : 0);
  323. SET_FIELD(rdif_context->flags1,
  324. RDIF_TASK_CONTEXT_NETWORK_INTERFACE,
  325. dif_task_params->dif_on_network ? 1 : 0);
  326. SET_FIELD(rdif_context->flags1,
  327. RDIF_TASK_CONTEXT_FORWARD_GUARD,
  328. dif_task_params->forward_guard ? 1 : 0);
  329. SET_FIELD(rdif_context->flags1,
  330. RDIF_TASK_CONTEXT_FORWARD_APP_TAG,
  331. dif_task_params->forward_app_tag ? 1 : 0);
  332. SET_FIELD(rdif_context->flags1,
  333. RDIF_TASK_CONTEXT_FORWARD_REF_TAG,
  334. dif_task_params->forward_ref_tag ? 1 : 0);
  335. SET_FIELD(rdif_context->flags1,
  336. RDIF_TASK_CONTEXT_FORWARD_APP_TAG_WITH_MASK,
  337. dif_task_params->forward_app_tag_with_mask ? 1 : 0);
  338. SET_FIELD(rdif_context->flags1,
  339. RDIF_TASK_CONTEXT_FORWARD_REF_TAG_WITH_MASK,
  340. dif_task_params->forward_ref_tag_with_mask ? 1 : 0);
  341. SET_FIELD(rdif_context->flags1,
  342. RDIF_TASK_CONTEXT_INTERVAL_SIZE,
  343. dif_task_params->dif_block_size_log - 9);
  344. SET_FIELD(rdif_context->state,
  345. RDIF_TASK_CONTEXT_REF_TAG_MASK,
  346. dif_task_params->ref_tag_mask);
  347. SET_FIELD(rdif_context->state, RDIF_TASK_CONTEXT_IGNORE_APP_TAG,
  348. dif_task_params->ignore_app_tag);
  349. }
  350. if (task_type == ISCSI_TASK_TYPE_TARGET_READ ||
  351. task_type == ISCSI_TASK_TYPE_INITIATOR_WRITE) {
  352. tdif_context->app_tag_value =
  353. cpu_to_le16(dif_task_params->application_tag);
  354. tdif_context->partial_crc_value_b =
  355. cpu_to_le16(dif_task_params->crc_seed ? 0xffff : 0x0000);
  356. tdif_context->partial_crc_value_a =
  357. cpu_to_le16(dif_task_params->crc_seed ? 0xffff : 0x0000);
  358. SET_FIELD(tdif_context->flags0, TDIF_TASK_CONTEXT_CRC_SEED,
  359. dif_task_params->crc_seed ? 1 : 0);
  360. SET_FIELD(tdif_context->flags0,
  361. TDIF_TASK_CONTEXT_SET_ERROR_WITH_EOP,
  362. dif_task_params->tx_dif_conn_err_en ? 1 : 0);
  363. SET_FIELD(tdif_context->flags1, TDIF_TASK_CONTEXT_FORWARD_GUARD,
  364. dif_task_params->forward_guard ? 1 : 0);
  365. SET_FIELD(tdif_context->flags1,
  366. TDIF_TASK_CONTEXT_FORWARD_APP_TAG,
  367. dif_task_params->forward_app_tag ? 1 : 0);
  368. SET_FIELD(tdif_context->flags1,
  369. TDIF_TASK_CONTEXT_FORWARD_REF_TAG,
  370. dif_task_params->forward_ref_tag ? 1 : 0);
  371. SET_FIELD(tdif_context->flags1, TDIF_TASK_CONTEXT_INTERVAL_SIZE,
  372. dif_task_params->dif_block_size_log - 9);
  373. SET_FIELD(tdif_context->flags1,
  374. TDIF_TASK_CONTEXT_HOST_INTERFACE,
  375. dif_task_params->dif_on_host ? 1 : 0);
  376. SET_FIELD(tdif_context->flags1,
  377. TDIF_TASK_CONTEXT_NETWORK_INTERFACE,
  378. dif_task_params->dif_on_network ? 1 : 0);
  379. val = cpu_to_le32(dif_task_params->initial_ref_tag);
  380. tdif_context->initial_ref_tag = val;
  381. tdif_context->app_tag_mask =
  382. cpu_to_le16(dif_task_params->application_tag_mask);
  383. SET_FIELD(tdif_context->flags0,
  384. TDIF_TASK_CONTEXT_HOST_GUARD_TYPE,
  385. dif_task_params->host_guard_type);
  386. SET_FIELD(tdif_context->flags0,
  387. TDIF_TASK_CONTEXT_PROTECTION_TYPE,
  388. dif_task_params->protection_type);
  389. SET_FIELD(tdif_context->flags0,
  390. TDIF_TASK_CONTEXT_INITIAL_REF_TAG_VALID,
  391. dif_task_params->initial_ref_tag_is_valid ? 1 : 0);
  392. SET_FIELD(tdif_context->flags0,
  393. TDIF_TASK_CONTEXT_KEEP_REF_TAG_CONST,
  394. dif_task_params->keep_ref_tag_const ? 1 : 0);
  395. SET_FIELD(tdif_context->flags1,
  396. TDIF_TASK_CONTEXT_VALIDATE_GUARD,
  397. (dif_task_params->validate_guard &&
  398. dif_task_params->dif_on_host) ? 1 : 0);
  399. SET_FIELD(tdif_context->flags1,
  400. TDIF_TASK_CONTEXT_VALIDATE_APP_TAG,
  401. (dif_task_params->validate_app_tag &&
  402. dif_task_params->dif_on_host) ? 1 : 0);
  403. SET_FIELD(tdif_context->flags1,
  404. TDIF_TASK_CONTEXT_VALIDATE_REF_TAG,
  405. (dif_task_params->validate_ref_tag &&
  406. dif_task_params->dif_on_host) ? 1 : 0);
  407. SET_FIELD(tdif_context->flags1,
  408. TDIF_TASK_CONTEXT_FORWARD_APP_TAG_WITH_MASK,
  409. dif_task_params->forward_app_tag_with_mask ? 1 : 0);
  410. SET_FIELD(tdif_context->flags1,
  411. TDIF_TASK_CONTEXT_FORWARD_REF_TAG_WITH_MASK,
  412. dif_task_params->forward_ref_tag_with_mask ? 1 : 0);
  413. SET_FIELD(tdif_context->flags1,
  414. TDIF_TASK_CONTEXT_REF_TAG_MASK,
  415. dif_task_params->ref_tag_mask);
  416. SET_FIELD(tdif_context->flags0,
  417. TDIF_TASK_CONTEXT_IGNORE_APP_TAG,
  418. dif_task_params->ignore_app_tag ? 1 : 0);
  419. }
  420. }
  421. static void set_local_completion_context(struct iscsi_task_context *context)
  422. {
  423. SET_FIELD(context->ystorm_st_context.state.flags,
  424. YSTORM_ISCSI_TASK_STATE_LOCAL_COMP, 1);
  425. SET_FIELD(context->ustorm_st_context.flags,
  426. USTORM_ISCSI_TASK_ST_CTX_LOCAL_COMP, 1);
  427. }
  428. static int init_rw_iscsi_task(struct iscsi_task_params *task_params,
  429. enum iscsi_task_type task_type,
  430. struct iscsi_conn_params *conn_params,
  431. struct iscsi_common_hdr *pdu_header,
  432. struct scsi_sgl_task_params *sgl_task_params,
  433. struct scsi_initiator_cmd_params *cmd_params,
  434. struct scsi_dif_task_params *dif_task_params)
  435. {
  436. u32 exp_data_transfer_len = conn_params->max_burst_length;
  437. struct iscsi_task_context *cxt;
  438. bool slow_io = false;
  439. u32 task_size, val;
  440. u8 num_sges = 0;
  441. task_size = calc_rw_task_size(task_params, task_type, sgl_task_params,
  442. dif_task_params);
  443. init_default_iscsi_task(task_params, (struct data_hdr *)pdu_header,
  444. task_type);
  445. cxt = task_params->context;
  446. if (task_type == ISCSI_TASK_TYPE_TARGET_READ) {
  447. set_local_completion_context(cxt);
  448. } else if (task_type == ISCSI_TASK_TYPE_TARGET_WRITE) {
  449. val = cpu_to_le32(task_size +
  450. ((struct iscsi_r2t_hdr *)pdu_header)->buffer_offset);
  451. cxt->ystorm_st_context.pdu_hdr.r2t.desired_data_trns_len = val;
  452. cxt->mstorm_st_context.expected_itt =
  453. cpu_to_le32(pdu_header->itt);
  454. } else {
  455. val = cpu_to_le32(task_size);
  456. cxt->ystorm_st_context.pdu_hdr.cmd.expected_transfer_length =
  457. val;
  458. init_initiator_rw_cdb_ystorm_context(&cxt->ystorm_st_context,
  459. cmd_params);
  460. val = cpu_to_le32(cmd_params->sense_data_buffer_phys_addr.lo);
  461. cxt->mstorm_st_context.sense_db.lo = val;
  462. val = cpu_to_le32(cmd_params->sense_data_buffer_phys_addr.hi);
  463. cxt->mstorm_st_context.sense_db.hi = val;
  464. }
  465. if (task_params->tx_io_size) {
  466. init_dif_context_flags(&cxt->ystorm_st_context.state.dif_flags,
  467. dif_task_params);
  468. init_dif_context_flags(&cxt->ustorm_st_context.dif_flags,
  469. dif_task_params);
  470. init_scsi_sgl_context(&cxt->ystorm_st_context.state.sgl_params,
  471. &cxt->ystorm_st_context.state.data_desc,
  472. sgl_task_params);
  473. slow_io = scsi_is_slow_sgl(sgl_task_params->num_sges,
  474. sgl_task_params->small_mid_sge);
  475. num_sges = !slow_io ? min_t(u16, sgl_task_params->num_sges,
  476. (u16)SCSI_NUM_SGES_SLOW_SGL_THR) :
  477. ISCSI_WQE_NUM_SGES_SLOWIO;
  478. if (slow_io) {
  479. SET_FIELD(cxt->ystorm_st_context.state.flags,
  480. YSTORM_ISCSI_TASK_STATE_SLOW_IO, 1);
  481. }
  482. } else if (task_params->rx_io_size) {
  483. init_dif_context_flags(&cxt->mstorm_st_context.dif_flags,
  484. dif_task_params);
  485. init_scsi_sgl_context(&cxt->mstorm_st_context.sgl_params,
  486. &cxt->mstorm_st_context.data_desc,
  487. sgl_task_params);
  488. num_sges = !scsi_is_slow_sgl(sgl_task_params->num_sges,
  489. sgl_task_params->small_mid_sge) ?
  490. min_t(u16, sgl_task_params->num_sges,
  491. (u16)SCSI_NUM_SGES_SLOW_SGL_THR) :
  492. ISCSI_WQE_NUM_SGES_SLOWIO;
  493. cxt->mstorm_st_context.rem_task_size = cpu_to_le32(task_size);
  494. }
  495. if (exp_data_transfer_len > task_size ||
  496. task_type != ISCSI_TASK_TYPE_TARGET_WRITE)
  497. exp_data_transfer_len = task_size;
  498. init_ustorm_task_contexts(&task_params->context->ustorm_st_context,
  499. &task_params->context->ustorm_ag_context,
  500. task_size, exp_data_transfer_len, num_sges,
  501. dif_task_params ?
  502. dif_task_params->tx_dif_conn_err_en : false);
  503. set_rw_exp_data_acked_and_cont_len(task_params->context, conn_params,
  504. task_type, task_size,
  505. exp_data_transfer_len,
  506. GET_FIELD(pdu_header->hdr_second_dword,
  507. ISCSI_CMD_HDR_TOTAL_AHS_LEN));
  508. if (dif_task_params)
  509. init_rtdif_task_context(&task_params->context->rdif_context,
  510. &task_params->context->tdif_context,
  511. dif_task_params, task_type);
  512. init_sqe(task_params, sgl_task_params, dif_task_params, pdu_header,
  513. cmd_params, task_type, false);
  514. return 0;
  515. }
  516. int init_initiator_rw_iscsi_task(struct iscsi_task_params *task_params,
  517. struct iscsi_conn_params *conn_params,
  518. struct scsi_initiator_cmd_params *cmd_params,
  519. struct iscsi_cmd_hdr *cmd_header,
  520. struct scsi_sgl_task_params *tx_sgl_params,
  521. struct scsi_sgl_task_params *rx_sgl_params,
  522. struct scsi_dif_task_params *dif_task_params)
  523. {
  524. if (GET_FIELD(cmd_header->flags_attr, ISCSI_CMD_HDR_WRITE))
  525. return init_rw_iscsi_task(task_params,
  526. ISCSI_TASK_TYPE_INITIATOR_WRITE,
  527. conn_params,
  528. (struct iscsi_common_hdr *)cmd_header,
  529. tx_sgl_params, cmd_params,
  530. dif_task_params);
  531. else if (GET_FIELD(cmd_header->flags_attr, ISCSI_CMD_HDR_READ) ||
  532. (task_params->rx_io_size == 0 && task_params->tx_io_size == 0))
  533. return init_rw_iscsi_task(task_params,
  534. ISCSI_TASK_TYPE_INITIATOR_READ,
  535. conn_params,
  536. (struct iscsi_common_hdr *)cmd_header,
  537. rx_sgl_params, cmd_params,
  538. dif_task_params);
  539. else
  540. return -1;
  541. }
  542. int init_initiator_login_request_task(struct iscsi_task_params *task_params,
  543. struct iscsi_login_req_hdr *login_header,
  544. struct scsi_sgl_task_params *tx_params,
  545. struct scsi_sgl_task_params *rx_params)
  546. {
  547. struct iscsi_task_context *cxt;
  548. cxt = task_params->context;
  549. init_default_iscsi_task(task_params,
  550. (struct data_hdr *)login_header,
  551. ISCSI_TASK_TYPE_MIDPATH);
  552. init_ustorm_task_contexts(&cxt->ustorm_st_context,
  553. &cxt->ustorm_ag_context,
  554. task_params->rx_io_size ?
  555. rx_params->total_buffer_size : 0,
  556. task_params->tx_io_size ?
  557. tx_params->total_buffer_size : 0, 0,
  558. 0);
  559. if (task_params->tx_io_size)
  560. init_scsi_sgl_context(&cxt->ystorm_st_context.state.sgl_params,
  561. &cxt->ystorm_st_context.state.data_desc,
  562. tx_params);
  563. if (task_params->rx_io_size)
  564. init_scsi_sgl_context(&cxt->mstorm_st_context.sgl_params,
  565. &cxt->mstorm_st_context.data_desc,
  566. rx_params);
  567. cxt->mstorm_st_context.rem_task_size =
  568. cpu_to_le32(task_params->rx_io_size ?
  569. rx_params->total_buffer_size : 0);
  570. init_sqe(task_params, tx_params, NULL,
  571. (struct iscsi_common_hdr *)login_header, NULL,
  572. ISCSI_TASK_TYPE_MIDPATH, false);
  573. return 0;
  574. }
  575. int init_initiator_nop_out_task(struct iscsi_task_params *task_params,
  576. struct iscsi_nop_out_hdr *nop_out_pdu_header,
  577. struct scsi_sgl_task_params *tx_sgl_task_params,
  578. struct scsi_sgl_task_params *rx_sgl_task_params)
  579. {
  580. struct iscsi_task_context *cxt;
  581. cxt = task_params->context;
  582. init_default_iscsi_task(task_params,
  583. (struct data_hdr *)nop_out_pdu_header,
  584. ISCSI_TASK_TYPE_MIDPATH);
  585. if (nop_out_pdu_header->itt == ISCSI_ITT_ALL_ONES)
  586. set_local_completion_context(task_params->context);
  587. if (task_params->tx_io_size)
  588. init_scsi_sgl_context(&cxt->ystorm_st_context.state.sgl_params,
  589. &cxt->ystorm_st_context.state.data_desc,
  590. tx_sgl_task_params);
  591. if (task_params->rx_io_size)
  592. init_scsi_sgl_context(&cxt->mstorm_st_context.sgl_params,
  593. &cxt->mstorm_st_context.data_desc,
  594. rx_sgl_task_params);
  595. init_ustorm_task_contexts(&cxt->ustorm_st_context,
  596. &cxt->ustorm_ag_context,
  597. task_params->rx_io_size ?
  598. rx_sgl_task_params->total_buffer_size : 0,
  599. task_params->tx_io_size ?
  600. tx_sgl_task_params->total_buffer_size : 0,
  601. 0, 0);
  602. cxt->mstorm_st_context.rem_task_size =
  603. cpu_to_le32(task_params->rx_io_size ?
  604. rx_sgl_task_params->total_buffer_size :
  605. 0);
  606. init_sqe(task_params, tx_sgl_task_params, NULL,
  607. (struct iscsi_common_hdr *)nop_out_pdu_header, NULL,
  608. ISCSI_TASK_TYPE_MIDPATH, false);
  609. return 0;
  610. }
  611. int init_initiator_logout_request_task(struct iscsi_task_params *task_params,
  612. struct iscsi_logout_req_hdr *logout_hdr,
  613. struct scsi_sgl_task_params *tx_params,
  614. struct scsi_sgl_task_params *rx_params)
  615. {
  616. struct iscsi_task_context *cxt;
  617. cxt = task_params->context;
  618. init_default_iscsi_task(task_params,
  619. (struct data_hdr *)logout_hdr,
  620. ISCSI_TASK_TYPE_MIDPATH);
  621. if (task_params->tx_io_size)
  622. init_scsi_sgl_context(&cxt->ystorm_st_context.state.sgl_params,
  623. &cxt->ystorm_st_context.state.data_desc,
  624. tx_params);
  625. if (task_params->rx_io_size)
  626. init_scsi_sgl_context(&cxt->mstorm_st_context.sgl_params,
  627. &cxt->mstorm_st_context.data_desc,
  628. rx_params);
  629. init_ustorm_task_contexts(&cxt->ustorm_st_context,
  630. &cxt->ustorm_ag_context,
  631. task_params->rx_io_size ?
  632. rx_params->total_buffer_size : 0,
  633. task_params->tx_io_size ?
  634. tx_params->total_buffer_size : 0,
  635. 0, 0);
  636. cxt->mstorm_st_context.rem_task_size =
  637. cpu_to_le32(task_params->rx_io_size ?
  638. rx_params->total_buffer_size : 0);
  639. init_sqe(task_params, tx_params, NULL,
  640. (struct iscsi_common_hdr *)logout_hdr, NULL,
  641. ISCSI_TASK_TYPE_MIDPATH, false);
  642. return 0;
  643. }
  644. int init_initiator_tmf_request_task(struct iscsi_task_params *task_params,
  645. struct iscsi_tmf_request_hdr *tmf_header)
  646. {
  647. init_default_iscsi_task(task_params, (struct data_hdr *)tmf_header,
  648. ISCSI_TASK_TYPE_MIDPATH);
  649. init_sqe(task_params, NULL, NULL,
  650. (struct iscsi_common_hdr *)tmf_header, NULL,
  651. ISCSI_TASK_TYPE_MIDPATH, false);
  652. return 0;
  653. }
  654. int init_initiator_text_request_task(struct iscsi_task_params *task_params,
  655. struct iscsi_text_request_hdr *text_header,
  656. struct scsi_sgl_task_params *tx_params,
  657. struct scsi_sgl_task_params *rx_params)
  658. {
  659. struct iscsi_task_context *cxt;
  660. cxt = task_params->context;
  661. init_default_iscsi_task(task_params,
  662. (struct data_hdr *)text_header,
  663. ISCSI_TASK_TYPE_MIDPATH);
  664. if (task_params->tx_io_size)
  665. init_scsi_sgl_context(&cxt->ystorm_st_context.state.sgl_params,
  666. &cxt->ystorm_st_context.state.data_desc,
  667. tx_params);
  668. if (task_params->rx_io_size)
  669. init_scsi_sgl_context(&cxt->mstorm_st_context.sgl_params,
  670. &cxt->mstorm_st_context.data_desc,
  671. rx_params);
  672. cxt->mstorm_st_context.rem_task_size =
  673. cpu_to_le32(task_params->rx_io_size ?
  674. rx_params->total_buffer_size : 0);
  675. init_ustorm_task_contexts(&cxt->ustorm_st_context,
  676. &cxt->ustorm_ag_context,
  677. task_params->rx_io_size ?
  678. rx_params->total_buffer_size : 0,
  679. task_params->tx_io_size ?
  680. tx_params->total_buffer_size : 0, 0, 0);
  681. init_sqe(task_params, tx_params, NULL,
  682. (struct iscsi_common_hdr *)text_header, NULL,
  683. ISCSI_TASK_TYPE_MIDPATH, false);
  684. return 0;
  685. }
  686. int init_cleanup_task(struct iscsi_task_params *task_params)
  687. {
  688. init_sqe(task_params, NULL, NULL, NULL, NULL, ISCSI_TASK_TYPE_MIDPATH,
  689. true);
  690. return 0;
  691. }