1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2017-2019 Solarflare Communications Inc. 5 * 6 * This software was jointly developed between OKTET Labs (under contract 7 * for Solarflare) and Solarflare Communications, Inc. 8 */ 9 10 #include <sys/queue.h> 11 #include <stdalign.h> 12 #include <string.h> 13 #include <errno.h> 14 15 #include <rte_ethdev.h> 16 #include <rte_log.h> 17 #include <rte_mbuf_dyn.h> 18 19 #include "efx.h" 20 21 #include "sfc_dp.h" 22 #include "sfc_log.h" 23 24 void 25 sfc_dp_queue_init(struct sfc_dp_queue *dpq, uint16_t port_id, uint16_t queue_id, 26 const struct rte_pci_addr *pci_addr) 27 { 28 dpq->port_id = port_id; 29 dpq->queue_id = queue_id; 30 dpq->pci_addr = *pci_addr; 31 } 32 33 struct sfc_dp * 34 sfc_dp_find_by_name(struct sfc_dp_list *head, enum sfc_dp_type type, 35 const char *name) 36 { 37 struct sfc_dp *entry; 38 39 TAILQ_FOREACH(entry, head, links) { 40 if (entry->type != type) 41 continue; 42 43 if (strcmp(entry->name, name) == 0) 44 return entry; 45 } 46 47 return NULL; 48 } 49 50 struct sfc_dp * 51 sfc_dp_find_by_caps(struct sfc_dp_list *head, enum sfc_dp_type type, 52 unsigned int avail_caps) 53 { 54 struct sfc_dp *entry; 55 56 TAILQ_FOREACH(entry, head, links) { 57 if (entry->type != type) 58 continue; 59 60 /* Take the first matching */ 61 if (sfc_dp_match_hw_fw_caps(entry, avail_caps)) 62 return entry; 63 } 64 65 return NULL; 66 } 67 68 int 69 sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry) 70 { 71 if (sfc_dp_find_by_name(head, entry->type, entry->name) != NULL) { 72 SFC_GENERIC_LOG(ERR, 73 "sfc %s datapath '%s' already registered", 74 entry->type == SFC_DP_RX ? "Rx" : 75 entry->type == SFC_DP_TX ? "Tx" : 76 "unknown", 77 entry->name); 78 return EEXIST; 79 } 80 81 TAILQ_INSERT_TAIL(head, entry, links); 82 83 return 0; 84 } 85 86 uint64_t sfc_dp_mport_override; 87 int sfc_dp_mport_offset = -1; 88 89 int 90 sfc_dp_mport_register(void) 91 { 92 static const struct rte_mbuf_dynfield mport = { 93 .name = "rte_net_sfc_dynfield_mport", 94 .size = sizeof(efx_mport_id_t), 95 .align = alignof(efx_mport_id_t), 96 }; 97 static const struct rte_mbuf_dynflag mport_override = { 98 .name = "rte_net_sfc_dynflag_mport_override", 99 }; 100 101 int field_offset; 102 int flag; 103 104 if (sfc_dp_mport_override != 0) { 105 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__); 106 return 0; 107 } 108 109 field_offset = rte_mbuf_dynfield_register(&mport); 110 if (field_offset < 0) { 111 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynfield", 112 __func__); 113 return -1; 114 } 115 116 flag = rte_mbuf_dynflag_register(&mport_override); 117 if (flag < 0) { 118 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynflag", 119 __func__); 120 return -1; 121 } 122 123 sfc_dp_mport_offset = field_offset; 124 sfc_dp_mport_override = UINT64_C(1) << flag; 125 126 return 0; 127 } 128 129 int sfc_dp_ft_ctx_id_offset = -1; 130 uint64_t sfc_dp_ft_ctx_id_valid; 131 132 int 133 sfc_dp_ft_ctx_id_register(void) 134 { 135 static const struct rte_mbuf_dynfield ft_ctx_id = { 136 .name = "rte_net_sfc_dynfield_ft_ctx_id", 137 .size = sizeof(uint8_t), 138 .align = alignof(uint8_t), 139 }; 140 141 int field_offset; 142 143 SFC_GENERIC_LOG(INFO, "%s() entry", __func__); 144 145 if (sfc_dp_ft_ctx_id_valid != 0) { 146 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__); 147 return 0; 148 } 149 150 field_offset = rte_mbuf_dynfield_register(&ft_ctx_id); 151 if (field_offset < 0) { 152 SFC_GENERIC_LOG(ERR, "%s() failed to register ft_ctx_id dynfield", 153 __func__); 154 return -1; 155 } 156 157 sfc_dp_ft_ctx_id_valid = rte_flow_restore_info_dynflag(); 158 sfc_dp_ft_ctx_id_offset = field_offset; 159 160 SFC_GENERIC_LOG(INFO, "%s() done", __func__); 161 162 return 0; 163 } 164