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 <string.h> 12 #include <errno.h> 13 14 #include <rte_log.h> 15 #include <rte_mbuf_dyn.h> 16 17 #include "efx.h" 18 19 #include "sfc_dp.h" 20 #include "sfc_log.h" 21 22 void 23 sfc_dp_queue_init(struct sfc_dp_queue *dpq, uint16_t port_id, uint16_t queue_id, 24 const struct rte_pci_addr *pci_addr) 25 { 26 dpq->port_id = port_id; 27 dpq->queue_id = queue_id; 28 dpq->pci_addr = *pci_addr; 29 } 30 31 struct sfc_dp * 32 sfc_dp_find_by_name(struct sfc_dp_list *head, enum sfc_dp_type type, 33 const char *name) 34 { 35 struct sfc_dp *entry; 36 37 TAILQ_FOREACH(entry, head, links) { 38 if (entry->type != type) 39 continue; 40 41 if (strcmp(entry->name, name) == 0) 42 return entry; 43 } 44 45 return NULL; 46 } 47 48 struct sfc_dp * 49 sfc_dp_find_by_caps(struct sfc_dp_list *head, enum sfc_dp_type type, 50 unsigned int avail_caps) 51 { 52 struct sfc_dp *entry; 53 54 TAILQ_FOREACH(entry, head, links) { 55 if (entry->type != type) 56 continue; 57 58 /* Take the first matching */ 59 if (sfc_dp_match_hw_fw_caps(entry, avail_caps)) 60 return entry; 61 } 62 63 return NULL; 64 } 65 66 int 67 sfc_dp_register(struct sfc_dp_list *head, struct sfc_dp *entry) 68 { 69 if (sfc_dp_find_by_name(head, entry->type, entry->name) != NULL) { 70 SFC_GENERIC_LOG(ERR, 71 "sfc %s dapapath '%s' already registered", 72 entry->type == SFC_DP_RX ? "Rx" : 73 entry->type == SFC_DP_TX ? "Tx" : 74 "unknown", 75 entry->name); 76 return EEXIST; 77 } 78 79 TAILQ_INSERT_TAIL(head, entry, links); 80 81 return 0; 82 } 83 84 uint64_t sfc_dp_mport_override; 85 int sfc_dp_mport_offset = -1; 86 87 int 88 sfc_dp_mport_register(void) 89 { 90 static const struct rte_mbuf_dynfield mport = { 91 .name = "rte_net_sfc_dynfield_mport", 92 .size = sizeof(efx_mport_id_t), 93 .align = __alignof__(efx_mport_id_t), 94 }; 95 static const struct rte_mbuf_dynflag mport_override = { 96 .name = "rte_net_sfc_dynflag_mport_override", 97 }; 98 99 int field_offset; 100 int flag; 101 102 if (sfc_dp_mport_override != 0) { 103 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__); 104 return 0; 105 } 106 107 field_offset = rte_mbuf_dynfield_register(&mport); 108 if (field_offset < 0) { 109 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynfield", 110 __func__); 111 return -1; 112 } 113 114 flag = rte_mbuf_dynflag_register(&mport_override); 115 if (flag < 0) { 116 SFC_GENERIC_LOG(ERR, "%s() failed to register mport dynflag", 117 __func__); 118 return -1; 119 } 120 121 sfc_dp_mport_offset = field_offset; 122 sfc_dp_mport_override = UINT64_C(1) << flag; 123 124 return 0; 125 } 126 127 int sfc_dp_ft_id_offset = -1; 128 uint64_t sfc_dp_ft_id_valid; 129 130 int 131 sfc_dp_ft_id_register(void) 132 { 133 static const struct rte_mbuf_dynfield ft_id = { 134 .name = "rte_net_sfc_dynfield_ft_id", 135 .size = sizeof(uint8_t), 136 .align = __alignof__(uint8_t), 137 }; 138 static const struct rte_mbuf_dynflag ft_id_valid = { 139 .name = "rte_net_sfc_dynflag_ft_id_valid", 140 }; 141 142 int field_offset; 143 int flag; 144 145 SFC_GENERIC_LOG(INFO, "%s() entry", __func__); 146 147 if (sfc_dp_ft_id_valid != 0) { 148 SFC_GENERIC_LOG(INFO, "%s() already registered", __func__); 149 return 0; 150 } 151 152 field_offset = rte_mbuf_dynfield_register(&ft_id); 153 if (field_offset < 0) { 154 SFC_GENERIC_LOG(ERR, "%s() failed to register ft_id dynfield", 155 __func__); 156 return -1; 157 } 158 159 flag = rte_mbuf_dynflag_register(&ft_id_valid); 160 if (flag < 0) { 161 SFC_GENERIC_LOG(ERR, "%s() failed to register ft_id dynflag", 162 __func__); 163 return -1; 164 } 165 166 sfc_dp_ft_id_offset = field_offset; 167 sfc_dp_ft_id_valid = UINT64_C(1) << flag; 168 169 SFC_GENERIC_LOG(INFO, "%s() done", __func__); 170 171 return 0; 172 } 173