net/iavf: fix default RSS configuration
[dpdk.git] / drivers / net / ionic / ionic_rx_filter.c
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3  */
4
5 #include <errno.h>
6 #include <stdbool.h>
7
8 #include <rte_malloc.h>
9
10 #include "ionic_lif.h"
11 #include "ionic_rx_filter.h"
12
13 void
14 ionic_rx_filter_free(struct ionic_rx_filter *f)
15 {
16         LIST_REMOVE(f, by_id);
17         LIST_REMOVE(f, by_hash);
18         rte_free(f);
19 }
20
21 int
22 ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f)
23 {
24         struct ionic_admin_ctx ctx = {
25                 .pending_work = true,
26                 .cmd.rx_filter_del = {
27                         .opcode = IONIC_CMD_RX_FILTER_DEL,
28                         .filter_id = rte_cpu_to_le_32(f->filter_id),
29                 },
30         };
31
32         return ionic_adminq_post(lif, &ctx);
33 }
34
35 int
36 ionic_rx_filters_init(struct ionic_lif *lif)
37 {
38         uint32_t i;
39
40         rte_spinlock_init(&lif->rx_filters.lock);
41
42         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
43                 LIST_INIT(&lif->rx_filters.by_hash[i]);
44                 LIST_INIT(&lif->rx_filters.by_id[i]);
45         }
46
47         return 0;
48 }
49
50 void
51 ionic_rx_filters_deinit(struct ionic_lif *lif)
52 {
53         struct ionic_rx_filter *f;
54         uint32_t i;
55
56         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
57                 while (!LIST_EMPTY(&lif->rx_filters.by_id[i])) {
58                         f = LIST_FIRST(&lif->rx_filters.by_id[i]);
59                         ionic_rx_filter_free(f);
60                 }
61         }
62 }
63
64 int
65 ionic_rx_filter_save(struct ionic_lif *lif, uint32_t flow_id,
66                 uint16_t rxq_index, struct ionic_admin_ctx *ctx)
67 {
68         struct ionic_rx_filter *f;
69         uint32_t key;
70
71         f = rte_zmalloc("ionic", sizeof(*f), 0);
72
73         if (!f)
74                 return -ENOMEM;
75
76         f->flow_id = flow_id;
77         f->filter_id = rte_le_to_cpu_32(ctx->comp.rx_filter_add.filter_id);
78         f->rxq_index = rxq_index;
79         f->match = rte_le_to_cpu_16(f->cmd.match);
80         memcpy(&f->cmd, &ctx->cmd, sizeof(f->cmd));
81
82         switch (f->match) {
83         case IONIC_RX_FILTER_MATCH_VLAN:
84                 key = rte_le_to_cpu_16(f->cmd.vlan.vlan);
85                 break;
86         case IONIC_RX_FILTER_MATCH_MAC:
87                 memcpy(&key, f->cmd.mac.addr, sizeof(key));
88                 break;
89         default:
90                 return -EINVAL;
91         }
92
93         key &= IONIC_RX_FILTER_HLISTS_MASK;
94
95         rte_spinlock_lock(&lif->rx_filters.lock);
96
97         LIST_INSERT_HEAD(&lif->rx_filters.by_hash[key], f, by_hash);
98
99         key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
100
101         LIST_INSERT_HEAD(&lif->rx_filters.by_id[key], f, by_id);
102
103         rte_spinlock_unlock(&lif->rx_filters.lock);
104
105         return 0;
106 }
107
108 struct ionic_rx_filter *
109 ionic_rx_filter_by_vlan(struct ionic_lif *lif, uint16_t vid)
110 {
111         uint32_t key = vid & IONIC_RX_FILTER_HLISTS_MASK;
112         struct ionic_rx_filter *f;
113         __le16 vid_le = rte_cpu_to_le_16(vid);
114
115         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
116                 if (f->match != IONIC_RX_FILTER_MATCH_VLAN)
117                         continue;
118                 if (f->cmd.vlan.vlan == vid_le)
119                         return f;
120         }
121
122         return NULL;
123 }
124
125 struct ionic_rx_filter *
126 ionic_rx_filter_by_addr(struct ionic_lif *lif, const uint8_t *addr)
127 {
128         const uint32_t key = *(const uint32_t *)addr &
129                 IONIC_RX_FILTER_HLISTS_MASK;
130         struct ionic_rx_filter *f;
131
132         LIST_FOREACH(f, &lif->rx_filters.by_hash[key], by_hash) {
133                 if (f->match != IONIC_RX_FILTER_MATCH_MAC)
134                         continue;
135                 if (memcmp(addr, f->cmd.mac.addr, RTE_ETHER_ADDR_LEN) == 0)
136                         return f;
137         }
138
139         return NULL;
140 }