xref: /dpdk/drivers/net/cnxk/cnxk_link.c (revision 852cedba)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include "cnxk_ethdev.h"
6 
7 void
cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev * dev,bool set)8 cnxk_nix_toggle_flag_link_cfg(struct cnxk_eth_dev *dev, bool set)
9 {
10 	if (set)
11 		dev->flags |= CNXK_LINK_CFG_IN_PROGRESS_F;
12 	else
13 		dev->flags &= ~CNXK_LINK_CFG_IN_PROGRESS_F;
14 
15 	/* Update link info for LBK */
16 	if (!set && roc_nix_is_lbk(&dev->nix)) {
17 		struct rte_eth_link link;
18 
19 		link.link_status = RTE_ETH_LINK_UP;
20 		link.link_speed = RTE_ETH_SPEED_NUM_100G;
21 		link.link_autoneg = RTE_ETH_LINK_FIXED;
22 		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
23 		rte_eth_linkstatus_set(dev->eth_dev, &link);
24 	}
25 
26 	rte_wmb();
27 }
28 
29 static inline int
nix_wait_for_link_cfg(struct cnxk_eth_dev * dev)30 nix_wait_for_link_cfg(struct cnxk_eth_dev *dev)
31 {
32 	uint16_t wait = 1000;
33 
34 	do {
35 		rte_atomic_thread_fence(__ATOMIC_ACQUIRE);
36 		if (!(dev->flags & CNXK_LINK_CFG_IN_PROGRESS_F))
37 			break;
38 		wait--;
39 		rte_delay_ms(1);
40 	} while (wait);
41 
42 	return wait ? 0 : -1;
43 }
44 
45 static void
nix_link_status_print(struct rte_eth_dev * eth_dev,struct rte_eth_link * link)46 nix_link_status_print(struct rte_eth_dev *eth_dev, struct rte_eth_link *link)
47 {
48 	if (link && link->link_status)
49 		plt_info("Port %d: Link Up - speed %u Mbps - %s",
50 			 (int)(eth_dev->data->port_id),
51 			 (uint32_t)link->link_speed,
52 			 link->link_duplex == RTE_ETH_LINK_FULL_DUPLEX
53 				 ? "full-duplex"
54 				 : "half-duplex");
55 	else
56 		plt_info("Port %d: Link Down", (int)(eth_dev->data->port_id));
57 }
58 
59 void
cnxk_eth_dev_link_status_get_cb(struct roc_nix * nix,struct roc_nix_link_info * link)60 cnxk_eth_dev_link_status_get_cb(struct roc_nix *nix,
61 				struct roc_nix_link_info *link)
62 {
63 	struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
64 	struct rte_eth_link eth_link;
65 	struct rte_eth_dev *eth_dev;
66 
67 	if (!link || !nix)
68 		return;
69 
70 	eth_dev = dev->eth_dev;
71 	if (!eth_dev)
72 		return;
73 
74 	rte_eth_linkstatus_get(eth_dev, &eth_link);
75 
76 	link->status = eth_link.link_status;
77 	link->speed = eth_link.link_speed;
78 	link->autoneg = eth_link.link_autoneg;
79 	link->full_duplex = eth_link.link_duplex;
80 }
81 
82 void
cnxk_eth_dev_link_status_cb(struct roc_nix * nix,struct roc_nix_link_info * link)83 cnxk_eth_dev_link_status_cb(struct roc_nix *nix, struct roc_nix_link_info *link)
84 {
85 	struct cnxk_eth_dev *dev = (struct cnxk_eth_dev *)nix;
86 	struct rte_eth_link eth_link;
87 	struct rte_eth_dev *eth_dev;
88 
89 	if (!link || !nix)
90 		return;
91 
92 	eth_dev = dev->eth_dev;
93 	if (!eth_dev || !eth_dev->data->dev_conf.intr_conf.lsc)
94 		return;
95 
96 	if (nix_wait_for_link_cfg(dev)) {
97 		plt_err("Timeout waiting for link_cfg to complete");
98 		return;
99 	}
100 
101 	eth_link.link_status = link->status;
102 	eth_link.link_speed = link->speed;
103 	eth_link.link_autoneg = RTE_ETH_LINK_AUTONEG;
104 	eth_link.link_duplex = link->full_duplex;
105 
106 	/* Print link info */
107 	nix_link_status_print(eth_dev, &eth_link);
108 
109 	/* Update link info */
110 	rte_eth_linkstatus_set(eth_dev, &eth_link);
111 
112 	/* Set the flag and execute application callbacks */
113 	rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
114 }
115 
116 int
cnxk_nix_link_update(struct rte_eth_dev * eth_dev,int wait_to_complete)117 cnxk_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
118 {
119 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
120 	struct roc_nix_link_info info;
121 	struct rte_eth_link link;
122 	int rc;
123 
124 	RTE_SET_USED(wait_to_complete);
125 	memset(&link, 0, sizeof(struct rte_eth_link));
126 
127 	if (!eth_dev->data->dev_started || roc_nix_is_sdp(&dev->nix))
128 		return 0;
129 
130 	if (roc_nix_is_lbk(&dev->nix)) {
131 		link.link_status = RTE_ETH_LINK_UP;
132 		link.link_speed = RTE_ETH_SPEED_NUM_100G;
133 		link.link_autoneg = RTE_ETH_LINK_FIXED;
134 		link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
135 	} else {
136 		rc = roc_nix_mac_link_info_get(&dev->nix, &info);
137 		if (rc)
138 			return rc;
139 		link.link_status = info.status;
140 		link.link_speed = info.speed;
141 		link.link_autoneg = RTE_ETH_LINK_AUTONEG;
142 		if (info.full_duplex)
143 			link.link_duplex = info.full_duplex;
144 	}
145 
146 	return rte_eth_linkstatus_set(eth_dev, &link);
147 }
148