vdpa/sfc: support setting vring state
[dpdk.git] / drivers / vdpa / sfc / sfc_vdpa_filter.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020-2021 Xilinx, Inc.
3  */
4
5 #include <rte_errno.h>
6 #include <rte_ether.h>
7 #include <rte_kvargs.h>
8
9 #include "efx.h"
10 #include "efx_impl.h"
11 #include "sfc_vdpa.h"
12
13 static inline int
14 sfc_vdpa_get_eth_addr(const char *key __rte_unused,
15                       const char *value, void *extra_args)
16 {
17         struct rte_ether_addr *mac_addr = extra_args;
18
19         if (value == NULL || extra_args == NULL)
20                 return -EINVAL;
21
22         /* Convert string with Ethernet address to an ether_addr */
23         rte_ether_unformat_addr(value, mac_addr);
24
25         return 0;
26 }
27
28 static int
29 sfc_vdpa_set_mac_filter(efx_nic_t *nic, efx_filter_spec_t *spec,
30                         int qid, uint8_t *eth_addr)
31 {
32         int rc;
33
34         if (nic == NULL || spec == NULL)
35                 return -1;
36
37         spec->efs_priority = EFX_FILTER_PRI_MANUAL;
38         spec->efs_flags = EFX_FILTER_FLAG_RX;
39         spec->efs_dmaq_id = qid;
40
41         rc = efx_filter_spec_set_eth_local(spec, EFX_FILTER_SPEC_VID_UNSPEC,
42                                            eth_addr);
43         if (rc != 0)
44                 return rc;
45
46         rc = efx_filter_insert(nic, spec);
47         if (rc != 0)
48                 return rc;
49
50         return rc;
51 }
52
53 int sfc_vdpa_filter_config(struct sfc_vdpa_ops_data *ops_data)
54 {
55         int rc;
56         int qid;
57         efx_nic_t *nic;
58         struct rte_ether_addr bcast_eth_addr;
59         struct rte_ether_addr ucast_eth_addr;
60         struct sfc_vdpa_adapter *sva = ops_data->dev_handle;
61         efx_filter_spec_t *spec;
62
63         sfc_vdpa_log_init(sva, "entry");
64
65         nic = sva->nic;
66
67         sfc_vdpa_log_init(sva, "process kvarg");
68
69         /* skip MAC filter configuration if mac address is not provided */
70         if (rte_kvargs_count(sva->kvargs, SFC_VDPA_MAC_ADDR) == 0) {
71                 sfc_vdpa_warn(sva,
72                               "MAC address is not provided, skipping MAC Filter Config");
73                 return -1;
74         }
75
76         rc = rte_kvargs_process(sva->kvargs, SFC_VDPA_MAC_ADDR,
77                                 &sfc_vdpa_get_eth_addr,
78                                 &ucast_eth_addr);
79         if (rc < 0)
80                 return -1;
81
82         /* create filters on the base queue */
83         qid = SFC_VDPA_GET_VI_INDEX(0);
84
85         sfc_vdpa_log_init(sva, "insert broadcast mac filter");
86
87         EFX_MAC_BROADCAST_ADDR_SET(bcast_eth_addr.addr_bytes);
88         spec = &sva->filters.spec[SFC_VDPA_BCAST_MAC_FILTER];
89
90         rc = sfc_vdpa_set_mac_filter(nic, spec, qid,
91                                      bcast_eth_addr.addr_bytes);
92         if (rc != 0)
93                 sfc_vdpa_err(ops_data->dev_handle,
94                              "broadcast MAC filter insertion failed: %s",
95                              rte_strerror(rc));
96         else
97                 sva->filters.filter_cnt++;
98
99         sfc_vdpa_log_init(sva, "insert unicast mac filter");
100         spec = &sva->filters.spec[SFC_VDPA_UCAST_MAC_FILTER];
101
102         rc = sfc_vdpa_set_mac_filter(nic, spec, qid,
103                                      ucast_eth_addr.addr_bytes);
104         if (rc != 0)
105                 sfc_vdpa_err(sva,
106                              "unicast MAC filter insertion failed: %s",
107                              rte_strerror(rc));
108         else
109                 sva->filters.filter_cnt++;
110
111         sfc_vdpa_log_init(sva, "done");
112
113         return rc;
114 }
115
116 int sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data *ops_data)
117 {
118         int i, rc = 0;
119         struct sfc_vdpa_adapter *sva = ops_data->dev_handle;
120         efx_nic_t *nic;
121
122         nic = sva->nic;
123
124         for (i = 0; i < sva->filters.filter_cnt; i++) {
125                 rc = efx_filter_remove(nic, &(sva->filters.spec[i]));
126                 if (rc != 0)
127                         sfc_vdpa_err(sva,
128                                      "remove HW filter failed for entry %d: %s",
129                                      i, rte_strerror(rc));
130         }
131
132         sva->filters.filter_cnt = 0;
133
134         return rc;
135 }