1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2014-2015 Hisilicon Limited. |
4 | */ |
5 | |
6 | #include <linux/etherdevice.h> |
7 | #include <linux/netdevice.h> |
8 | #include <linux/spinlock.h> |
9 | |
10 | #include "hnae.h" |
11 | #include "hns_dsaf_mac.h" |
12 | #include "hns_dsaf_main.h" |
13 | #include "hns_dsaf_ppe.h" |
14 | #include "hns_dsaf_rcb.h" |
15 | |
16 | static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle) |
17 | { |
18 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
19 | |
20 | return vf_cb->mac_cb; |
21 | } |
22 | |
23 | static struct dsaf_device *hns_ae_get_dsaf_dev(struct hnae_ae_dev *dev) |
24 | { |
25 | return container_of(dev, struct dsaf_device, ae_dev); |
26 | } |
27 | |
28 | static struct hns_ppe_cb *hns_get_ppe_cb(struct hnae_handle *handle) |
29 | { |
30 | int ppe_index; |
31 | struct ppe_common_cb *ppe_comm; |
32 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
33 | |
34 | ppe_comm = vf_cb->dsaf_dev->ppe_common[0]; |
35 | ppe_index = vf_cb->port_index; |
36 | |
37 | return &ppe_comm->ppe_cb[ppe_index]; |
38 | } |
39 | |
40 | static int hns_ae_get_q_num_per_vf( |
41 | struct dsaf_device *dsaf_dev, int port) |
42 | { |
43 | return dsaf_dev->rcb_common[0]->max_q_per_vf; |
44 | } |
45 | |
46 | static int hns_ae_get_vf_num_per_port( |
47 | struct dsaf_device *dsaf_dev, int port) |
48 | { |
49 | return dsaf_dev->rcb_common[0]->max_vfn; |
50 | } |
51 | |
52 | static struct ring_pair_cb *hns_ae_get_base_ring_pair( |
53 | struct dsaf_device *dsaf_dev, int port) |
54 | { |
55 | struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[0]; |
56 | int q_num = rcb_comm->max_q_per_vf; |
57 | int vf_num = rcb_comm->max_vfn; |
58 | |
59 | return &rcb_comm->ring_pair_cb[port * q_num * vf_num]; |
60 | } |
61 | |
62 | static struct ring_pair_cb *hns_ae_get_ring_pair(struct hnae_queue *q) |
63 | { |
64 | return container_of(q, struct ring_pair_cb, q); |
65 | } |
66 | |
67 | static struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, |
68 | u32 port_id) |
69 | { |
70 | int vfnum_per_port; |
71 | int qnum_per_vf; |
72 | int i; |
73 | struct dsaf_device *dsaf_dev; |
74 | struct hnae_handle *ae_handle; |
75 | struct ring_pair_cb *ring_pair_cb; |
76 | struct hnae_vf_cb *vf_cb; |
77 | |
78 | dsaf_dev = hns_ae_get_dsaf_dev(dev); |
79 | |
80 | ring_pair_cb = hns_ae_get_base_ring_pair(dsaf_dev, port: port_id); |
81 | vfnum_per_port = hns_ae_get_vf_num_per_port(dsaf_dev, port: port_id); |
82 | qnum_per_vf = hns_ae_get_q_num_per_vf(dsaf_dev, port: port_id); |
83 | |
84 | vf_cb = kzalloc(struct_size(vf_cb, ae_handle.qs, qnum_per_vf), |
85 | GFP_KERNEL); |
86 | if (unlikely(!vf_cb)) { |
87 | dev_err(dsaf_dev->dev, "malloc vf_cb fail!\n" ); |
88 | ae_handle = ERR_PTR(error: -ENOMEM); |
89 | goto handle_err; |
90 | } |
91 | ae_handle = &vf_cb->ae_handle; |
92 | /* ae_handle Init */ |
93 | ae_handle->owner_dev = dsaf_dev->dev; |
94 | ae_handle->dev = dev; |
95 | ae_handle->q_num = qnum_per_vf; |
96 | ae_handle->coal_param = HNAE_LOWEST_LATENCY_COAL_PARAM; |
97 | |
98 | /* find ring pair, and set vf id*/ |
99 | for (ae_handle->vf_id = 0; |
100 | ae_handle->vf_id < vfnum_per_port; ae_handle->vf_id++) { |
101 | if (!ring_pair_cb->used_by_vf) |
102 | break; |
103 | ring_pair_cb += qnum_per_vf; |
104 | } |
105 | if (ae_handle->vf_id >= vfnum_per_port) { |
106 | dev_err(dsaf_dev->dev, "malloc queue fail!\n" ); |
107 | ae_handle = ERR_PTR(error: -EINVAL); |
108 | goto vf_id_err; |
109 | } |
110 | |
111 | for (i = 0; i < qnum_per_vf; i++) { |
112 | ae_handle->qs[i] = &ring_pair_cb->q; |
113 | ae_handle->qs[i]->rx_ring.q = ae_handle->qs[i]; |
114 | ae_handle->qs[i]->tx_ring.q = ae_handle->qs[i]; |
115 | |
116 | ring_pair_cb->used_by_vf = 1; |
117 | ring_pair_cb++; |
118 | } |
119 | |
120 | vf_cb->dsaf_dev = dsaf_dev; |
121 | vf_cb->port_index = port_id; |
122 | vf_cb->mac_cb = dsaf_dev->mac_cb[port_id]; |
123 | |
124 | ae_handle->phy_if = vf_cb->mac_cb->phy_if; |
125 | ae_handle->phy_dev = vf_cb->mac_cb->phy_dev; |
126 | ae_handle->if_support = vf_cb->mac_cb->if_support; |
127 | ae_handle->port_type = vf_cb->mac_cb->mac_type; |
128 | ae_handle->media_type = vf_cb->mac_cb->media_type; |
129 | ae_handle->dport_id = port_id; |
130 | |
131 | return ae_handle; |
132 | vf_id_err: |
133 | kfree(objp: vf_cb); |
134 | handle_err: |
135 | return ae_handle; |
136 | } |
137 | |
138 | static void hns_ae_put_handle(struct hnae_handle *handle) |
139 | { |
140 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
141 | int i; |
142 | |
143 | for (i = 0; i < handle->q_num; i++) |
144 | hns_ae_get_ring_pair(q: handle->qs[i])->used_by_vf = 0; |
145 | |
146 | kfree(objp: vf_cb); |
147 | } |
148 | |
149 | static int hns_ae_wait_flow_down(struct hnae_handle *handle) |
150 | { |
151 | struct dsaf_device *dsaf_dev; |
152 | struct hns_ppe_cb *ppe_cb; |
153 | struct hnae_vf_cb *vf_cb; |
154 | int ret; |
155 | int i; |
156 | |
157 | for (i = 0; i < handle->q_num; i++) { |
158 | ret = hns_rcb_wait_tx_ring_clean(qs: handle->qs[i]); |
159 | if (ret) |
160 | return ret; |
161 | } |
162 | |
163 | ppe_cb = hns_get_ppe_cb(handle); |
164 | ret = hns_ppe_wait_tx_fifo_clean(ppe_cb); |
165 | if (ret) |
166 | return ret; |
167 | |
168 | dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
169 | if (!dsaf_dev) |
170 | return -EINVAL; |
171 | ret = hns_dsaf_wait_pkt_clean(dsaf_dev, port: handle->dport_id); |
172 | if (ret) |
173 | return ret; |
174 | |
175 | vf_cb = hns_ae_get_vf_cb(handle); |
176 | ret = hns_mac_wait_fifo_clean(mac_cb: vf_cb->mac_cb); |
177 | if (ret) |
178 | return ret; |
179 | |
180 | mdelay(10); |
181 | return 0; |
182 | } |
183 | |
184 | static void hns_ae_ring_enable_all(struct hnae_handle *handle, int val) |
185 | { |
186 | int q_num = handle->q_num; |
187 | int i; |
188 | |
189 | for (i = 0; i < q_num; i++) |
190 | hns_rcb_ring_enable_hw(q: handle->qs[i], val); |
191 | } |
192 | |
193 | static void hns_ae_init_queue(struct hnae_queue *q) |
194 | { |
195 | struct ring_pair_cb *ring = |
196 | container_of(q, struct ring_pair_cb, q); |
197 | |
198 | hns_rcb_init_hw(ring); |
199 | } |
200 | |
201 | static void hns_ae_fini_queue(struct hnae_queue *q) |
202 | { |
203 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle: q->handle); |
204 | |
205 | if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) |
206 | hns_rcb_reset_ring_hw(q); |
207 | } |
208 | |
209 | static int hns_ae_set_mac_address(struct hnae_handle *handle, const void *p) |
210 | { |
211 | int ret; |
212 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
213 | |
214 | if (!p || !is_valid_ether_addr(addr: (const u8 *)p)) { |
215 | dev_err(handle->owner_dev, "is not valid ether addr !\n" ); |
216 | return -EADDRNOTAVAIL; |
217 | } |
218 | |
219 | ret = hns_mac_change_vf_addr(mac_cb, vmid: handle->vf_id, addr: p); |
220 | if (ret != 0) { |
221 | dev_err(handle->owner_dev, |
222 | "set_mac_address fail, ret=%d!\n" , ret); |
223 | return ret; |
224 | } |
225 | |
226 | return 0; |
227 | } |
228 | |
229 | static int hns_ae_add_uc_address(struct hnae_handle *handle, |
230 | const unsigned char *addr) |
231 | { |
232 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
233 | |
234 | if (mac_cb->mac_type != HNAE_PORT_SERVICE) |
235 | return -ENOSPC; |
236 | |
237 | return hns_mac_add_uc_addr(mac_cb, vf_id: handle->vf_id, addr); |
238 | } |
239 | |
240 | static int hns_ae_rm_uc_address(struct hnae_handle *handle, |
241 | const unsigned char *addr) |
242 | { |
243 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
244 | |
245 | if (mac_cb->mac_type != HNAE_PORT_SERVICE) |
246 | return -ENOSPC; |
247 | |
248 | return hns_mac_rm_uc_addr(mac_cb, vf_id: handle->vf_id, addr); |
249 | } |
250 | |
251 | static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr) |
252 | { |
253 | int ret; |
254 | char *mac_addr = (char *)addr; |
255 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
256 | u8 port_num; |
257 | |
258 | assert(mac_cb); |
259 | |
260 | if (mac_cb->mac_type != HNAE_PORT_SERVICE) |
261 | return 0; |
262 | |
263 | ret = hns_mac_set_multi(mac_cb, port_num: mac_cb->mac_id, addr: mac_addr, enable: true); |
264 | if (ret) { |
265 | dev_err(handle->owner_dev, |
266 | "mac add mul_mac:%pM port%d fail, ret = %#x!\n" , |
267 | mac_addr, mac_cb->mac_id, ret); |
268 | return ret; |
269 | } |
270 | |
271 | ret = hns_mac_get_inner_port_num(mac_cb, vmid: handle->vf_id, port_num: &port_num); |
272 | if (ret) |
273 | return ret; |
274 | |
275 | ret = hns_mac_set_multi(mac_cb, port_num, addr: mac_addr, enable: true); |
276 | if (ret) |
277 | dev_err(handle->owner_dev, |
278 | "mac add mul_mac:%pM port%d fail, ret = %#x!\n" , |
279 | mac_addr, DSAF_BASE_INNER_PORT_NUM, ret); |
280 | |
281 | return ret; |
282 | } |
283 | |
284 | static int hns_ae_clr_multicast(struct hnae_handle *handle) |
285 | { |
286 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
287 | |
288 | if (mac_cb->mac_type != HNAE_PORT_SERVICE) |
289 | return 0; |
290 | |
291 | return hns_mac_clr_multicast(mac_cb, vfn: handle->vf_id); |
292 | } |
293 | |
294 | static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu) |
295 | { |
296 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
297 | struct hnae_queue *q; |
298 | u32 rx_buf_size; |
299 | int i, ret; |
300 | |
301 | /* when buf_size is 2048, max mtu is 6K for rx ring max bd num is 3. */ |
302 | if (!AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver)) { |
303 | if (new_mtu <= BD_SIZE_2048_MAX_MTU) |
304 | rx_buf_size = 2048; |
305 | else |
306 | rx_buf_size = 4096; |
307 | } else { |
308 | rx_buf_size = mac_cb->dsaf_dev->buf_size; |
309 | } |
310 | |
311 | ret = hns_mac_set_mtu(mac_cb, new_mtu, buf_size: rx_buf_size); |
312 | |
313 | if (!ret) { |
314 | /* reinit ring buf_size */ |
315 | for (i = 0; i < handle->q_num; i++) { |
316 | q = handle->qs[i]; |
317 | q->rx_ring.buf_size = rx_buf_size; |
318 | hns_rcb_set_rx_ring_bs(q, buf_size: rx_buf_size); |
319 | } |
320 | } |
321 | |
322 | return ret; |
323 | } |
324 | |
325 | static void hns_ae_set_tso_stats(struct hnae_handle *handle, int enable) |
326 | { |
327 | struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); |
328 | |
329 | hns_ppe_set_tso_enable(ppe_cb, value: enable); |
330 | } |
331 | |
332 | static int hns_ae_start(struct hnae_handle *handle) |
333 | { |
334 | int ret; |
335 | int k; |
336 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
337 | |
338 | ret = hns_mac_vm_config_bc_en(mac_cb, vm: 0, enable: true); |
339 | if (ret) |
340 | return ret; |
341 | |
342 | for (k = 0; k < handle->q_num; k++) { |
343 | if (AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver)) |
344 | hns_rcb_int_clr_hw(q: handle->qs[k], |
345 | flag: RCB_INT_FLAG_TX | RCB_INT_FLAG_RX); |
346 | else |
347 | hns_rcbv2_int_clr_hw(q: handle->qs[k], |
348 | flag: RCB_INT_FLAG_TX | RCB_INT_FLAG_RX); |
349 | } |
350 | hns_ae_ring_enable_all(handle, val: 1); |
351 | msleep(msecs: 100); |
352 | |
353 | hns_mac_start(mac_cb); |
354 | |
355 | return 0; |
356 | } |
357 | |
358 | static void hns_ae_stop(struct hnae_handle *handle) |
359 | { |
360 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
361 | |
362 | /* just clean tx fbd, neednot rx fbd*/ |
363 | hns_rcb_wait_fbd_clean(qs: handle->qs, q_num: handle->q_num, flag: RCB_INT_FLAG_TX); |
364 | |
365 | msleep(msecs: 20); |
366 | |
367 | hns_mac_stop(mac_cb); |
368 | |
369 | usleep_range(min: 10000, max: 20000); |
370 | |
371 | hns_ae_ring_enable_all(handle, val: 0); |
372 | |
373 | /* clean rx fbd. */ |
374 | hns_rcb_wait_fbd_clean(qs: handle->qs, q_num: handle->q_num, flag: RCB_INT_FLAG_RX); |
375 | |
376 | (void)hns_mac_vm_config_bc_en(mac_cb, vm: 0, enable: false); |
377 | } |
378 | |
379 | static void hns_ae_reset(struct hnae_handle *handle) |
380 | { |
381 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
382 | |
383 | if (vf_cb->mac_cb->mac_type == HNAE_PORT_DEBUG) { |
384 | hns_mac_reset(mac_cb: vf_cb->mac_cb); |
385 | hns_ppe_reset_common(dsaf_dev: vf_cb->dsaf_dev, ppe_common_index: 0); |
386 | } |
387 | } |
388 | |
389 | static void hns_ae_toggle_ring_irq(struct hnae_ring *ring, u32 mask) |
390 | { |
391 | u32 flag; |
392 | |
393 | if (is_tx_ring(ring)) |
394 | flag = RCB_INT_FLAG_TX; |
395 | else |
396 | flag = RCB_INT_FLAG_RX; |
397 | |
398 | hns_rcb_int_ctrl_hw(q: ring->q, flag, enable: mask); |
399 | } |
400 | |
401 | static void hns_aev2_toggle_ring_irq(struct hnae_ring *ring, u32 mask) |
402 | { |
403 | u32 flag; |
404 | |
405 | if (is_tx_ring(ring)) |
406 | flag = RCB_INT_FLAG_TX; |
407 | else |
408 | flag = RCB_INT_FLAG_RX; |
409 | |
410 | hns_rcbv2_int_ctrl_hw(q: ring->q, flag, mask); |
411 | } |
412 | |
413 | static int hns_ae_get_link_status(struct hnae_handle *handle) |
414 | { |
415 | u32 link_status; |
416 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
417 | |
418 | hns_mac_get_link_status(mac_cb, link_status: &link_status); |
419 | |
420 | return !!link_status; |
421 | } |
422 | |
423 | static int hns_ae_get_mac_info(struct hnae_handle *handle, |
424 | u8 *auto_neg, u16 *speed, u8 *duplex) |
425 | { |
426 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
427 | |
428 | return hns_mac_get_port_info(mac_cb, auto_neg, speed, duplex); |
429 | } |
430 | |
431 | static bool hns_ae_need_adjust_link(struct hnae_handle *handle, int speed, |
432 | int duplex) |
433 | { |
434 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
435 | |
436 | return hns_mac_need_adjust_link(mac_cb, speed, duplex); |
437 | } |
438 | |
439 | static void hns_ae_adjust_link(struct hnae_handle *handle, int speed, |
440 | int duplex) |
441 | { |
442 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
443 | |
444 | switch (mac_cb->dsaf_dev->dsaf_ver) { |
445 | case AE_VERSION_1: |
446 | hns_mac_adjust_link(mac_cb, speed, duplex); |
447 | break; |
448 | |
449 | case AE_VERSION_2: |
450 | /* chip need to clear all pkt inside */ |
451 | hns_mac_disable(mac_cb, mode: MAC_COMM_MODE_RX); |
452 | if (hns_ae_wait_flow_down(handle)) { |
453 | hns_mac_enable(mac_cb, mode: MAC_COMM_MODE_RX); |
454 | break; |
455 | } |
456 | |
457 | hns_mac_adjust_link(mac_cb, speed, duplex); |
458 | hns_mac_enable(mac_cb, mode: MAC_COMM_MODE_RX); |
459 | break; |
460 | |
461 | default: |
462 | break; |
463 | } |
464 | } |
465 | |
466 | static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue, |
467 | u32 *uplimit) |
468 | { |
469 | *uplimit = HNS_RCB_RING_MAX_PENDING_BD; |
470 | } |
471 | |
472 | static void hns_ae_get_pauseparam(struct hnae_handle *handle, |
473 | u32 *auto_neg, u32 *rx_en, u32 *tx_en) |
474 | { |
475 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
476 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
477 | |
478 | hns_mac_get_autoneg(mac_cb, auto_neg); |
479 | |
480 | hns_mac_get_pauseparam(mac_cb, rx_en, tx_en); |
481 | |
482 | /* Service port's pause feature is provided by DSAF, not mac */ |
483 | if (handle->port_type == HNAE_PORT_SERVICE) |
484 | hns_dsaf_get_rx_mac_pause_en(dsaf_dev, mac_id: mac_cb->mac_id, en: rx_en); |
485 | } |
486 | |
487 | static void hns_ae_set_promisc_mode(struct hnae_handle *handle, u32 en) |
488 | { |
489 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
490 | |
491 | hns_dsaf_set_promisc_mode(dsaf_dev: hns_ae_get_dsaf_dev(dev: handle->dev), en); |
492 | hns_mac_set_promisc(mac_cb, en: (u8)!!en); |
493 | } |
494 | |
495 | static int hns_ae_set_pauseparam(struct hnae_handle *handle, |
496 | u32 autoneg, u32 rx_en, u32 tx_en) |
497 | { |
498 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
499 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
500 | int ret; |
501 | |
502 | ret = hns_mac_set_autoneg(mac_cb, enable: autoneg); |
503 | if (ret) |
504 | return ret; |
505 | |
506 | /* Service port's pause feature is provided by DSAF, not mac */ |
507 | if (handle->port_type == HNAE_PORT_SERVICE) { |
508 | ret = hns_dsaf_set_rx_mac_pause_en(dsaf_dev, |
509 | mac_id: mac_cb->mac_id, en: rx_en); |
510 | if (ret) |
511 | return ret; |
512 | rx_en = 0; |
513 | } |
514 | return hns_mac_set_pauseparam(mac_cb, rx_en, tx_en); |
515 | } |
516 | |
517 | static void hns_ae_get_coalesce_usecs(struct hnae_handle *handle, |
518 | u32 *tx_usecs, u32 *rx_usecs) |
519 | { |
520 | struct ring_pair_cb *ring_pair = |
521 | container_of(handle->qs[0], struct ring_pair_cb, q); |
522 | |
523 | *tx_usecs = hns_rcb_get_coalesce_usecs(rcb_common: ring_pair->rcb_common, |
524 | port_idx: ring_pair->port_id_in_comm); |
525 | *rx_usecs = hns_rcb_get_coalesce_usecs(rcb_common: ring_pair->rcb_common, |
526 | port_idx: ring_pair->port_id_in_comm); |
527 | } |
528 | |
529 | static void hns_ae_get_max_coalesced_frames(struct hnae_handle *handle, |
530 | u32 *tx_frames, u32 *rx_frames) |
531 | { |
532 | struct ring_pair_cb *ring_pair = |
533 | container_of(handle->qs[0], struct ring_pair_cb, q); |
534 | struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
535 | |
536 | if (AE_IS_VER1(dsaf_dev->dsaf_ver) || |
537 | handle->port_type == HNAE_PORT_DEBUG) |
538 | *tx_frames = hns_rcb_get_rx_coalesced_frames( |
539 | rcb_common: ring_pair->rcb_common, port_idx: ring_pair->port_id_in_comm); |
540 | else |
541 | *tx_frames = hns_rcb_get_tx_coalesced_frames( |
542 | rcb_common: ring_pair->rcb_common, port_idx: ring_pair->port_id_in_comm); |
543 | *rx_frames = hns_rcb_get_rx_coalesced_frames(rcb_common: ring_pair->rcb_common, |
544 | port_idx: ring_pair->port_id_in_comm); |
545 | } |
546 | |
547 | static int hns_ae_set_coalesce_usecs(struct hnae_handle *handle, |
548 | u32 timeout) |
549 | { |
550 | struct ring_pair_cb *ring_pair = |
551 | container_of(handle->qs[0], struct ring_pair_cb, q); |
552 | |
553 | return hns_rcb_set_coalesce_usecs( |
554 | rcb_common: ring_pair->rcb_common, port_idx: ring_pair->port_id_in_comm, timeout); |
555 | } |
556 | |
557 | static int hns_ae_set_coalesce_frames(struct hnae_handle *handle, |
558 | u32 tx_frames, u32 rx_frames) |
559 | { |
560 | int ret; |
561 | struct ring_pair_cb *ring_pair = |
562 | container_of(handle->qs[0], struct ring_pair_cb, q); |
563 | struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
564 | |
565 | if (AE_IS_VER1(dsaf_dev->dsaf_ver) || |
566 | handle->port_type == HNAE_PORT_DEBUG) { |
567 | if (tx_frames != rx_frames) |
568 | return -EINVAL; |
569 | return hns_rcb_set_rx_coalesced_frames( |
570 | rcb_common: ring_pair->rcb_common, |
571 | port_idx: ring_pair->port_id_in_comm, coalesced_frames: rx_frames); |
572 | } else { |
573 | if (tx_frames != 1) |
574 | return -EINVAL; |
575 | ret = hns_rcb_set_tx_coalesced_frames( |
576 | rcb_common: ring_pair->rcb_common, |
577 | port_idx: ring_pair->port_id_in_comm, coalesced_frames: tx_frames); |
578 | if (ret) |
579 | return ret; |
580 | |
581 | return hns_rcb_set_rx_coalesced_frames( |
582 | rcb_common: ring_pair->rcb_common, |
583 | port_idx: ring_pair->port_id_in_comm, coalesced_frames: rx_frames); |
584 | } |
585 | } |
586 | |
587 | static void hns_ae_get_coalesce_range(struct hnae_handle *handle, |
588 | u32 *tx_frames_low, u32 *rx_frames_low, |
589 | u32 *tx_frames_high, u32 *rx_frames_high, |
590 | u32 *tx_usecs_low, u32 *rx_usecs_low, |
591 | u32 *tx_usecs_high, u32 *rx_usecs_high) |
592 | { |
593 | struct dsaf_device *dsaf_dev; |
594 | |
595 | assert(handle); |
596 | |
597 | dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
598 | |
599 | *tx_frames_low = HNS_RCB_TX_FRAMES_LOW; |
600 | *rx_frames_low = HNS_RCB_RX_FRAMES_LOW; |
601 | |
602 | if (AE_IS_VER1(dsaf_dev->dsaf_ver) || |
603 | handle->port_type == HNAE_PORT_DEBUG) |
604 | *tx_frames_high = |
605 | (dsaf_dev->desc_num - 1 > HNS_RCB_TX_FRAMES_HIGH) ? |
606 | HNS_RCB_TX_FRAMES_HIGH : dsaf_dev->desc_num - 1; |
607 | else |
608 | *tx_frames_high = 1; |
609 | |
610 | *rx_frames_high = (dsaf_dev->desc_num - 1 > HNS_RCB_RX_FRAMES_HIGH) ? |
611 | HNS_RCB_RX_FRAMES_HIGH : dsaf_dev->desc_num - 1; |
612 | *tx_usecs_low = HNS_RCB_TX_USECS_LOW; |
613 | *rx_usecs_low = HNS_RCB_RX_USECS_LOW; |
614 | *tx_usecs_high = HNS_RCB_TX_USECS_HIGH; |
615 | *rx_usecs_high = HNS_RCB_RX_USECS_HIGH; |
616 | } |
617 | |
618 | static void hns_ae_update_stats(struct hnae_handle *handle, |
619 | struct net_device_stats *net_stats) |
620 | { |
621 | int port; |
622 | int idx; |
623 | struct dsaf_device *dsaf_dev; |
624 | struct hns_mac_cb *mac_cb; |
625 | struct hns_ppe_cb *ppe_cb; |
626 | struct hnae_queue *queue; |
627 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
628 | u64 tx_bytes = 0, rx_bytes = 0, tx_packets = 0, rx_packets = 0; |
629 | u64 rx_errors = 0, tx_errors = 0, tx_dropped = 0; |
630 | u64 rx_missed_errors; |
631 | |
632 | dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
633 | if (!dsaf_dev) |
634 | return; |
635 | port = vf_cb->port_index; |
636 | ppe_cb = hns_get_ppe_cb(handle); |
637 | mac_cb = hns_get_mac_cb(handle); |
638 | |
639 | for (idx = 0; idx < handle->q_num; idx++) { |
640 | queue = handle->qs[idx]; |
641 | hns_rcb_update_stats(queue); |
642 | |
643 | tx_bytes += queue->tx_ring.stats.tx_bytes; |
644 | tx_packets += queue->tx_ring.stats.tx_pkts; |
645 | rx_bytes += queue->rx_ring.stats.rx_bytes; |
646 | rx_packets += queue->rx_ring.stats.rx_pkts; |
647 | |
648 | rx_errors += queue->rx_ring.stats.err_pkt_len |
649 | + queue->rx_ring.stats.l2_err |
650 | + queue->rx_ring.stats.l3l4_csum_err; |
651 | } |
652 | |
653 | hns_ppe_update_stats(ppe_cb); |
654 | rx_missed_errors = ppe_cb->hw_stats.rx_drop_no_buf; |
655 | tx_errors += ppe_cb->hw_stats.tx_err_checksum |
656 | + ppe_cb->hw_stats.tx_err_fifo_empty; |
657 | |
658 | if (mac_cb->mac_type == HNAE_PORT_SERVICE) { |
659 | hns_dsaf_update_stats(dsaf_dev, inode_num: port); |
660 | /* for port upline direction, i.e., rx. */ |
661 | rx_missed_errors += dsaf_dev->hw_stats[port].bp_drop; |
662 | rx_missed_errors += dsaf_dev->hw_stats[port].pad_drop; |
663 | rx_missed_errors += dsaf_dev->hw_stats[port].crc_false; |
664 | |
665 | /* for port downline direction, i.e., tx. */ |
666 | port = port + DSAF_PPE_INODE_BASE; |
667 | hns_dsaf_update_stats(dsaf_dev, inode_num: port); |
668 | tx_dropped += dsaf_dev->hw_stats[port].bp_drop; |
669 | tx_dropped += dsaf_dev->hw_stats[port].pad_drop; |
670 | tx_dropped += dsaf_dev->hw_stats[port].crc_false; |
671 | tx_dropped += dsaf_dev->hw_stats[port].rslt_drop; |
672 | tx_dropped += dsaf_dev->hw_stats[port].vlan_drop; |
673 | tx_dropped += dsaf_dev->hw_stats[port].stp_drop; |
674 | } |
675 | |
676 | hns_mac_update_stats(mac_cb); |
677 | rx_errors += mac_cb->hw_stats.rx_fifo_overrun_err; |
678 | |
679 | tx_errors += mac_cb->hw_stats.tx_bad_pkts |
680 | + mac_cb->hw_stats.tx_fragment_err |
681 | + mac_cb->hw_stats.tx_jabber_err |
682 | + mac_cb->hw_stats.tx_underrun_err |
683 | + mac_cb->hw_stats.tx_crc_err; |
684 | |
685 | net_stats->tx_bytes = tx_bytes; |
686 | net_stats->tx_packets = tx_packets; |
687 | net_stats->rx_bytes = rx_bytes; |
688 | net_stats->rx_dropped = 0; |
689 | net_stats->rx_packets = rx_packets; |
690 | net_stats->rx_errors = rx_errors; |
691 | net_stats->tx_errors = tx_errors; |
692 | net_stats->tx_dropped = tx_dropped; |
693 | net_stats->rx_missed_errors = rx_missed_errors; |
694 | net_stats->rx_crc_errors = mac_cb->hw_stats.rx_fcs_err; |
695 | net_stats->rx_frame_errors = mac_cb->hw_stats.rx_align_err; |
696 | net_stats->rx_fifo_errors = mac_cb->hw_stats.rx_fifo_overrun_err; |
697 | net_stats->rx_length_errors = mac_cb->hw_stats.rx_len_err; |
698 | net_stats->multicast = mac_cb->hw_stats.rx_mc_pkts; |
699 | } |
700 | |
701 | static void hns_ae_get_stats(struct hnae_handle *handle, u64 *data) |
702 | { |
703 | int idx; |
704 | struct hns_mac_cb *mac_cb; |
705 | struct hns_ppe_cb *ppe_cb; |
706 | u64 *p = data; |
707 | struct hnae_vf_cb *vf_cb; |
708 | |
709 | if (!handle || !data) { |
710 | pr_err("hns_ae_get_stats NULL handle or data pointer!\n" ); |
711 | return; |
712 | } |
713 | |
714 | vf_cb = hns_ae_get_vf_cb(handle); |
715 | mac_cb = hns_get_mac_cb(handle); |
716 | ppe_cb = hns_get_ppe_cb(handle); |
717 | |
718 | for (idx = 0; idx < handle->q_num; idx++) { |
719 | hns_rcb_get_stats(queue: handle->qs[idx], data: p); |
720 | p += hns_rcb_get_ring_sset_count(stringset: (int)ETH_SS_STATS); |
721 | } |
722 | |
723 | hns_ppe_get_stats(ppe_cb, data: p); |
724 | p += hns_ppe_get_sset_count(stringset: (int)ETH_SS_STATS); |
725 | |
726 | hns_mac_get_stats(mac_cb, data: p); |
727 | p += hns_mac_get_sset_count(mac_cb, stringset: (int)ETH_SS_STATS); |
728 | |
729 | if (mac_cb->mac_type == HNAE_PORT_SERVICE) |
730 | hns_dsaf_get_stats(ddev: vf_cb->dsaf_dev, data: p, port: vf_cb->port_index); |
731 | } |
732 | |
733 | static void hns_ae_get_strings(struct hnae_handle *handle, |
734 | u32 stringset, u8 *data) |
735 | { |
736 | int port; |
737 | int idx; |
738 | struct hns_mac_cb *mac_cb; |
739 | struct hns_ppe_cb *ppe_cb; |
740 | struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
741 | u8 *p = data; |
742 | struct hnae_vf_cb *vf_cb; |
743 | |
744 | assert(handle); |
745 | |
746 | vf_cb = hns_ae_get_vf_cb(handle); |
747 | port = vf_cb->port_index; |
748 | mac_cb = hns_get_mac_cb(handle); |
749 | ppe_cb = hns_get_ppe_cb(handle); |
750 | |
751 | for (idx = 0; idx < handle->q_num; idx++) { |
752 | hns_rcb_get_strings(stringset, data: p, index: idx); |
753 | p += ETH_GSTRING_LEN * hns_rcb_get_ring_sset_count(stringset); |
754 | } |
755 | |
756 | hns_ppe_get_strings(ppe_cb, stringset, data: p); |
757 | p += ETH_GSTRING_LEN * hns_ppe_get_sset_count(stringset); |
758 | |
759 | hns_mac_get_strings(mac_cb, stringset, data: p); |
760 | p += ETH_GSTRING_LEN * hns_mac_get_sset_count(mac_cb, stringset); |
761 | |
762 | if (mac_cb->mac_type == HNAE_PORT_SERVICE) |
763 | hns_dsaf_get_strings(stringset, data: p, port, dsaf_dev); |
764 | } |
765 | |
766 | static int hns_ae_get_sset_count(struct hnae_handle *handle, int stringset) |
767 | { |
768 | u32 sset_count = 0; |
769 | struct hns_mac_cb *mac_cb; |
770 | struct dsaf_device *dsaf_dev = hns_ae_get_dsaf_dev(dev: handle->dev); |
771 | |
772 | assert(handle); |
773 | |
774 | mac_cb = hns_get_mac_cb(handle); |
775 | |
776 | sset_count += hns_rcb_get_ring_sset_count(stringset) * handle->q_num; |
777 | sset_count += hns_ppe_get_sset_count(stringset); |
778 | sset_count += hns_mac_get_sset_count(mac_cb, stringset); |
779 | |
780 | if (mac_cb->mac_type == HNAE_PORT_SERVICE) |
781 | sset_count += hns_dsaf_get_sset_count(dsaf_dev, stringset); |
782 | |
783 | return sset_count; |
784 | } |
785 | |
786 | static int hns_ae_config_loopback(struct hnae_handle *handle, |
787 | enum hnae_loop loop, int en) |
788 | { |
789 | int ret; |
790 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
791 | struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); |
792 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
793 | |
794 | switch (loop) { |
795 | case MAC_INTERNALLOOP_PHY: |
796 | ret = 0; |
797 | break; |
798 | case MAC_INTERNALLOOP_SERDES: |
799 | ret = dsaf_dev->misc_op->cfg_serdes_loopback(vf_cb->mac_cb, |
800 | !!en); |
801 | break; |
802 | case MAC_INTERNALLOOP_MAC: |
803 | ret = hns_mac_config_mac_loopback(mac_cb: vf_cb->mac_cb, loop, en); |
804 | break; |
805 | default: |
806 | ret = -EINVAL; |
807 | } |
808 | |
809 | return ret; |
810 | } |
811 | |
812 | static void hns_ae_update_led_status(struct hnae_handle *handle) |
813 | { |
814 | struct hns_mac_cb *mac_cb; |
815 | |
816 | assert(handle); |
817 | mac_cb = hns_get_mac_cb(handle); |
818 | if (mac_cb->media_type != HNAE_MEDIA_TYPE_FIBER) |
819 | return; |
820 | |
821 | hns_set_led_opt(mac_cb); |
822 | } |
823 | |
824 | static int hns_ae_cpld_set_led_id(struct hnae_handle *handle, |
825 | enum hnae_led_state status) |
826 | { |
827 | struct hns_mac_cb *mac_cb; |
828 | |
829 | assert(handle); |
830 | |
831 | mac_cb = hns_get_mac_cb(handle); |
832 | |
833 | return hns_cpld_led_set_id(mac_cb, status); |
834 | } |
835 | |
836 | static void hns_ae_get_regs(struct hnae_handle *handle, void *data) |
837 | { |
838 | u32 *p = data; |
839 | int i; |
840 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
841 | struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); |
842 | |
843 | hns_ppe_get_regs(ppe_cb, data: p); |
844 | p += hns_ppe_get_regs_count(); |
845 | |
846 | hns_rcb_get_common_regs(rcb_common: vf_cb->dsaf_dev->rcb_common[0], data: p); |
847 | p += hns_rcb_get_common_regs_count(); |
848 | |
849 | for (i = 0; i < handle->q_num; i++) { |
850 | hns_rcb_get_ring_regs(queue: handle->qs[i], data: p); |
851 | p += hns_rcb_get_ring_regs_count(); |
852 | } |
853 | |
854 | hns_mac_get_regs(mac_cb: vf_cb->mac_cb, data: p); |
855 | p += hns_mac_get_regs_count(mac_cb: vf_cb->mac_cb); |
856 | |
857 | if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) |
858 | hns_dsaf_get_regs(ddev: vf_cb->dsaf_dev, port: vf_cb->port_index, data: p); |
859 | } |
860 | |
861 | static int hns_ae_get_regs_len(struct hnae_handle *handle) |
862 | { |
863 | u32 total_num; |
864 | struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle); |
865 | |
866 | total_num = hns_ppe_get_regs_count(); |
867 | total_num += hns_rcb_get_common_regs_count(); |
868 | total_num += hns_rcb_get_ring_regs_count() * handle->q_num; |
869 | total_num += hns_mac_get_regs_count(mac_cb: vf_cb->mac_cb); |
870 | |
871 | if (vf_cb->mac_cb->mac_type == HNAE_PORT_SERVICE) |
872 | total_num += hns_dsaf_get_regs_count(); |
873 | |
874 | return total_num; |
875 | } |
876 | |
877 | static u32 (struct hnae_handle *handle) |
878 | { |
879 | return HNS_PPEV2_RSS_KEY_SIZE; |
880 | } |
881 | |
882 | static u32 (struct hnae_handle *handle) |
883 | { |
884 | return HNS_PPEV2_RSS_IND_TBL_SIZE; |
885 | } |
886 | |
887 | static int (struct hnae_handle *handle, u32 *indir, u8 *key, |
888 | u8 *hfunc) |
889 | { |
890 | struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); |
891 | |
892 | /* currently we support only one type of hash function i.e. Toep hash */ |
893 | if (hfunc) |
894 | *hfunc = ETH_RSS_HASH_TOP; |
895 | |
896 | /* get the RSS Key required by the user */ |
897 | if (key) |
898 | memcpy(key, ppe_cb->rss_key, HNS_PPEV2_RSS_KEY_SIZE); |
899 | |
900 | /* update the current hash->queue mappings from the shadow RSS table */ |
901 | if (indir) |
902 | memcpy(indir, ppe_cb->rss_indir_table, |
903 | HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir)); |
904 | |
905 | return 0; |
906 | } |
907 | |
908 | static int (struct hnae_handle *handle, const u32 *indir, |
909 | const u8 *key, const u8 hfunc) |
910 | { |
911 | struct hns_ppe_cb *ppe_cb = hns_get_ppe_cb(handle); |
912 | |
913 | /* set the RSS Hash Key if specififed by the user */ |
914 | if (key) { |
915 | memcpy(ppe_cb->rss_key, key, HNS_PPEV2_RSS_KEY_SIZE); |
916 | hns_ppe_set_rss_key(ppe_cb, rss_key: ppe_cb->rss_key); |
917 | } |
918 | |
919 | if (indir) { |
920 | /* update the shadow RSS table with user specified qids */ |
921 | memcpy(ppe_cb->rss_indir_table, indir, |
922 | HNS_PPEV2_RSS_IND_TBL_SIZE * sizeof(*indir)); |
923 | |
924 | /* now update the hardware */ |
925 | hns_ppe_set_indir_table(ppe_cb, rss_tab: ppe_cb->rss_indir_table); |
926 | } |
927 | |
928 | return 0; |
929 | } |
930 | |
931 | static struct hnae_ae_ops hns_dsaf_ops = { |
932 | .get_handle = hns_ae_get_handle, |
933 | .put_handle = hns_ae_put_handle, |
934 | .init_queue = hns_ae_init_queue, |
935 | .fini_queue = hns_ae_fini_queue, |
936 | .start = hns_ae_start, |
937 | .stop = hns_ae_stop, |
938 | .reset = hns_ae_reset, |
939 | .toggle_ring_irq = hns_ae_toggle_ring_irq, |
940 | .get_status = hns_ae_get_link_status, |
941 | .get_info = hns_ae_get_mac_info, |
942 | .adjust_link = hns_ae_adjust_link, |
943 | .need_adjust_link = hns_ae_need_adjust_link, |
944 | .set_loopback = hns_ae_config_loopback, |
945 | .get_ring_bdnum_limit = hns_ae_get_ring_bdnum_limit, |
946 | .get_pauseparam = hns_ae_get_pauseparam, |
947 | .set_pauseparam = hns_ae_set_pauseparam, |
948 | .get_coalesce_usecs = hns_ae_get_coalesce_usecs, |
949 | .get_max_coalesced_frames = hns_ae_get_max_coalesced_frames, |
950 | .set_coalesce_usecs = hns_ae_set_coalesce_usecs, |
951 | .set_coalesce_frames = hns_ae_set_coalesce_frames, |
952 | .get_coalesce_range = hns_ae_get_coalesce_range, |
953 | .set_promisc_mode = hns_ae_set_promisc_mode, |
954 | .set_mac_addr = hns_ae_set_mac_address, |
955 | .add_uc_addr = hns_ae_add_uc_address, |
956 | .rm_uc_addr = hns_ae_rm_uc_address, |
957 | .set_mc_addr = hns_ae_set_multicast_one, |
958 | .clr_mc_addr = hns_ae_clr_multicast, |
959 | .set_mtu = hns_ae_set_mtu, |
960 | .update_stats = hns_ae_update_stats, |
961 | .set_tso_stats = hns_ae_set_tso_stats, |
962 | .get_stats = hns_ae_get_stats, |
963 | .get_strings = hns_ae_get_strings, |
964 | .get_sset_count = hns_ae_get_sset_count, |
965 | .update_led_status = hns_ae_update_led_status, |
966 | .set_led_id = hns_ae_cpld_set_led_id, |
967 | .get_regs = hns_ae_get_regs, |
968 | .get_regs_len = hns_ae_get_regs_len, |
969 | .get_rss_key_size = hns_ae_get_rss_key_size, |
970 | .get_rss_indir_size = hns_ae_get_rss_indir_size, |
971 | .get_rss = hns_ae_get_rss, |
972 | .set_rss = hns_ae_set_rss |
973 | }; |
974 | |
975 | int hns_dsaf_ae_init(struct dsaf_device *dsaf_dev) |
976 | { |
977 | struct hnae_ae_dev *ae_dev = &dsaf_dev->ae_dev; |
978 | static atomic_t id = ATOMIC_INIT(-1); |
979 | |
980 | switch (dsaf_dev->dsaf_ver) { |
981 | case AE_VERSION_1: |
982 | hns_dsaf_ops.toggle_ring_irq = hns_ae_toggle_ring_irq; |
983 | break; |
984 | case AE_VERSION_2: |
985 | hns_dsaf_ops.toggle_ring_irq = hns_aev2_toggle_ring_irq; |
986 | break; |
987 | default: |
988 | break; |
989 | } |
990 | |
991 | snprintf(buf: ae_dev->name, AE_NAME_SIZE, fmt: "%s%d" , DSAF_DEVICE_NAME, |
992 | (int)atomic_inc_return(v: &id)); |
993 | ae_dev->ops = &hns_dsaf_ops; |
994 | ae_dev->dev = dsaf_dev->dev; |
995 | |
996 | return hnae_ae_register(dev: ae_dev, THIS_MODULE); |
997 | } |
998 | |
999 | void hns_dsaf_ae_uninit(struct dsaf_device *dsaf_dev) |
1000 | { |
1001 | hnae_ae_unregister(dev: &dsaf_dev->ae_dev); |
1002 | } |
1003 | |