1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2014-2015 Hisilicon Limited. |
4 | */ |
5 | |
6 | #include <linux/acpi.h> |
7 | #include <linux/init.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/kernel.h> |
10 | #include <linux/mfd/syscon.h> |
11 | #include <linux/module.h> |
12 | #include <linux/netdevice.h> |
13 | #include <linux/of.h> |
14 | #include <linux/of_address.h> |
15 | #include <linux/of_mdio.h> |
16 | #include <linux/phy.h> |
17 | #include <linux/platform_device.h> |
18 | |
19 | #include "hns_dsaf_main.h" |
20 | #include "hns_dsaf_misc.h" |
21 | #include "hns_dsaf_rcb.h" |
22 | |
23 | #define MAC_EN_FLAG_V 0xada0328 |
24 | |
25 | static const u16 mac_phy_to_speed[] = { |
26 | [PHY_INTERFACE_MODE_MII] = MAC_SPEED_100, |
27 | [PHY_INTERFACE_MODE_GMII] = MAC_SPEED_1000, |
28 | [PHY_INTERFACE_MODE_SGMII] = MAC_SPEED_1000, |
29 | [PHY_INTERFACE_MODE_TBI] = MAC_SPEED_1000, |
30 | [PHY_INTERFACE_MODE_RMII] = MAC_SPEED_100, |
31 | [PHY_INTERFACE_MODE_RGMII] = MAC_SPEED_1000, |
32 | [PHY_INTERFACE_MODE_RGMII_ID] = MAC_SPEED_1000, |
33 | [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_SPEED_1000, |
34 | [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_SPEED_1000, |
35 | [PHY_INTERFACE_MODE_RTBI] = MAC_SPEED_1000, |
36 | [PHY_INTERFACE_MODE_XGMII] = MAC_SPEED_10000 |
37 | }; |
38 | |
39 | static const enum mac_mode g_mac_mode_100[] = { |
40 | [PHY_INTERFACE_MODE_MII] = MAC_MODE_MII_100, |
41 | [PHY_INTERFACE_MODE_RMII] = MAC_MODE_RMII_100 |
42 | }; |
43 | |
44 | static const enum mac_mode g_mac_mode_1000[] = { |
45 | [PHY_INTERFACE_MODE_GMII] = MAC_MODE_GMII_1000, |
46 | [PHY_INTERFACE_MODE_SGMII] = MAC_MODE_SGMII_1000, |
47 | [PHY_INTERFACE_MODE_TBI] = MAC_MODE_TBI_1000, |
48 | [PHY_INTERFACE_MODE_RGMII] = MAC_MODE_RGMII_1000, |
49 | [PHY_INTERFACE_MODE_RGMII_ID] = MAC_MODE_RGMII_1000, |
50 | [PHY_INTERFACE_MODE_RGMII_RXID] = MAC_MODE_RGMII_1000, |
51 | [PHY_INTERFACE_MODE_RGMII_TXID] = MAC_MODE_RGMII_1000, |
52 | [PHY_INTERFACE_MODE_RTBI] = MAC_MODE_RTBI_1000 |
53 | }; |
54 | |
55 | static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb) |
56 | { |
57 | switch (mac_cb->max_speed) { |
58 | case MAC_SPEED_100: |
59 | return g_mac_mode_100[mac_cb->phy_if]; |
60 | case MAC_SPEED_1000: |
61 | return g_mac_mode_1000[mac_cb->phy_if]; |
62 | case MAC_SPEED_10000: |
63 | return MAC_MODE_XGMII_10000; |
64 | default: |
65 | return MAC_MODE_MII_100; |
66 | } |
67 | } |
68 | |
69 | void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) |
70 | { |
71 | struct mac_driver *mac_ctrl_drv; |
72 | int ret, sfp_prsnt; |
73 | |
74 | mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
75 | |
76 | if (mac_ctrl_drv->get_link_status) |
77 | mac_ctrl_drv->get_link_status(mac_ctrl_drv, link_status); |
78 | else |
79 | *link_status = 0; |
80 | |
81 | if (mac_cb->media_type == HNAE_MEDIA_TYPE_FIBER) { |
82 | ret = mac_cb->dsaf_dev->misc_op->get_sfp_prsnt(mac_cb, |
83 | &sfp_prsnt); |
84 | if (!ret) |
85 | *link_status = *link_status && sfp_prsnt; |
86 | } |
87 | |
88 | mac_cb->link = *link_status; |
89 | } |
90 | |
91 | int hns_mac_get_port_info(struct hns_mac_cb *mac_cb, |
92 | u8 *auto_neg, u16 *speed, u8 *duplex) |
93 | { |
94 | struct mac_driver *mac_ctrl_drv; |
95 | struct mac_info info; |
96 | |
97 | mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
98 | |
99 | if (!mac_ctrl_drv->get_info) |
100 | return -ENODEV; |
101 | |
102 | mac_ctrl_drv->get_info(mac_ctrl_drv, &info); |
103 | if (auto_neg) |
104 | *auto_neg = info.auto_neg; |
105 | if (speed) |
106 | *speed = info.speed; |
107 | if (duplex) |
108 | *duplex = info.duplex; |
109 | |
110 | return 0; |
111 | } |
112 | |
113 | /** |
114 | *hns_mac_need_adjust_link - check is need change mac speed and duplex register |
115 | *@mac_cb: mac device |
116 | *@speed: phy device speed |
117 | *@duplex:phy device duplex |
118 | * |
119 | */ |
120 | bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex) |
121 | { |
122 | struct mac_driver *mac_ctrl_drv; |
123 | |
124 | mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac); |
125 | |
126 | if (mac_ctrl_drv->need_adjust_link) |
127 | return mac_ctrl_drv->need_adjust_link(mac_ctrl_drv, |
128 | (enum mac_speed)speed, duplex); |
129 | else |
130 | return true; |
131 | } |
132 | |
133 | void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex) |
134 | { |
135 | int ret; |
136 | struct mac_driver *mac_ctrl_drv; |
137 | |
138 | mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac); |
139 | |
140 | mac_cb->speed = speed; |
141 | mac_cb->half_duplex = !duplex; |
142 | |
143 | if (mac_ctrl_drv->adjust_link) { |
144 | ret = mac_ctrl_drv->adjust_link(mac_ctrl_drv, |
145 | (enum mac_speed)speed, duplex); |
146 | if (ret) { |
147 | dev_err(mac_cb->dev, |
148 | "adjust_link failed, %s mac%d ret = %#x!\n" , |
149 | mac_cb->dsaf_dev->ae_dev.name, |
150 | mac_cb->mac_id, ret); |
151 | return; |
152 | } |
153 | } |
154 | } |
155 | |
156 | /** |
157 | *hns_mac_get_inner_port_num - get mac table inner port number |
158 | *@mac_cb: mac device |
159 | *@vmid: vm id |
160 | *@port_num:port number |
161 | * |
162 | */ |
163 | int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num) |
164 | { |
165 | int q_num_per_vf, vf_num_per_port; |
166 | int vm_queue_id; |
167 | u8 tmp_port; |
168 | |
169 | if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) { |
170 | if (mac_cb->mac_id != DSAF_MAX_PORT_NUM) { |
171 | dev_err(mac_cb->dev, |
172 | "input invalid, %s mac%d vmid%d !\n" , |
173 | mac_cb->dsaf_dev->ae_dev.name, |
174 | mac_cb->mac_id, vmid); |
175 | return -EINVAL; |
176 | } |
177 | } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) { |
178 | if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM) { |
179 | dev_err(mac_cb->dev, |
180 | "input invalid, %s mac%d vmid%d!\n" , |
181 | mac_cb->dsaf_dev->ae_dev.name, |
182 | mac_cb->mac_id, vmid); |
183 | return -EINVAL; |
184 | } |
185 | } else { |
186 | dev_err(mac_cb->dev, "dsaf mode invalid, %s mac%d!\n" , |
187 | mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id); |
188 | return -EINVAL; |
189 | } |
190 | |
191 | if (vmid >= mac_cb->dsaf_dev->rcb_common[0]->max_vfn) { |
192 | dev_err(mac_cb->dev, "input invalid, %s mac%d vmid%d !\n" , |
193 | mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid); |
194 | return -EINVAL; |
195 | } |
196 | |
197 | q_num_per_vf = mac_cb->dsaf_dev->rcb_common[0]->max_q_per_vf; |
198 | vf_num_per_port = mac_cb->dsaf_dev->rcb_common[0]->max_vfn; |
199 | |
200 | vm_queue_id = vmid * q_num_per_vf + |
201 | vf_num_per_port * q_num_per_vf * mac_cb->mac_id; |
202 | |
203 | switch (mac_cb->dsaf_dev->dsaf_mode) { |
204 | case DSAF_MODE_ENABLE_FIX: |
205 | tmp_port = 0; |
206 | break; |
207 | case DSAF_MODE_DISABLE_FIX: |
208 | tmp_port = 0; |
209 | break; |
210 | case DSAF_MODE_ENABLE_0VM: |
211 | case DSAF_MODE_ENABLE_8VM: |
212 | case DSAF_MODE_ENABLE_16VM: |
213 | case DSAF_MODE_ENABLE_32VM: |
214 | case DSAF_MODE_ENABLE_128VM: |
215 | case DSAF_MODE_DISABLE_2PORT_8VM: |
216 | case DSAF_MODE_DISABLE_2PORT_16VM: |
217 | case DSAF_MODE_DISABLE_2PORT_64VM: |
218 | case DSAF_MODE_DISABLE_6PORT_0VM: |
219 | case DSAF_MODE_DISABLE_6PORT_2VM: |
220 | case DSAF_MODE_DISABLE_6PORT_4VM: |
221 | case DSAF_MODE_DISABLE_6PORT_16VM: |
222 | tmp_port = vm_queue_id; |
223 | break; |
224 | default: |
225 | dev_err(mac_cb->dev, "dsaf mode invalid, %s mac%d!\n" , |
226 | mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id); |
227 | return -EINVAL; |
228 | } |
229 | tmp_port += DSAF_BASE_INNER_PORT_NUM; |
230 | |
231 | *port_num = tmp_port; |
232 | |
233 | return 0; |
234 | } |
235 | |
236 | /** |
237 | *hns_mac_change_vf_addr - change vf mac address |
238 | *@mac_cb: mac device |
239 | *@vmid: vmid |
240 | *@addr:mac address |
241 | */ |
242 | int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, |
243 | u32 vmid, const char *addr) |
244 | { |
245 | int ret; |
246 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
247 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
248 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
249 | struct mac_entry_idx *old_entry; |
250 | |
251 | old_entry = &mac_cb->addr_entry_idx[vmid]; |
252 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
253 | memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); |
254 | mac_entry.in_vlan_id = old_entry->vlan_id; |
255 | mac_entry.in_port_num = mac_cb->mac_id; |
256 | ret = hns_mac_get_inner_port_num(mac_cb, vmid: (u8)vmid, |
257 | port_num: &mac_entry.port_num); |
258 | if (ret) |
259 | return ret; |
260 | |
261 | if ((old_entry->valid != 0) && |
262 | (memcmp(p: old_entry->addr, |
263 | q: addr, size: sizeof(mac_entry.addr)) != 0)) { |
264 | ret = hns_dsaf_del_mac_entry(dsaf_dev, |
265 | vlan_id: old_entry->vlan_id, |
266 | in_port_num: mac_cb->mac_id, |
267 | addr: old_entry->addr); |
268 | if (ret) |
269 | return ret; |
270 | } |
271 | |
272 | ret = hns_dsaf_set_mac_uc_entry(dsaf_dev, mac_entry: &mac_entry); |
273 | if (ret) |
274 | return ret; |
275 | } |
276 | |
277 | if ((mac_ctrl_drv->set_mac_addr) && (vmid == 0)) |
278 | mac_ctrl_drv->set_mac_addr(mac_cb->priv.mac, addr); |
279 | |
280 | memcpy(old_entry->addr, addr, sizeof(old_entry->addr)); |
281 | old_entry->valid = 1; |
282 | return 0; |
283 | } |
284 | |
285 | int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, |
286 | const unsigned char *addr) |
287 | { |
288 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
289 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
290 | int ret; |
291 | |
292 | if (HNS_DSAF_IS_DEBUG(dsaf_dev)) |
293 | return -ENOSPC; |
294 | |
295 | memset(&mac_entry, 0, sizeof(mac_entry)); |
296 | memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); |
297 | mac_entry.in_port_num = mac_cb->mac_id; |
298 | ret = hns_mac_get_inner_port_num(mac_cb, vmid: vf_id, port_num: &mac_entry.port_num); |
299 | if (ret) |
300 | return ret; |
301 | |
302 | return hns_dsaf_set_mac_uc_entry(dsaf_dev, mac_entry: &mac_entry); |
303 | } |
304 | |
305 | int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, |
306 | const unsigned char *addr) |
307 | { |
308 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
309 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
310 | int ret; |
311 | |
312 | if (HNS_DSAF_IS_DEBUG(dsaf_dev)) |
313 | return -ENOSPC; |
314 | |
315 | memset(&mac_entry, 0, sizeof(mac_entry)); |
316 | memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); |
317 | mac_entry.in_port_num = mac_cb->mac_id; |
318 | ret = hns_mac_get_inner_port_num(mac_cb, vmid: vf_id, port_num: &mac_entry.port_num); |
319 | if (ret) |
320 | return ret; |
321 | |
322 | return hns_dsaf_rm_mac_addr(dsaf_dev, mac_entry: &mac_entry); |
323 | } |
324 | |
325 | int hns_mac_set_multi(struct hns_mac_cb *mac_cb, |
326 | u32 port_num, char *addr, bool enable) |
327 | { |
328 | int ret; |
329 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
330 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
331 | |
332 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev) && addr) { |
333 | memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); |
334 | mac_entry.in_vlan_id = 0;/*vlan_id;*/ |
335 | mac_entry.in_port_num = mac_cb->mac_id; |
336 | mac_entry.port_num = port_num; |
337 | |
338 | if (!enable) |
339 | ret = hns_dsaf_del_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
340 | else |
341 | ret = hns_dsaf_add_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
342 | if (ret) { |
343 | dev_err(dsaf_dev->dev, |
344 | "set mac mc port failed, %s mac%d ret = %#x!\n" , |
345 | mac_cb->dsaf_dev->ae_dev.name, |
346 | mac_cb->mac_id, ret); |
347 | return ret; |
348 | } |
349 | } |
350 | |
351 | return 0; |
352 | } |
353 | |
354 | int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn) |
355 | { |
356 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
357 | u8 port_num; |
358 | int ret = hns_mac_get_inner_port_num(mac_cb, vmid: vfn, port_num: &port_num); |
359 | |
360 | if (ret) |
361 | return ret; |
362 | |
363 | return hns_dsaf_clr_mac_mc_port(dsaf_dev, mac_id: mac_cb->mac_id, port_num); |
364 | } |
365 | |
366 | static void hns_mac_param_get(struct mac_params *param, |
367 | struct hns_mac_cb *mac_cb) |
368 | { |
369 | param->vaddr = mac_cb->vaddr; |
370 | param->mac_mode = hns_get_enet_interface(mac_cb); |
371 | ether_addr_copy(dst: param->addr, src: mac_cb->addr_entry_idx[0].addr); |
372 | param->mac_id = mac_cb->mac_id; |
373 | param->dev = mac_cb->dev; |
374 | } |
375 | |
376 | /** |
377 | * hns_mac_port_config_bc_en - set broadcast rx&tx enable |
378 | * @mac_cb: mac device |
379 | * @port_num: queue number |
380 | * @vlan_id: vlan id` |
381 | * @enable: enable |
382 | * return 0 - success , negative --fail |
383 | */ |
384 | static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, |
385 | u32 port_num, u16 vlan_id, bool enable) |
386 | { |
387 | int ret; |
388 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
389 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
390 | |
391 | /* directy return ok in debug network mode */ |
392 | if (mac_cb->mac_type == HNAE_PORT_DEBUG) |
393 | return 0; |
394 | |
395 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
396 | eth_broadcast_addr(addr: mac_entry.addr); |
397 | mac_entry.in_vlan_id = vlan_id; |
398 | mac_entry.in_port_num = mac_cb->mac_id; |
399 | mac_entry.port_num = port_num; |
400 | |
401 | if (!enable) |
402 | ret = hns_dsaf_del_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
403 | else |
404 | ret = hns_dsaf_add_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
405 | return ret; |
406 | } |
407 | |
408 | return 0; |
409 | } |
410 | |
411 | /** |
412 | * hns_mac_vm_config_bc_en - set broadcast rx&tx enable |
413 | * @mac_cb: mac device |
414 | * @vmid: vm id |
415 | * @enable: enable |
416 | * return 0 - success , negative --fail |
417 | */ |
418 | int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) |
419 | { |
420 | int ret; |
421 | struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; |
422 | u8 port_num; |
423 | struct mac_entry_idx *uc_mac_entry; |
424 | struct dsaf_drv_mac_single_dest_entry mac_entry; |
425 | |
426 | if (mac_cb->mac_type == HNAE_PORT_DEBUG) |
427 | return 0; |
428 | |
429 | uc_mac_entry = &mac_cb->addr_entry_idx[vmid]; |
430 | |
431 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { |
432 | eth_broadcast_addr(addr: mac_entry.addr); |
433 | mac_entry.in_vlan_id = uc_mac_entry->vlan_id; |
434 | mac_entry.in_port_num = mac_cb->mac_id; |
435 | ret = hns_mac_get_inner_port_num(mac_cb, vmid, port_num: &port_num); |
436 | if (ret) |
437 | return ret; |
438 | mac_entry.port_num = port_num; |
439 | |
440 | if (!enable) |
441 | ret = hns_dsaf_del_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
442 | else |
443 | ret = hns_dsaf_add_mac_mc_port(dsaf_dev, mac_entry: &mac_entry); |
444 | return ret; |
445 | } |
446 | |
447 | return 0; |
448 | } |
449 | |
450 | int hns_mac_wait_fifo_clean(struct hns_mac_cb *mac_cb) |
451 | { |
452 | struct mac_driver *drv = hns_mac_get_drv(mac_cb); |
453 | |
454 | if (drv->wait_fifo_clean) |
455 | return drv->wait_fifo_clean(drv); |
456 | |
457 | return 0; |
458 | } |
459 | |
460 | void hns_mac_reset(struct hns_mac_cb *mac_cb) |
461 | { |
462 | struct mac_driver *drv = hns_mac_get_drv(mac_cb); |
463 | bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); |
464 | |
465 | drv->mac_init(drv); |
466 | |
467 | if (drv->config_max_frame_length) |
468 | drv->config_max_frame_length(drv, mac_cb->max_frm); |
469 | |
470 | if (drv->set_tx_auto_pause_frames) |
471 | drv->set_tx_auto_pause_frames(drv, mac_cb->tx_pause_frm_time); |
472 | |
473 | if (drv->set_an_mode) |
474 | drv->set_an_mode(drv, 1); |
475 | |
476 | if (drv->mac_pausefrm_cfg) { |
477 | if (mac_cb->mac_type == HNAE_PORT_DEBUG) |
478 | drv->mac_pausefrm_cfg(drv, !is_ver1, !is_ver1); |
479 | else /* mac rx must disable, dsaf pfc close instead of it*/ |
480 | drv->mac_pausefrm_cfg(drv, 0, 1); |
481 | } |
482 | } |
483 | |
484 | int hns_mac_set_mtu(struct hns_mac_cb *mac_cb, u32 new_mtu, u32 buf_size) |
485 | { |
486 | struct mac_driver *drv = hns_mac_get_drv(mac_cb); |
487 | u32 new_frm = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; |
488 | |
489 | if (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size) |
490 | return -EINVAL; |
491 | |
492 | if (!drv->config_max_frame_length) |
493 | return -ECHILD; |
494 | |
495 | /* adjust max frame to be at least the size of a standard frame */ |
496 | if (new_frm < (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN)) |
497 | new_frm = (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN); |
498 | |
499 | drv->config_max_frame_length(drv, new_frm); |
500 | |
501 | mac_cb->max_frm = new_frm; |
502 | |
503 | return 0; |
504 | } |
505 | |
506 | void hns_mac_start(struct hns_mac_cb *mac_cb) |
507 | { |
508 | struct mac_driver *mac_drv = hns_mac_get_drv(mac_cb); |
509 | |
510 | /* for virt */ |
511 | if (mac_drv->mac_en_flg == MAC_EN_FLAG_V) { |
512 | /*plus 1 when the virtual mac has been enabled */ |
513 | mac_drv->virt_dev_num += 1; |
514 | return; |
515 | } |
516 | |
517 | if (mac_drv->mac_enable) { |
518 | mac_drv->mac_enable(mac_cb->priv.mac, MAC_COMM_MODE_RX_AND_TX); |
519 | mac_drv->mac_en_flg = MAC_EN_FLAG_V; |
520 | } |
521 | } |
522 | |
523 | void hns_mac_stop(struct hns_mac_cb *mac_cb) |
524 | { |
525 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
526 | |
527 | /*modified for virtualization */ |
528 | if (mac_ctrl_drv->virt_dev_num > 0) { |
529 | mac_ctrl_drv->virt_dev_num -= 1; |
530 | if (mac_ctrl_drv->virt_dev_num > 0) |
531 | return; |
532 | } |
533 | |
534 | if (mac_ctrl_drv->mac_disable) |
535 | mac_ctrl_drv->mac_disable(mac_cb->priv.mac, |
536 | MAC_COMM_MODE_RX_AND_TX); |
537 | |
538 | mac_ctrl_drv->mac_en_flg = 0; |
539 | mac_cb->link = 0; |
540 | mac_cb->dsaf_dev->misc_op->cpld_reset_led(mac_cb); |
541 | } |
542 | |
543 | /** |
544 | * hns_mac_get_autoneg - get auto autonegotiation |
545 | * @mac_cb: mac control block |
546 | * @auto_neg: output pointer to autoneg result |
547 | * return 0 - success , negative --fail |
548 | */ |
549 | void hns_mac_get_autoneg(struct hns_mac_cb *mac_cb, u32 *auto_neg) |
550 | { |
551 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
552 | |
553 | if (mac_ctrl_drv->autoneg_stat) |
554 | mac_ctrl_drv->autoneg_stat(mac_ctrl_drv, auto_neg); |
555 | else |
556 | *auto_neg = 0; |
557 | } |
558 | |
559 | /** |
560 | * hns_mac_get_pauseparam - set rx & tx pause parameter |
561 | * @mac_cb: mac control block |
562 | * @rx_en: rx enable status |
563 | * @tx_en: tx enable status |
564 | * return 0 - success , negative --fail |
565 | */ |
566 | void hns_mac_get_pauseparam(struct hns_mac_cb *mac_cb, u32 *rx_en, u32 *tx_en) |
567 | { |
568 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
569 | |
570 | if (mac_ctrl_drv->get_pause_enable) { |
571 | mac_ctrl_drv->get_pause_enable(mac_ctrl_drv, rx_en, tx_en); |
572 | } else { |
573 | *rx_en = 0; |
574 | *tx_en = 0; |
575 | } |
576 | } |
577 | |
578 | /** |
579 | * hns_mac_set_autoneg - set auto autonegotiation |
580 | * @mac_cb: mac control block |
581 | * @enable: enable or not |
582 | * return 0 - success , negative --fail |
583 | */ |
584 | int hns_mac_set_autoneg(struct hns_mac_cb *mac_cb, u8 enable) |
585 | { |
586 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
587 | |
588 | if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII && enable) { |
589 | dev_err(mac_cb->dev, "enabling autoneg is not allowed!\n" ); |
590 | return -ENOTSUPP; |
591 | } |
592 | |
593 | if (mac_ctrl_drv->set_an_mode) |
594 | mac_ctrl_drv->set_an_mode(mac_ctrl_drv, enable); |
595 | |
596 | return 0; |
597 | } |
598 | |
599 | /** |
600 | * hns_mac_set_pauseparam - set rx & tx pause parameter |
601 | * @mac_cb: mac control block |
602 | * @rx_en: rx enable or not |
603 | * @tx_en: tx enable or not |
604 | * return 0 - success , negative --fail |
605 | */ |
606 | int hns_mac_set_pauseparam(struct hns_mac_cb *mac_cb, u32 rx_en, u32 tx_en) |
607 | { |
608 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
609 | bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); |
610 | |
611 | if (mac_cb->mac_type == HNAE_PORT_DEBUG) { |
612 | if (is_ver1 && (tx_en || rx_en)) { |
613 | dev_err(mac_cb->dev, "macv1 can't enable tx/rx_pause!\n" ); |
614 | return -EINVAL; |
615 | } |
616 | } |
617 | |
618 | if (mac_ctrl_drv->mac_pausefrm_cfg) |
619 | mac_ctrl_drv->mac_pausefrm_cfg(mac_ctrl_drv, rx_en, tx_en); |
620 | |
621 | return 0; |
622 | } |
623 | |
624 | /** |
625 | * hns_mac_init_ex - mac init |
626 | * @mac_cb: mac control block |
627 | * return 0 - success , negative --fail |
628 | */ |
629 | static int hns_mac_init_ex(struct hns_mac_cb *mac_cb) |
630 | { |
631 | int ret; |
632 | struct mac_params param; |
633 | struct mac_driver *drv; |
634 | |
635 | hns_dsaf_fix_mac_mode(mac_cb); |
636 | |
637 | memset(¶m, 0, sizeof(struct mac_params)); |
638 | hns_mac_param_get(param: ¶m, mac_cb); |
639 | |
640 | if (MAC_SPEED_FROM_MODE(param.mac_mode) < MAC_SPEED_10000) |
641 | drv = (struct mac_driver *)hns_gmac_config(mac_cb, mac_param: ¶m); |
642 | else |
643 | drv = (struct mac_driver *)hns_xgmac_config(mac_cb, mac_param: ¶m); |
644 | |
645 | if (!drv) |
646 | return -ENOMEM; |
647 | |
648 | mac_cb->priv.mac = (void *)drv; |
649 | hns_mac_reset(mac_cb); |
650 | |
651 | hns_mac_adjust_link(mac_cb, speed: mac_cb->speed, duplex: !mac_cb->half_duplex); |
652 | |
653 | ret = hns_mac_port_config_bc_en(mac_cb, port_num: mac_cb->mac_id, vlan_id: 0, enable: true); |
654 | if (ret) |
655 | goto free_mac_drv; |
656 | |
657 | return 0; |
658 | |
659 | free_mac_drv: |
660 | drv->mac_free(mac_cb->priv.mac); |
661 | mac_cb->priv.mac = NULL; |
662 | |
663 | return ret; |
664 | } |
665 | |
666 | static int |
667 | hns_mac_phy_parse_addr(struct device *dev, struct fwnode_handle *fwnode) |
668 | { |
669 | u32 addr; |
670 | int ret; |
671 | |
672 | ret = fwnode_property_read_u32(fwnode, propname: "phy-addr" , val: &addr); |
673 | if (ret) { |
674 | dev_err(dev, "has invalid PHY address ret:%d\n" , ret); |
675 | return ret; |
676 | } |
677 | |
678 | if (addr >= PHY_MAX_ADDR) { |
679 | dev_err(dev, "PHY address %i is too large\n" , addr); |
680 | return -EINVAL; |
681 | } |
682 | |
683 | return addr; |
684 | } |
685 | |
686 | static int |
687 | hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb, |
688 | u32 addr) |
689 | { |
690 | struct phy_device *phy; |
691 | const char *phy_type; |
692 | bool is_c45; |
693 | int rc; |
694 | |
695 | rc = fwnode_property_read_string(fwnode: mac_cb->fw_port, |
696 | propname: "phy-mode" , val: &phy_type); |
697 | if (rc < 0) |
698 | return rc; |
699 | |
700 | if (!strcmp(phy_type, phy_modes(interface: PHY_INTERFACE_MODE_XGMII))) |
701 | is_c45 = true; |
702 | else if (!strcmp(phy_type, phy_modes(interface: PHY_INTERFACE_MODE_SGMII))) |
703 | is_c45 = false; |
704 | else |
705 | return -ENODATA; |
706 | |
707 | phy = get_phy_device(bus: mdio, addr, is_c45); |
708 | if (!phy || IS_ERR(ptr: phy)) |
709 | return -EIO; |
710 | |
711 | phy->irq = mdio->irq[addr]; |
712 | |
713 | /* All data is now stored in the phy struct; |
714 | * register it |
715 | */ |
716 | rc = phy_device_register(phy); |
717 | if (rc) { |
718 | phy_device_free(phydev: phy); |
719 | dev_err(&mdio->dev, "registered phy fail at address %i\n" , |
720 | addr); |
721 | return -ENODEV; |
722 | } |
723 | |
724 | mac_cb->phy_dev = phy; |
725 | |
726 | dev_dbg(&mdio->dev, "registered phy at address %i\n" , addr); |
727 | |
728 | return 0; |
729 | } |
730 | |
731 | static int hns_mac_register_phy(struct hns_mac_cb *mac_cb) |
732 | { |
733 | struct fwnode_reference_args args; |
734 | struct platform_device *pdev; |
735 | struct mii_bus *mii_bus; |
736 | int rc; |
737 | int addr; |
738 | |
739 | /* Loop over the child nodes and register a phy_device for each one */ |
740 | if (!to_acpi_device_node(mac_cb->fw_port)) |
741 | return -ENODEV; |
742 | |
743 | rc = acpi_node_get_property_reference( |
744 | fwnode: mac_cb->fw_port, name: "mdio-node" , index: 0, args: &args); |
745 | if (rc) |
746 | return rc; |
747 | if (!is_acpi_device_node(fwnode: args.fwnode)) |
748 | return -EINVAL; |
749 | |
750 | addr = hns_mac_phy_parse_addr(dev: mac_cb->dev, fwnode: mac_cb->fw_port); |
751 | if (addr < 0) |
752 | return addr; |
753 | |
754 | /* dev address in adev */ |
755 | pdev = hns_dsaf_find_platform_device(fwnode: args.fwnode); |
756 | if (!pdev) { |
757 | dev_err(mac_cb->dev, "mac%d mdio pdev is NULL\n" , |
758 | mac_cb->mac_id); |
759 | return -EINVAL; |
760 | } |
761 | |
762 | mii_bus = platform_get_drvdata(pdev); |
763 | if (!mii_bus) { |
764 | dev_err(mac_cb->dev, |
765 | "mac%d mdio is NULL, dsaf will probe again later\n" , |
766 | mac_cb->mac_id); |
767 | return -EPROBE_DEFER; |
768 | } |
769 | |
770 | rc = hns_mac_register_phydev(mdio: mii_bus, mac_cb, addr); |
771 | if (!rc) |
772 | dev_dbg(mac_cb->dev, "mac%d register phy addr:%d\n" , |
773 | mac_cb->mac_id, addr); |
774 | |
775 | return rc; |
776 | } |
777 | |
778 | static void hns_mac_remove_phydev(struct hns_mac_cb *mac_cb) |
779 | { |
780 | if (!to_acpi_device_node(mac_cb->fw_port) || !mac_cb->phy_dev) |
781 | return; |
782 | |
783 | phy_device_remove(phydev: mac_cb->phy_dev); |
784 | phy_device_free(phydev: mac_cb->phy_dev); |
785 | |
786 | mac_cb->phy_dev = NULL; |
787 | } |
788 | |
789 | #define MAC_MEDIA_TYPE_MAX_LEN 16 |
790 | |
791 | static const struct { |
792 | enum hnae_media_type value; |
793 | const char *name; |
794 | } media_type_defs[] = { |
795 | {HNAE_MEDIA_TYPE_UNKNOWN, "unknown" }, |
796 | {HNAE_MEDIA_TYPE_FIBER, "fiber" }, |
797 | {HNAE_MEDIA_TYPE_COPPER, "copper" }, |
798 | {HNAE_MEDIA_TYPE_BACKPLANE, "backplane" }, |
799 | }; |
800 | |
801 | /** |
802 | *hns_mac_get_info - get mac information from device node |
803 | *@mac_cb: mac device |
804 | * return: 0 --success, negative --fail |
805 | */ |
806 | static int hns_mac_get_info(struct hns_mac_cb *mac_cb) |
807 | { |
808 | struct device_node *np; |
809 | struct regmap *syscon; |
810 | struct of_phandle_args cpld_args; |
811 | const char *media_type; |
812 | u32 i; |
813 | u32 ret; |
814 | |
815 | mac_cb->link = false; |
816 | mac_cb->half_duplex = false; |
817 | mac_cb->media_type = HNAE_MEDIA_TYPE_UNKNOWN; |
818 | mac_cb->speed = mac_phy_to_speed[mac_cb->phy_if]; |
819 | mac_cb->max_speed = mac_cb->speed; |
820 | |
821 | if (mac_cb->phy_if == PHY_INTERFACE_MODE_SGMII) { |
822 | mac_cb->if_support = MAC_GMAC_SUPPORTED; |
823 | mac_cb->if_support |= SUPPORTED_1000baseT_Full; |
824 | } else if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII) { |
825 | mac_cb->if_support = SUPPORTED_10000baseR_FEC; |
826 | mac_cb->if_support |= SUPPORTED_10000baseKR_Full; |
827 | } |
828 | |
829 | mac_cb->max_frm = MAC_DEFAULT_MTU; |
830 | mac_cb->tx_pause_frm_time = MAC_DEFAULT_PAUSE_TIME; |
831 | mac_cb->port_rst_off = mac_cb->mac_id; |
832 | mac_cb->port_mode_off = 0; |
833 | |
834 | /* if the dsaf node doesn't contain a port subnode, get phy-handle |
835 | * from dsaf node |
836 | */ |
837 | if (!mac_cb->fw_port) { |
838 | np = of_parse_phandle(np: mac_cb->dev->of_node, phandle_name: "phy-handle" , |
839 | index: mac_cb->mac_id); |
840 | mac_cb->phy_dev = of_phy_find_device(phy_np: np); |
841 | if (mac_cb->phy_dev) { |
842 | /* refcount is held by of_phy_find_device() |
843 | * if the phy_dev is found |
844 | */ |
845 | put_device(dev: &mac_cb->phy_dev->mdio.dev); |
846 | |
847 | dev_dbg(mac_cb->dev, "mac%d phy_node: %pOFn\n" , |
848 | mac_cb->mac_id, np); |
849 | } |
850 | of_node_put(node: np); |
851 | |
852 | return 0; |
853 | } |
854 | |
855 | if (is_of_node(fwnode: mac_cb->fw_port)) { |
856 | /* parse property from port subnode in dsaf */ |
857 | np = of_parse_phandle(to_of_node(mac_cb->fw_port), |
858 | phandle_name: "phy-handle" , index: 0); |
859 | mac_cb->phy_dev = of_phy_find_device(phy_np: np); |
860 | if (mac_cb->phy_dev) { |
861 | /* refcount is held by of_phy_find_device() |
862 | * if the phy_dev is found |
863 | */ |
864 | put_device(dev: &mac_cb->phy_dev->mdio.dev); |
865 | dev_dbg(mac_cb->dev, "mac%d phy_node: %pOFn\n" , |
866 | mac_cb->mac_id, np); |
867 | } |
868 | of_node_put(node: np); |
869 | |
870 | np = of_parse_phandle(to_of_node(mac_cb->fw_port), |
871 | phandle_name: "serdes-syscon" , index: 0); |
872 | syscon = syscon_node_to_regmap(np); |
873 | of_node_put(node: np); |
874 | if (IS_ERR_OR_NULL(ptr: syscon)) { |
875 | dev_err(mac_cb->dev, "serdes-syscon is needed!\n" ); |
876 | return -EINVAL; |
877 | } |
878 | mac_cb->serdes_ctrl = syscon; |
879 | |
880 | ret = fwnode_property_read_u32(fwnode: mac_cb->fw_port, |
881 | propname: "port-rst-offset" , |
882 | val: &mac_cb->port_rst_off); |
883 | if (ret) { |
884 | dev_dbg(mac_cb->dev, |
885 | "mac%d port-rst-offset not found, use default value.\n" , |
886 | mac_cb->mac_id); |
887 | } |
888 | |
889 | ret = fwnode_property_read_u32(fwnode: mac_cb->fw_port, |
890 | propname: "port-mode-offset" , |
891 | val: &mac_cb->port_mode_off); |
892 | if (ret) { |
893 | dev_dbg(mac_cb->dev, |
894 | "mac%d port-mode-offset not found, use default value.\n" , |
895 | mac_cb->mac_id); |
896 | } |
897 | |
898 | ret = of_parse_phandle_with_fixed_args( |
899 | to_of_node(mac_cb->fw_port), list_name: "cpld-syscon" , cell_count: 1, index: 0, |
900 | out_args: &cpld_args); |
901 | if (ret) { |
902 | dev_dbg(mac_cb->dev, "mac%d no cpld-syscon found.\n" , |
903 | mac_cb->mac_id); |
904 | mac_cb->cpld_ctrl = NULL; |
905 | } else { |
906 | syscon = syscon_node_to_regmap(np: cpld_args.np); |
907 | if (IS_ERR_OR_NULL(ptr: syscon)) { |
908 | dev_dbg(mac_cb->dev, "no cpld-syscon found!\n" ); |
909 | mac_cb->cpld_ctrl = NULL; |
910 | } else { |
911 | mac_cb->cpld_ctrl = syscon; |
912 | mac_cb->cpld_ctrl_reg = cpld_args.args[0]; |
913 | } |
914 | } |
915 | } else if (is_acpi_node(fwnode: mac_cb->fw_port)) { |
916 | ret = hns_mac_register_phy(mac_cb); |
917 | /* Mac can work well if there is phy or not.If the port don't |
918 | * connect with phy, the return value will be ignored. Only |
919 | * when there is phy but can't find mdio bus, the return value |
920 | * will be handled. |
921 | */ |
922 | if (ret == -EPROBE_DEFER) |
923 | return ret; |
924 | } else { |
925 | dev_err(mac_cb->dev, "mac%d cannot find phy node\n" , |
926 | mac_cb->mac_id); |
927 | } |
928 | |
929 | if (!fwnode_property_read_string(fwnode: mac_cb->fw_port, propname: "media-type" , |
930 | val: &media_type)) { |
931 | for (i = 0; i < ARRAY_SIZE(media_type_defs); i++) { |
932 | if (!strncmp(media_type_defs[i].name, media_type, |
933 | MAC_MEDIA_TYPE_MAX_LEN)) { |
934 | mac_cb->media_type = media_type_defs[i].value; |
935 | break; |
936 | } |
937 | } |
938 | } |
939 | |
940 | if (fwnode_property_read_u8_array(fwnode: mac_cb->fw_port, propname: "mc-mac-mask" , |
941 | val: mac_cb->mc_mask, ETH_ALEN)) { |
942 | dev_warn(mac_cb->dev, |
943 | "no mc-mac-mask property, set to default value.\n" ); |
944 | eth_broadcast_addr(addr: mac_cb->mc_mask); |
945 | } |
946 | |
947 | return 0; |
948 | } |
949 | |
950 | /** |
951 | * hns_mac_get_mode - get mac mode |
952 | * @phy_if: phy interface |
953 | * return 0 - gmac, 1 - xgmac , negative --fail |
954 | */ |
955 | static int hns_mac_get_mode(phy_interface_t phy_if) |
956 | { |
957 | switch (phy_if) { |
958 | case PHY_INTERFACE_MODE_SGMII: |
959 | return MAC_GMAC_IDX; |
960 | case PHY_INTERFACE_MODE_XGMII: |
961 | return MAC_XGMAC_IDX; |
962 | default: |
963 | return -EINVAL; |
964 | } |
965 | } |
966 | |
967 | static u8 __iomem * |
968 | hns_mac_get_vaddr(struct dsaf_device *dsaf_dev, |
969 | struct hns_mac_cb *mac_cb, u32 mac_mode_idx) |
970 | { |
971 | u8 __iomem *base = dsaf_dev->io_base; |
972 | int mac_id = mac_cb->mac_id; |
973 | |
974 | if (mac_cb->mac_type == HNAE_PORT_SERVICE) |
975 | return base + 0x40000 + mac_id * 0x4000 - |
976 | mac_mode_idx * 0x20000; |
977 | else |
978 | return dsaf_dev->ppe_base + 0x1000; |
979 | } |
980 | |
981 | /** |
982 | * hns_mac_get_cfg - get mac cfg from dtb or acpi table |
983 | * @dsaf_dev: dsa fabric device struct pointer |
984 | * @mac_cb: mac control block |
985 | * return 0 - success , negative --fail |
986 | */ |
987 | static int |
988 | hns_mac_get_cfg(struct dsaf_device *dsaf_dev, struct hns_mac_cb *mac_cb) |
989 | { |
990 | int ret; |
991 | u32 mac_mode_idx; |
992 | |
993 | mac_cb->dsaf_dev = dsaf_dev; |
994 | mac_cb->dev = dsaf_dev->dev; |
995 | |
996 | mac_cb->sys_ctl_vaddr = dsaf_dev->sc_base; |
997 | mac_cb->serdes_vaddr = dsaf_dev->sds_base; |
998 | |
999 | mac_cb->sfp_prsnt = 0; |
1000 | mac_cb->txpkt_for_led = 0; |
1001 | mac_cb->rxpkt_for_led = 0; |
1002 | |
1003 | if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) |
1004 | mac_cb->mac_type = HNAE_PORT_SERVICE; |
1005 | else |
1006 | mac_cb->mac_type = HNAE_PORT_DEBUG; |
1007 | |
1008 | mac_cb->phy_if = dsaf_dev->misc_op->get_phy_if(mac_cb); |
1009 | |
1010 | ret = hns_mac_get_mode(phy_if: mac_cb->phy_if); |
1011 | if (ret < 0) { |
1012 | dev_err(dsaf_dev->dev, |
1013 | "hns_mac_get_mode failed, mac%d ret = %#x!\n" , |
1014 | mac_cb->mac_id, ret); |
1015 | return ret; |
1016 | } |
1017 | mac_mode_idx = (u32)ret; |
1018 | |
1019 | ret = hns_mac_get_info(mac_cb); |
1020 | if (ret) |
1021 | return ret; |
1022 | |
1023 | mac_cb->dsaf_dev->misc_op->cpld_reset_led(mac_cb); |
1024 | mac_cb->vaddr = hns_mac_get_vaddr(dsaf_dev, mac_cb, mac_mode_idx); |
1025 | |
1026 | return 0; |
1027 | } |
1028 | |
1029 | static int hns_mac_get_max_port_num(struct dsaf_device *dsaf_dev) |
1030 | { |
1031 | if (HNS_DSAF_IS_DEBUG(dsaf_dev)) |
1032 | return 1; |
1033 | else |
1034 | return DSAF_MAX_PORT_NUM; |
1035 | } |
1036 | |
1037 | void hns_mac_enable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode) |
1038 | { |
1039 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1040 | |
1041 | mac_ctrl_drv->mac_enable(mac_cb->priv.mac, mode); |
1042 | } |
1043 | |
1044 | void hns_mac_disable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode) |
1045 | { |
1046 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1047 | |
1048 | mac_ctrl_drv->mac_disable(mac_cb->priv.mac, mode); |
1049 | } |
1050 | |
1051 | /** |
1052 | * hns_mac_init - init mac |
1053 | * @dsaf_dev: dsa fabric device struct pointer |
1054 | * return 0 - success , negative --fail |
1055 | */ |
1056 | int hns_mac_init(struct dsaf_device *dsaf_dev) |
1057 | { |
1058 | bool found = false; |
1059 | int ret; |
1060 | u32 port_id; |
1061 | int max_port_num = hns_mac_get_max_port_num(dsaf_dev); |
1062 | struct hns_mac_cb *mac_cb; |
1063 | struct fwnode_handle *child; |
1064 | |
1065 | device_for_each_child_node(dsaf_dev->dev, child) { |
1066 | ret = fwnode_property_read_u32(fwnode: child, propname: "reg" , val: &port_id); |
1067 | if (ret) { |
1068 | fwnode_handle_put(fwnode: child); |
1069 | dev_err(dsaf_dev->dev, |
1070 | "get reg fail, ret=%d!\n" , ret); |
1071 | return ret; |
1072 | } |
1073 | if (port_id >= max_port_num) { |
1074 | fwnode_handle_put(fwnode: child); |
1075 | dev_err(dsaf_dev->dev, |
1076 | "reg(%u) out of range!\n" , port_id); |
1077 | return -EINVAL; |
1078 | } |
1079 | mac_cb = devm_kzalloc(dev: dsaf_dev->dev, size: sizeof(*mac_cb), |
1080 | GFP_KERNEL); |
1081 | if (!mac_cb) { |
1082 | fwnode_handle_put(fwnode: child); |
1083 | return -ENOMEM; |
1084 | } |
1085 | mac_cb->fw_port = child; |
1086 | mac_cb->mac_id = (u8)port_id; |
1087 | dsaf_dev->mac_cb[port_id] = mac_cb; |
1088 | found = true; |
1089 | } |
1090 | |
1091 | /* if don't get any port subnode from dsaf node |
1092 | * will init all port then, this is compatible with the old dts |
1093 | */ |
1094 | if (!found) { |
1095 | for (port_id = 0; port_id < max_port_num; port_id++) { |
1096 | mac_cb = devm_kzalloc(dev: dsaf_dev->dev, size: sizeof(*mac_cb), |
1097 | GFP_KERNEL); |
1098 | if (!mac_cb) |
1099 | return -ENOMEM; |
1100 | |
1101 | mac_cb->mac_id = port_id; |
1102 | dsaf_dev->mac_cb[port_id] = mac_cb; |
1103 | } |
1104 | } |
1105 | |
1106 | /* init mac_cb for all port */ |
1107 | for (port_id = 0; port_id < max_port_num; port_id++) { |
1108 | mac_cb = dsaf_dev->mac_cb[port_id]; |
1109 | if (!mac_cb) |
1110 | continue; |
1111 | |
1112 | ret = hns_mac_get_cfg(dsaf_dev, mac_cb); |
1113 | if (ret) |
1114 | return ret; |
1115 | |
1116 | ret = hns_mac_init_ex(mac_cb); |
1117 | if (ret) |
1118 | return ret; |
1119 | } |
1120 | |
1121 | return 0; |
1122 | } |
1123 | |
1124 | void hns_mac_uninit(struct dsaf_device *dsaf_dev) |
1125 | { |
1126 | int i; |
1127 | int max_port_num = hns_mac_get_max_port_num(dsaf_dev); |
1128 | |
1129 | for (i = 0; i < max_port_num; i++) { |
1130 | if (!dsaf_dev->mac_cb[i]) |
1131 | continue; |
1132 | |
1133 | dsaf_dev->misc_op->cpld_reset_led(dsaf_dev->mac_cb[i]); |
1134 | hns_mac_remove_phydev(mac_cb: dsaf_dev->mac_cb[i]); |
1135 | dsaf_dev->mac_cb[i] = NULL; |
1136 | } |
1137 | } |
1138 | |
1139 | int hns_mac_config_mac_loopback(struct hns_mac_cb *mac_cb, |
1140 | enum hnae_loop loop, int en) |
1141 | { |
1142 | int ret; |
1143 | struct mac_driver *drv = hns_mac_get_drv(mac_cb); |
1144 | |
1145 | if (drv->config_loopback) |
1146 | ret = drv->config_loopback(drv, loop, en); |
1147 | else |
1148 | ret = -ENOTSUPP; |
1149 | |
1150 | return ret; |
1151 | } |
1152 | |
1153 | void hns_mac_update_stats(struct hns_mac_cb *mac_cb) |
1154 | { |
1155 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1156 | |
1157 | mac_ctrl_drv->update_stats(mac_ctrl_drv); |
1158 | } |
1159 | |
1160 | void hns_mac_get_stats(struct hns_mac_cb *mac_cb, u64 *data) |
1161 | { |
1162 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1163 | |
1164 | mac_ctrl_drv->get_ethtool_stats(mac_ctrl_drv, data); |
1165 | } |
1166 | |
1167 | void hns_mac_get_strings(struct hns_mac_cb *mac_cb, |
1168 | int stringset, u8 *data) |
1169 | { |
1170 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1171 | |
1172 | mac_ctrl_drv->get_strings(stringset, data); |
1173 | } |
1174 | |
1175 | int hns_mac_get_sset_count(struct hns_mac_cb *mac_cb, int stringset) |
1176 | { |
1177 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1178 | |
1179 | return mac_ctrl_drv->get_sset_count(stringset); |
1180 | } |
1181 | |
1182 | void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en) |
1183 | { |
1184 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1185 | |
1186 | hns_dsaf_set_promisc_tcam(dsaf_dev: mac_cb->dsaf_dev, port: mac_cb->mac_id, enable: !!en); |
1187 | |
1188 | if (mac_ctrl_drv->set_promiscuous) |
1189 | mac_ctrl_drv->set_promiscuous(mac_ctrl_drv, en); |
1190 | } |
1191 | |
1192 | int hns_mac_get_regs_count(struct hns_mac_cb *mac_cb) |
1193 | { |
1194 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1195 | |
1196 | return mac_ctrl_drv->get_regs_count(); |
1197 | } |
1198 | |
1199 | void hns_mac_get_regs(struct hns_mac_cb *mac_cb, void *data) |
1200 | { |
1201 | struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); |
1202 | |
1203 | mac_ctrl_drv->get_regs(mac_ctrl_drv, data); |
1204 | } |
1205 | |
1206 | void hns_set_led_opt(struct hns_mac_cb *mac_cb) |
1207 | { |
1208 | int nic_data; |
1209 | int txpkts, rxpkts; |
1210 | |
1211 | txpkts = mac_cb->txpkt_for_led - mac_cb->hw_stats.tx_good_pkts; |
1212 | rxpkts = mac_cb->rxpkt_for_led - mac_cb->hw_stats.rx_good_pkts; |
1213 | if (txpkts || rxpkts) |
1214 | nic_data = 1; |
1215 | else |
1216 | nic_data = 0; |
1217 | mac_cb->txpkt_for_led = mac_cb->hw_stats.tx_good_pkts; |
1218 | mac_cb->rxpkt_for_led = mac_cb->hw_stats.rx_good_pkts; |
1219 | mac_cb->dsaf_dev->misc_op->cpld_set_led(mac_cb, (int)mac_cb->link, |
1220 | mac_cb->speed, nic_data); |
1221 | } |
1222 | |
1223 | int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, |
1224 | enum hnae_led_state status) |
1225 | { |
1226 | if (!mac_cb) |
1227 | return 0; |
1228 | |
1229 | return mac_cb->dsaf_dev->misc_op->cpld_set_led_id(mac_cb, status); |
1230 | } |
1231 | |