Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Mucse IC Design Ltd.
3 : : */
4 : :
5 : : #include "rnp_osdep.h"
6 : :
7 : : #include "rnp_mbx_fw.h"
8 : : #include "rnp_mac.h"
9 : : #include "rnp_eth_regs.h"
10 : : #include "rnp_mac_regs.h"
11 : : #include "rnp_bitrev.h"
12 : : #include "rnp_crc32.h"
13 : : #include "../rnp.h"
14 : :
15 : : static int
16 : 0 : rnp_update_mpfm_indep(struct rnp_eth_port *port, u32 mode, bool en)
17 : : {
18 : 0 : u32 nr_lane = port->attr.nr_lane;
19 : 0 : struct rnp_hw *hw = port->hw;
20 : : u32 disable = 0, enable = 0;
21 : : u32 reg;
22 : :
23 : 0 : reg = RNP_MAC_REG_RD(hw, nr_lane, RNP_MAC_PKT_FLT_CTRL);
24 : : /* make sure not all receive modes are available */
25 [ # # ]: 0 : reg &= ~RNP_MAC_RA;
26 : : switch (mode) {
27 : : case RNP_MPF_MODE_NONE:
28 : : break;
29 : : case RNP_MPF_MODE_ALLMULTI:
30 : : enable = RNP_MAC_PM;
31 : : disable = 0;
32 : : break;
33 : : case RNP_MPF_MODE_PROMISC:
34 : : enable = RNP_MAC_PROMISC_EN;
35 : : disable = 0;
36 : : break;
37 : 0 : default:
38 : 0 : RNP_PMD_LOG(ERR, "update_mpfm argument is invalid");
39 : 0 : return -EINVAL;
40 : : }
41 [ # # ]: 0 : if (en) {
42 : : reg &= ~disable;
43 : 0 : reg |= enable;
44 : : } else {
45 : 0 : reg &= ~enable;
46 : : reg |= disable;
47 : : }
48 : : /* disable common filter when indep mode */
49 : 0 : reg |= RNP_MAC_HPF | RNP_MAC_HMC;
50 : 0 : RNP_MAC_REG_WR(hw, nr_lane, RNP_MAC_PKT_FLT_CTRL, reg);
51 : 0 : RNP_MAC_REG_WR(hw, nr_lane, RNP_MAC_FCTRL, RNP_MAC_FCTRL_BYPASS);
52 : :
53 : 0 : return 0;
54 : : }
55 : :
56 : : static int
57 : 0 : rnp_update_mpfm_pf(struct rnp_eth_port *port, u32 mode, bool en)
58 : : {
59 : 0 : u32 nr_lane = port->attr.nr_lane;
60 : 0 : struct rnp_hw *hw = port->hw;
61 : : u32 mac_filter_ctrl;
62 : : u32 filter_ctrl;
63 : : u32 bypass_ctrl;
64 : : u32 bypass = 0;
65 : :
66 : 0 : bypass_ctrl = RNP_E_REG_RD(hw, RNP_MAC_FCTRL);
67 : 0 : bypass_ctrl |= RNP_MAC_FCTRL_BAM;
68 : :
69 : : filter_ctrl = RNP_MAC_MULTICASE_TBL_EN | RNP_MAC_UNICASE_TBL_EN;
70 : 0 : RNP_E_REG_WR(hw, RNP_MAC_MCSTCTRL, filter_ctrl);
71 : :
72 : : switch (mode) {
73 : : case RNP_MPF_MODE_NONE:
74 : : bypass = 0;
75 : : break;
76 : : case RNP_MPF_MODE_ALLMULTI:
77 : : bypass = RNP_MAC_FCTRL_MPE;
78 : : break;
79 : : case RNP_MPF_MODE_PROMISC:
80 : : bypass = RNP_MAC_FCTRL_UPE | RNP_MAC_FCTRL_MPE;
81 : : break;
82 : 0 : default:
83 : 0 : RNP_PMD_LOG(ERR, "update_mpfm argument is invalid");
84 : 0 : return -EINVAL;
85 : : }
86 [ # # ]: 0 : if (en)
87 : 0 : bypass_ctrl |= bypass;
88 : : else
89 : 0 : bypass_ctrl &= ~bypass;
90 : :
91 : 0 : RNP_E_REG_WR(hw, RNP_MAC_FCTRL, bypass_ctrl);
92 : 0 : mac_filter_ctrl = RNP_MAC_REG_RD(hw, nr_lane, RNP_MAC_PKT_FLT_CTRL);
93 : : mac_filter_ctrl |= RNP_MAC_PM | RNP_MAC_PROMISC_EN;
94 : 0 : mac_filter_ctrl &= ~RNP_MAC_RA;
95 : 0 : RNP_MAC_REG_WR(hw, nr_lane, RNP_MAC_PKT_FLT_CTRL, mac_filter_ctrl);
96 : :
97 : 0 : return 0;
98 : : }
99 : :
100 : : static int
101 : 0 : rnp_set_mac_addr_pf(struct rnp_eth_port *port,
102 : : const u8 *addr, u32 index)
103 : : {
104 : 0 : struct rnp_hw *hw = port->hw;
105 : 0 : u32 addr_hi = 0, addr_lo = 0;
106 : : u8 *mac = NULL;
107 : :
108 : : mac = (u8 *)&addr_hi;
109 : 0 : mac[0] = addr[1];
110 : 0 : mac[1] = addr[0];
111 : : mac = (u8 *)&addr_lo;
112 : 0 : mac[0] = addr[5];
113 : 0 : mac[1] = addr[4];
114 : 0 : mac[2] = addr[3];
115 : 0 : mac[3] = addr[2];
116 : 0 : addr_hi |= RNP_MAC_FILTER_EN;
117 : 0 : RNP_E_REG_WR(hw, RNP_RAH_BASE_ADDR(index), addr_hi);
118 : 0 : RNP_E_REG_WR(hw, RNP_RAL_BASE_ADDR(index), addr_lo);
119 : :
120 : 0 : return 0;
121 : : }
122 : :
123 : : static int
124 : 0 : rnp_set_mac_addr_indep(struct rnp_eth_port *port,
125 : : const u8 *addr, u32 index)
126 : : {
127 : 0 : u16 lane = port->attr.nr_lane;
128 : 0 : struct rnp_hw *hw = port->hw;
129 : 0 : u32 addr_hi = 0, addr_lo = 0;
130 : : u8 *mac = NULL;
131 : :
132 : : mac = (u8 *)&addr_lo;
133 : 0 : mac[0] = addr[0];
134 : 0 : mac[1] = addr[1];
135 : 0 : mac[2] = addr[2];
136 : 0 : mac[3] = addr[3];
137 : : mac = (u8 *)&addr_hi;
138 : 0 : mac[0] = addr[4];
139 : 0 : mac[1] = addr[5];
140 : :
141 : 0 : addr_hi |= RNP_MAC_AE;
142 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_HI(index), addr_hi);
143 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_LO(index), addr_lo);
144 : :
145 : 0 : return 0;
146 : : }
147 : :
148 : : static int
149 : 0 : rnp_clear_mac_pf(struct rnp_eth_port *port, u32 index)
150 : : {
151 : 0 : struct rnp_hw *hw = port->hw;
152 : :
153 : 0 : RNP_E_REG_WR(hw, RNP_RAL_BASE_ADDR(index), 0);
154 : 0 : RNP_E_REG_WR(hw, RNP_RAH_BASE_ADDR(index), 0);
155 : :
156 : 0 : return 0;
157 : : }
158 : :
159 : : static int
160 : 0 : rnp_clear_mac_indep(struct rnp_eth_port *port, u32 index)
161 : : {
162 : 0 : u16 lane = port->attr.nr_lane;
163 : 0 : struct rnp_hw *hw = port->hw;
164 : :
165 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_HI(index), 0);
166 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_LO(index), 0);
167 : :
168 : 0 : return 0;
169 : : }
170 : :
171 : : static int
172 : 0 : rnp_en_vlan_filter_pf(struct rnp_eth_port *port, bool en)
173 : : {
174 : 0 : struct rnp_hw *hw = port->hw;
175 : : u32 ctrl;
176 : :
177 : : /* enable/disable all vlan filter configuration */
178 : 0 : ctrl = RNP_E_REG_RD(hw, RNP_VLAN_FILTER_CTRL);
179 [ # # ]: 0 : if (en)
180 : 0 : ctrl |= RNP_VLAN_FILTER_EN;
181 : : else
182 : 0 : ctrl &= ~RNP_VLAN_FILTER_EN;
183 : 0 : RNP_E_REG_WR(hw, RNP_VLAN_FILTER_CTRL, ctrl);
184 : :
185 : 0 : return 0;
186 : : }
187 : :
188 : : static int
189 : 0 : rnp_en_vlan_filter_indep(struct rnp_eth_port *port, bool en)
190 : : {
191 : 0 : u16 lane = port->attr.nr_lane;
192 : 0 : struct rnp_hw *hw = port->hw;
193 : : u32 flt_reg, vlan_reg;
194 : :
195 : 0 : flt_reg = RNP_MAC_REG_RD(hw, lane, RNP_MAC_PKT_FLT_CTRL);
196 : 0 : vlan_reg = RNP_MAC_REG_RD(hw, lane, RNP_MAC_VLAN_TAG);
197 [ # # ]: 0 : if (en) {
198 : 0 : flt_reg |= RNP_MAC_VTFE;
199 : 0 : vlan_reg |= (RNP_MAC_VLAN_VTHM | RNP_MAC_VLAN_ETV |
200 : : RNP_MAC_VLAN_HASH_EN);
201 : : } else {
202 : 0 : flt_reg &= ~RNP_MAC_VTFE;
203 : 0 : vlan_reg &= ~(RNP_MAC_VLAN_VTHM | RNP_MAC_VLAN_ETV |
204 : : RNP_MAC_VLAN_HASH_EN);
205 : : }
206 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_PKT_FLT_CTRL, flt_reg);
207 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_VLAN_TAG, vlan_reg);
208 : :
209 : 0 : return 0;
210 : : }
211 : :
212 : : static int
213 : 0 : rnp_update_vlan_filter_pf(struct rnp_eth_port *port,
214 : : u16 vlan, bool add)
215 : : {
216 : : struct rnp_vlan_filter *vfta_tb = &port->vfta;
217 : 0 : struct rnp_hw *hw = port->hw;
218 : : u32 vid_idx;
219 : : u32 vid_bit;
220 : : u32 vfta;
221 : :
222 : 0 : vid_idx = (u32)((vlan >> 5) & 0x7F);
223 : 0 : vid_bit = (u32)(1 << (vlan & 0x1F));
224 : 0 : vfta = RNP_E_REG_RD(hw, RNP_VFTA_HASH_TABLE(vid_idx));
225 [ # # ]: 0 : if (add)
226 : 0 : vfta |= vid_bit;
227 : : else
228 : 0 : vfta &= ~vid_bit;
229 : 0 : RNP_E_REG_WR(hw, RNP_VFTA_HASH_TABLE(vid_idx), vfta);
230 : : /* update local VFTA copy */
231 : 0 : vfta_tb->vfta_entries[vid_idx] = vfta;
232 : :
233 : 0 : return 0;
234 : : }
235 : :
236 : : static void
237 : 0 : rnp_update_vlan_hash_indep(struct rnp_eth_port *port)
238 : : {
239 : 0 : struct rnp_hw *hw = port->hw;
240 : 0 : u16 lane = port->attr.nr_lane;
241 : : u64 vid_idx, vid_bit;
242 : : u16 shift_bit = 0;
243 : : u16 hash = 0;
244 : : u16 vid_le;
245 : : u32 crc;
246 : : u16 vid;
247 : :
248 : : /* Generate VLAN Hash Table */
249 [ # # ]: 0 : for (vid = 0; vid < VLAN_N_VID; vid++) {
250 : 0 : vid_idx = RNP_VLAN_BITMAP_IDX(vid);
251 : 0 : vid_bit = port->vfta.vlans_bitmap[vid_idx];
252 : 0 : shift_bit = vid - (BITS_TO_LONGS(VLAN_N_VID) * vid_idx);
253 : 0 : shift_bit &= 0x3f;
254 : 0 : vid_bit = (u64)(vid_bit >> shift_bit);
255 : : /* If Vid isn't Set, Calc Next Vid Hash Value */
256 [ # # ]: 0 : if (!(vid_bit & 1))
257 : 0 : continue;
258 : : vid_le = cpu_to_le16(vid);
259 : 0 : crc = bitrev32(~rnp_vid_crc32_calc(~0, vid_le));
260 : 0 : crc >>= RNP_MAC_VLAN_HASH_SHIFT;
261 : 0 : hash |= (1 << crc);
262 : : }
263 : : /* Update vlan hash table */
264 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_VLAN_HASH, hash);
265 : 0 : }
266 : :
267 : : static int
268 : 0 : rnp_update_vlan_filter_indep(struct rnp_eth_port *port,
269 : : u16 vid,
270 : : bool add)
271 : : {
272 : : u64 vid_bit, vid_idx;
273 : :
274 : 0 : vid_bit = RNP_VLAN_BITMAP_BIT(vid);
275 : 0 : vid_idx = RNP_VLAN_BITMAP_IDX(vid);
276 [ # # ]: 0 : if (add)
277 : 0 : port->vfta.vlans_bitmap[vid_idx] |= vid_bit;
278 : : else
279 : 0 : port->vfta.vlans_bitmap[vid_idx] &= ~vid_bit;
280 : :
281 : 0 : rnp_update_vlan_hash_indep(port);
282 : :
283 : 0 : return 0;
284 : : }
285 : :
286 : : static u32
287 : 0 : rnp_sample_mac_vector(struct rnp_eth_port *port, u8 *mc_addr)
288 : : {
289 : : u32 vector = 0;
290 : :
291 [ # # # # : 0 : switch (port->hash_filter_type) {
# ]
292 : 0 : case 0: /* Use bits [11:0] of the address */
293 : 0 : vector = ((mc_addr[4] << 8) | (((u16)mc_addr[5])));
294 : 0 : break;
295 : 0 : case 1: /* Use bits [12:1] of the address */
296 : 0 : vector = ((mc_addr[4] << 7) | (((u16)mc_addr[5]) >> 1));
297 : 0 : break;
298 : 0 : case 2: /* Use bits [13:2] of the address */
299 : 0 : vector = ((mc_addr[4] << 6) | (((u16)mc_addr[5]) >> 2));
300 : 0 : break;
301 : 0 : case 3: /* Use bits [14:3] of the address */
302 : 0 : vector = ((mc_addr[4] << 4) | (((u16)mc_addr[5]) >> 4));
303 : 0 : break;
304 : 0 : default: /* Invalid mc_filter_type */
305 : 0 : RNP_PMD_ERR("Mac Hash filter type param set incorrect");
306 : 0 : break;
307 : : }
308 : 0 : vector &= RNP_MAC_HASH_MASK;
309 : :
310 : 0 : return vector;
311 : : }
312 : :
313 : : static int
314 : 0 : rnp_update_mta_pf(struct rnp_eth_port *port, u8 *mc_addr)
315 : : {
316 : 0 : struct rnp_hw *hw = port->hw;
317 : : u32 vector, hash_bit;
318 : : u32 mta_row, mta_col;
319 : : u32 value, reg;
320 : :
321 : 0 : vector = rnp_sample_mac_vector(port, mc_addr);
322 : 0 : mta_row = (vector >> RNP_HTA_BIT_SHIFT) & 0x7f;
323 : 0 : mta_col = vector & (RNP_HTA_BIT_MASK);
324 : 0 : hash_bit = 1 << mta_col;
325 : 0 : value = port->mc_hash_table[mta_row];
326 [ # # ]: 0 : if (!(value & hash_bit)) {
327 : 0 : port->mc_hash_table[mta_row] |= hash_bit;
328 : : reg = port->mc_hash_table[mta_row];
329 : 0 : RNP_E_REG_WR(hw, RNP_MC_HASH_TABLE(mta_row), reg);
330 : : }
331 : :
332 : 0 : return 0;
333 : : }
334 : :
335 : : static int
336 : 0 : rnp_clear_mta_pf(struct rnp_eth_port *port, bool en __rte_unused)
337 : : {
338 : 0 : struct rnp_hw *hw = port->hw;
339 : : u16 idx = 0;
340 : :
341 [ # # ]: 0 : for (idx = 0; idx < port->attr.mc_hash_tb_size; idx++)
342 : 0 : RNP_E_REG_WR(hw, RNP_MC_HASH_TABLE(idx), 0);
343 : 0 : memset(&port->mc_hash_table, 0, sizeof(port->mc_hash_table));
344 : :
345 : 0 : return 0;
346 : : }
347 : :
348 : : static int
349 : 0 : rnp_update_mta_indep(struct rnp_eth_port *port, u8 *mc_addr)
350 : : {
351 : : u32 hash_bit, mta_row, mta_col;
352 : 0 : u16 lane = port->attr.nr_lane;
353 : 0 : struct rnp_hw *hw = port->hw;
354 : : u32 crc, value, reg;
355 : :
356 : 0 : crc = bitrev32(~rnp_calc_crc32(~0, mc_addr, RTE_ETHER_ADDR_LEN));
357 : 0 : crc >>= port->attr.hash_table_shift;
358 : 0 : mta_row = (crc >> RNP_HTA_BIT_SHIFT) & 0x07;
359 : 0 : mta_col = crc & RNP_HTA_BIT_MASK;
360 : 0 : value = port->mc_hash_table[mta_row];
361 : 0 : hash_bit = 1 << mta_col;
362 [ # # ]: 0 : if (!(value & hash_bit)) {
363 : 0 : port->mc_hash_table[mta_row] |= hash_bit;
364 : : reg = port->mc_hash_table[mta_row];
365 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_HASH_TB(mta_row), reg);
366 : : }
367 : :
368 : 0 : return 0;
369 : : }
370 : :
371 : : static int
372 : 0 : rnp_clear_mta_indep(struct rnp_eth_port *port, bool en __rte_unused)
373 : : {
374 : 0 : u16 lane = port->attr.nr_lane;
375 : 0 : struct rnp_hw *hw = port->hw;
376 : : u16 idx = 0;
377 : :
378 [ # # ]: 0 : for (idx = 0; idx < port->attr.mc_hash_tb_size; idx++)
379 : 0 : RNP_MAC_REG_WR(hw, lane, RNP_MAC_ADDR_HASH_TB(idx), 0);
380 : 0 : memset(&port->mc_hash_table, 0, sizeof(port->mc_hash_table));
381 : :
382 : 0 : return 0;
383 : : }
384 : :
385 : : const struct rnp_mac_ops rnp_mac_ops_pf = {
386 : : .get_macaddr = rnp_mbx_fw_get_macaddr,
387 : : .update_mpfm = rnp_update_mpfm_pf,
388 : : .set_rafb = rnp_set_mac_addr_pf,
389 : : .clear_rafb = rnp_clear_mac_pf,
390 : : .update_mta = rnp_update_mta_pf,
391 : : .clear_mta = rnp_clear_mta_pf,
392 : : .vlan_f_en = rnp_en_vlan_filter_pf,
393 : : .update_vlan = rnp_update_vlan_filter_pf,
394 : : };
395 : :
396 : : const struct rnp_mac_ops rnp_mac_ops_indep = {
397 : : .get_macaddr = rnp_mbx_fw_get_macaddr,
398 : : .update_mpfm = rnp_update_mpfm_indep,
399 : : .set_rafb = rnp_set_mac_addr_indep,
400 : : .clear_rafb = rnp_clear_mac_indep,
401 : : .update_mta = rnp_update_mta_indep,
402 : : .clear_mta = rnp_clear_mta_indep,
403 : : .vlan_f_en = rnp_en_vlan_filter_indep,
404 : : .update_vlan = rnp_update_vlan_filter_indep,
405 : : };
406 : :
407 : 0 : int rnp_get_mac_addr(struct rnp_eth_port *port, u8 *mac)
408 : : {
409 : 0 : const struct rnp_mac_ops *mac_ops =
410 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
411 : :
412 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->get_macaddr, mac);
413 : : }
414 : :
415 : 0 : int rnp_update_mpfm(struct rnp_eth_port *port,
416 : : u32 mode, bool en)
417 : : {
418 : 0 : const struct rnp_mac_ops *mac_ops =
419 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
420 : :
421 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->update_mpfm, mode, en);
422 : : }
423 : :
424 : 0 : int rnp_set_macaddr(struct rnp_eth_port *port, u8 *mac, u32 index)
425 : : {
426 : 0 : const struct rnp_mac_ops *mac_ops =
427 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
428 : :
429 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->set_rafb, mac, index);
430 : : }
431 : :
432 : 0 : int rnp_clear_macaddr(struct rnp_eth_port *port, u32 index)
433 : : {
434 : 0 : const struct rnp_mac_ops *mac_ops =
435 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
436 : :
437 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->clear_rafb, index);
438 : : }
439 : :
440 : 0 : int rnp_update_mc_hash(struct rnp_eth_port *port, u8 *mc_addr)
441 : : {
442 : 0 : const struct rnp_mac_ops *mac_ops =
443 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
444 : :
445 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->update_mta, mc_addr);
446 : : }
447 : :
448 : 0 : int rnp_clear_mc_hash(struct rnp_eth_port *port)
449 : : {
450 : 0 : const struct rnp_mac_ops *mac_ops =
451 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
452 : :
453 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->clear_mta, TRUE);
454 : : }
455 : :
456 : 0 : int rnp_rx_vlan_filter_en(struct rnp_eth_port *port, bool en)
457 : : {
458 : 0 : const struct rnp_mac_ops *mac_ops =
459 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
460 : :
461 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->vlan_f_en, en);
462 : : }
463 : :
464 : 0 : int rnp_update_vlan_filter(struct rnp_eth_port *port, u16 vid, bool en)
465 : : {
466 : 0 : const struct rnp_mac_ops *mac_ops =
467 : 0 : RNP_DEV_PP_TO_MAC_OPS(port->eth_dev);
468 : :
469 [ # # ]: 0 : return rnp_call_hwif_impl(port, mac_ops->update_vlan, vid, en);
470 : : }
471 : :
472 : 0 : void rnp_mac_ops_init(struct rnp_hw *hw)
473 : : {
474 : 0 : struct rnp_proc_priv *proc_priv = RNP_DEV_TO_PROC_PRIV(hw->back->eth_dev);
475 : :
476 [ # # ]: 0 : if (rnp_pf_is_multiple_ports(hw->device_id))
477 : 0 : proc_priv->mac_ops = &rnp_mac_ops_indep;
478 : : else
479 : 0 : proc_priv->mac_ops = &rnp_mac_ops_pf;
480 : 0 : }
|