uda.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2. /* Copyright (c) 2016 - 2021 Intel Corporation */
  3. #include <linux/etherdevice.h>
  4. #include "osdep.h"
  5. #include "hmc.h"
  6. #include "defs.h"
  7. #include "type.h"
  8. #include "protos.h"
  9. #include "uda.h"
  10. #include "uda_d.h"
  11. /**
  12. * irdma_sc_access_ah() - Create, modify or delete AH
  13. * @cqp: struct for cqp hw
  14. * @info: ah information
  15. * @op: Operation
  16. * @scratch: u64 saved to be used during cqp completion
  17. */
  18. int irdma_sc_access_ah(struct irdma_sc_cqp *cqp, struct irdma_ah_info *info,
  19. u32 op, u64 scratch)
  20. {
  21. __le64 *wqe;
  22. u64 qw1, qw2;
  23. wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
  24. if (!wqe)
  25. return -ENOMEM;
  26. set_64bit_val(wqe, 0, ether_addr_to_u64(info->mac_addr) << 16);
  27. qw1 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXLO, info->pd_idx) |
  28. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_TC, info->tc_tos) |
  29. FIELD_PREP(IRDMA_UDAQPC_VLANTAG, info->vlan_tag);
  30. qw2 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ARPINDEX, info->dst_arpindex) |
  31. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_FLOWLABEL, info->flow_label) |
  32. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_HOPLIMIT, info->hop_ttl) |
  33. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXHI, info->pd_idx >> 16);
  34. if (!info->ipv4_valid) {
  35. set_64bit_val(wqe, 40,
  36. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
  37. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
  38. set_64bit_val(wqe, 32,
  39. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
  40. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
  41. set_64bit_val(wqe, 56,
  42. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->src_ip_addr[0]) |
  43. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->src_ip_addr[1]));
  44. set_64bit_val(wqe, 48,
  45. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->src_ip_addr[2]) |
  46. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[3]));
  47. } else {
  48. set_64bit_val(wqe, 32,
  49. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
  50. set_64bit_val(wqe, 48,
  51. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[0]));
  52. }
  53. set_64bit_val(wqe, 8, qw1);
  54. set_64bit_val(wqe, 16, qw2);
  55. dma_wmb(); /* need write block before writing WQE header */
  56. set_64bit_val(
  57. wqe, 24,
  58. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_WQEVALID, cqp->polarity) |
  59. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_OPCODE, op) |
  60. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK, info->do_lpbk) |
  61. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_IPV4VALID, info->ipv4_valid) |
  62. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_AVIDX, info->ah_idx) |
  63. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG, info->insert_vlan_tag));
  64. print_hex_dump_debug("WQE: MANAGE_AH WQE", DUMP_PREFIX_OFFSET, 16, 8,
  65. wqe, IRDMA_CQP_WQE_SIZE * 8, false);
  66. irdma_sc_cqp_post_sq(cqp);
  67. return 0;
  68. }
  69. /**
  70. * irdma_create_mg_ctx() - create a mcg context
  71. * @info: multicast group context info
  72. */
  73. static void irdma_create_mg_ctx(struct irdma_mcast_grp_info *info)
  74. {
  75. struct irdma_mcast_grp_ctx_entry_info *entry_info = NULL;
  76. u8 idx = 0; /* index in the array */
  77. u8 ctx_idx = 0; /* index in the MG context */
  78. memset(info->dma_mem_mc.va, 0, IRDMA_MAX_MGS_PER_CTX * sizeof(u64));
  79. for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
  80. entry_info = &info->mg_ctx_info[idx];
  81. if (entry_info->valid_entry) {
  82. set_64bit_val((__le64 *)info->dma_mem_mc.va,
  83. ctx_idx * sizeof(u64),
  84. FIELD_PREP(IRDMA_UDA_MGCTX_DESTPORT, entry_info->dest_port) |
  85. FIELD_PREP(IRDMA_UDA_MGCTX_VALIDENT, entry_info->valid_entry) |
  86. FIELD_PREP(IRDMA_UDA_MGCTX_QPID, entry_info->qp_id));
  87. ctx_idx++;
  88. }
  89. }
  90. }
  91. /**
  92. * irdma_access_mcast_grp() - Access mcast group based on op
  93. * @cqp: Control QP
  94. * @info: multicast group context info
  95. * @op: operation to perform
  96. * @scratch: u64 saved to be used during cqp completion
  97. */
  98. int irdma_access_mcast_grp(struct irdma_sc_cqp *cqp,
  99. struct irdma_mcast_grp_info *info, u32 op,
  100. u64 scratch)
  101. {
  102. __le64 *wqe;
  103. if (info->mg_id >= IRDMA_UDA_MAX_FSI_MGS) {
  104. ibdev_dbg(to_ibdev(cqp->dev), "WQE: mg_id out of range\n");
  105. return -EINVAL;
  106. }
  107. wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
  108. if (!wqe) {
  109. ibdev_dbg(to_ibdev(cqp->dev), "WQE: ring full\n");
  110. return -ENOMEM;
  111. }
  112. irdma_create_mg_ctx(info);
  113. set_64bit_val(wqe, 32, info->dma_mem_mc.pa);
  114. set_64bit_val(wqe, 16,
  115. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANID, info->vlan_id) |
  116. FIELD_PREP(IRDMA_UDA_CQPSQ_QS_HANDLE, info->qs_handle));
  117. set_64bit_val(wqe, 0, ether_addr_to_u64(info->dest_mac_addr));
  118. set_64bit_val(wqe, 8,
  119. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID, info->hmc_fcn_id));
  120. if (!info->ipv4_valid) {
  121. set_64bit_val(wqe, 56,
  122. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
  123. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
  124. set_64bit_val(wqe, 48,
  125. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
  126. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
  127. } else {
  128. set_64bit_val(wqe, 48,
  129. FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
  130. }
  131. dma_wmb(); /* need write memory block before writing the WQE header. */
  132. set_64bit_val(wqe, 24,
  133. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_WQEVALID, cqp->polarity) |
  134. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_OPCODE, op) |
  135. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_MGIDX, info->mg_id) |
  136. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANVALID, info->vlan_valid) |
  137. FIELD_PREP(IRDMA_UDA_CQPSQ_MG_IPV4VALID, info->ipv4_valid));
  138. print_hex_dump_debug("WQE: MANAGE_MCG WQE", DUMP_PREFIX_OFFSET, 16, 8,
  139. wqe, IRDMA_CQP_WQE_SIZE * 8, false);
  140. print_hex_dump_debug("WQE: MCG_HOST CTX WQE", DUMP_PREFIX_OFFSET, 16,
  141. 8, info->dma_mem_mc.va,
  142. IRDMA_MAX_MGS_PER_CTX * 8, false);
  143. irdma_sc_cqp_post_sq(cqp);
  144. return 0;
  145. }
  146. /**
  147. * irdma_compare_mgs - Compares two multicast group structures
  148. * @entry1: Multcast group info
  149. * @entry2: Multcast group info in context
  150. */
  151. static bool irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info *entry1,
  152. struct irdma_mcast_grp_ctx_entry_info *entry2)
  153. {
  154. if (entry1->dest_port == entry2->dest_port &&
  155. entry1->qp_id == entry2->qp_id)
  156. return true;
  157. return false;
  158. }
  159. /**
  160. * irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx
  161. * @ctx: Multcast group context
  162. * @mg: Multcast group info
  163. */
  164. int irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx,
  165. struct irdma_mcast_grp_ctx_entry_info *mg)
  166. {
  167. u32 idx;
  168. bool free_entry_found = false;
  169. u32 free_entry_idx = 0;
  170. /* find either an identical or a free entry for a multicast group */
  171. for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
  172. if (ctx->mg_ctx_info[idx].valid_entry) {
  173. if (irdma_compare_mgs(&ctx->mg_ctx_info[idx], mg)) {
  174. ctx->mg_ctx_info[idx].use_cnt++;
  175. return 0;
  176. }
  177. continue;
  178. }
  179. if (!free_entry_found) {
  180. free_entry_found = true;
  181. free_entry_idx = idx;
  182. }
  183. }
  184. if (free_entry_found) {
  185. ctx->mg_ctx_info[free_entry_idx] = *mg;
  186. ctx->mg_ctx_info[free_entry_idx].valid_entry = true;
  187. ctx->mg_ctx_info[free_entry_idx].use_cnt = 1;
  188. ctx->no_of_mgs++;
  189. return 0;
  190. }
  191. return -ENOMEM;
  192. }
  193. /**
  194. * irdma_sc_del_mcast_grp - Delete mcast group
  195. * @ctx: Multcast group context
  196. * @mg: Multcast group info
  197. *
  198. * Finds and removes a specific mulicast group from context, all
  199. * parameters must match to remove a multicast group.
  200. */
  201. int irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info *ctx,
  202. struct irdma_mcast_grp_ctx_entry_info *mg)
  203. {
  204. u32 idx;
  205. /* find an entry in multicast group context */
  206. for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
  207. if (!ctx->mg_ctx_info[idx].valid_entry)
  208. continue;
  209. if (irdma_compare_mgs(mg, &ctx->mg_ctx_info[idx])) {
  210. ctx->mg_ctx_info[idx].use_cnt--;
  211. if (!ctx->mg_ctx_info[idx].use_cnt) {
  212. ctx->mg_ctx_info[idx].valid_entry = false;
  213. ctx->no_of_mgs--;
  214. /* Remove gap if element was not the last */
  215. if (idx != ctx->no_of_mgs &&
  216. ctx->no_of_mgs > 0) {
  217. memcpy(&ctx->mg_ctx_info[idx],
  218. &ctx->mg_ctx_info[ctx->no_of_mgs - 1],
  219. sizeof(ctx->mg_ctx_info[idx]));
  220. ctx->mg_ctx_info[ctx->no_of_mgs - 1].valid_entry = false;
  221. }
  222. }
  223. return 0;
  224. }
  225. }
  226. return -EINVAL;
  227. }