net/sfc: maintain controller to EFX interface mapping
[dpdk.git] / drivers / net / sfc / sfc_dp.c
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 }