1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /**************************************************************************** |
3 | * Driver for Solarflare network controllers and boards |
4 | * Copyright 2019 Solarflare Communications Inc. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published |
8 | * by the Free Software Foundation, incorporated herein by reference. |
9 | */ |
10 | #ifndef EFX_MCDI_FILTERS_H |
11 | #define EFX_MCDI_FILTERS_H |
12 | |
13 | #include "net_driver.h" |
14 | #include "filter.h" |
15 | #include "mcdi_pcol.h" |
16 | |
17 | #define EFX_EF10_FILTER_DEV_UC_MAX 32 |
18 | #define EFX_EF10_FILTER_DEV_MC_MAX 256 |
19 | |
20 | enum efx_mcdi_filter_default_filters { |
21 | EFX_EF10_BCAST, |
22 | EFX_EF10_UCDEF, |
23 | EFX_EF10_MCDEF, |
24 | EFX_EF10_VXLAN4_UCDEF, |
25 | EFX_EF10_VXLAN4_MCDEF, |
26 | EFX_EF10_VXLAN6_UCDEF, |
27 | EFX_EF10_VXLAN6_MCDEF, |
28 | EFX_EF10_NVGRE4_UCDEF, |
29 | EFX_EF10_NVGRE4_MCDEF, |
30 | EFX_EF10_NVGRE6_UCDEF, |
31 | EFX_EF10_NVGRE6_MCDEF, |
32 | EFX_EF10_GENEVE4_UCDEF, |
33 | EFX_EF10_GENEVE4_MCDEF, |
34 | EFX_EF10_GENEVE6_UCDEF, |
35 | EFX_EF10_GENEVE6_MCDEF, |
36 | |
37 | EFX_EF10_NUM_DEFAULT_FILTERS |
38 | }; |
39 | |
40 | /* Per-VLAN filters information */ |
41 | struct efx_mcdi_filter_vlan { |
42 | struct list_head list; |
43 | u16 vid; |
44 | u16 uc[EFX_EF10_FILTER_DEV_UC_MAX]; |
45 | u16 mc[EFX_EF10_FILTER_DEV_MC_MAX]; |
46 | u16 default_filters[EFX_EF10_NUM_DEFAULT_FILTERS]; |
47 | }; |
48 | |
49 | struct efx_mcdi_dev_addr { |
50 | u8 addr[ETH_ALEN]; |
51 | }; |
52 | |
53 | struct efx_mcdi_filter_table { |
54 | /* The MCDI match masks supported by this fw & hw, in order of priority */ |
55 | u32 rx_match_mcdi_flags[ |
56 | MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2]; |
57 | unsigned int rx_match_count; |
58 | /* Our RSS context is exclusive (as opposed to shared) */ |
59 | bool ; |
60 | |
61 | struct rw_semaphore lock; /* Protects entries */ |
62 | struct { |
63 | unsigned long spec; /* pointer to spec plus flag bits */ |
64 | /* AUTO_OLD is used to mark and sweep MAC filters for the device address lists. */ |
65 | /* unused flag 1UL */ |
66 | #define EFX_EF10_FILTER_FLAG_AUTO_OLD 2UL |
67 | #define EFX_EF10_FILTER_FLAGS 3UL |
68 | u64 handle; /* firmware handle */ |
69 | } *entry; |
70 | /* Shadow of net_device address lists, guarded by mac_lock */ |
71 | struct efx_mcdi_dev_addr dev_uc_list[EFX_EF10_FILTER_DEV_UC_MAX]; |
72 | struct efx_mcdi_dev_addr dev_mc_list[EFX_EF10_FILTER_DEV_MC_MAX]; |
73 | int dev_uc_count; |
74 | int dev_mc_count; |
75 | bool uc_promisc; |
76 | bool mc_promisc; |
77 | /* Whether in multicast promiscuous mode when last changed */ |
78 | bool mc_promisc_last; |
79 | bool mc_overflow; /* Too many MC addrs; should always imply mc_promisc */ |
80 | /* RSS contexts have yet to be restored after MC reboot */ |
81 | bool ; |
82 | /* filters have yet to be restored after MC reboot */ |
83 | bool must_restore_filters; |
84 | /* Multicast filter chaining allows less-specific filters to receive |
85 | * multicast packets that matched more-specific filters. Early EF10 |
86 | * firmware didn't support this (SF bug 26807); if mc_chaining == false |
87 | * then we still subscribe the dev_mc_list even when mc_promisc to |
88 | * prevent another VI stealing the traffic. |
89 | */ |
90 | bool mc_chaining; |
91 | bool vlan_filter; |
92 | /* Entries on the vlan_list are added/removed under filter_sem */ |
93 | struct list_head vlan_list; |
94 | }; |
95 | |
96 | int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining); |
97 | void efx_mcdi_filter_table_down(struct efx_nic *efx); |
98 | void efx_mcdi_filter_table_remove(struct efx_nic *efx); |
99 | void efx_mcdi_filter_table_restore(struct efx_nic *efx); |
100 | |
101 | void efx_mcdi_filter_table_reset_mc_allocations(struct efx_nic *efx); |
102 | |
103 | /* |
104 | * The filter table(s) are managed by firmware and we have write-only |
105 | * access. When removing filters we must identify them to the |
106 | * firmware by a 64-bit handle, but this is too wide for Linux kernel |
107 | * interfaces (32-bit for RX NFC, 16-bit for RFS). Also, we need to |
108 | * be able to tell in advance whether a requested insertion will |
109 | * replace an existing filter. Therefore we maintain a software hash |
110 | * table, which should be at least as large as the hardware hash |
111 | * table. |
112 | * |
113 | * Huntington has a single 8K filter table shared between all filter |
114 | * types and both ports. |
115 | */ |
116 | #define EFX_MCDI_FILTER_TBL_ROWS 8192 |
117 | |
118 | bool efx_mcdi_filter_match_supported(struct efx_mcdi_filter_table *table, |
119 | bool encap, |
120 | enum efx_filter_match_flags match_flags); |
121 | |
122 | void efx_mcdi_filter_sync_rx_mode(struct efx_nic *efx); |
123 | s32 efx_mcdi_filter_insert(struct efx_nic *efx, struct efx_filter_spec *spec, |
124 | bool replace_equal); |
125 | int efx_mcdi_filter_remove_safe(struct efx_nic *efx, |
126 | enum efx_filter_priority priority, |
127 | u32 filter_id); |
128 | int efx_mcdi_filter_get_safe(struct efx_nic *efx, |
129 | enum efx_filter_priority priority, |
130 | u32 filter_id, struct efx_filter_spec *spec); |
131 | |
132 | u32 efx_mcdi_filter_count_rx_used(struct efx_nic *efx, |
133 | enum efx_filter_priority priority); |
134 | int efx_mcdi_filter_clear_rx(struct efx_nic *efx, |
135 | enum efx_filter_priority priority); |
136 | u32 efx_mcdi_filter_get_rx_id_limit(struct efx_nic *efx); |
137 | s32 efx_mcdi_filter_get_rx_ids(struct efx_nic *efx, |
138 | enum efx_filter_priority priority, |
139 | u32 *buf, u32 size); |
140 | |
141 | void efx_mcdi_filter_cleanup_vlans(struct efx_nic *efx); |
142 | int efx_mcdi_filter_add_vlan(struct efx_nic *efx, u16 vid); |
143 | struct efx_mcdi_filter_vlan *efx_mcdi_filter_find_vlan(struct efx_nic *efx, u16 vid); |
144 | void efx_mcdi_filter_del_vlan(struct efx_nic *efx, u16 vid); |
145 | |
146 | void efx_mcdi_rx_free_indir_table(struct efx_nic *efx); |
147 | int (struct efx_nic *efx, |
148 | struct efx_rss_context *ctx, |
149 | const u32 *rx_indir_table, |
150 | const u8 *key); |
151 | int (struct efx_nic *efx, bool user, |
152 | const u32 *rx_indir_table, |
153 | const u8 *key); |
154 | int (struct efx_nic *efx, bool user, |
155 | const u32 *rx_indir_table |
156 | __attribute__ ((unused)), |
157 | const u8 *key |
158 | __attribute__ ((unused))); |
159 | int efx_mcdi_push_default_indir_table(struct efx_nic *efx, |
160 | unsigned int ); |
161 | int (struct efx_nic *efx); |
162 | int (struct efx_nic *efx, |
163 | struct efx_rss_context *ctx); |
164 | int (struct efx_nic *efx, u32 context, |
165 | u32 *flags); |
166 | void (struct efx_nic *efx, |
167 | struct efx_rss_context *ctx); |
168 | void (struct efx_nic *efx); |
169 | |
170 | static inline void efx_mcdi_update_rx_scatter(struct efx_nic *efx) |
171 | { |
172 | /* no need to do anything here */ |
173 | } |
174 | |
175 | bool efx_mcdi_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id, |
176 | unsigned int filter_idx); |
177 | |
178 | #endif |
179 | |