Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include <ethdev_pci.h>
6 : : #include <rte_ether.h>
7 : : #include <rte_kvargs.h>
8 : :
9 : : #include "otx_ep_common.h"
10 : : #include "otx_ep_vf.h"
11 : : #include "otx2_ep_vf.h"
12 : : #include "cnxk_ep_vf.h"
13 : : #include "otx_ep_mbox.h"
14 : :
15 : : /*
16 : : * When a new command is implemented, the below table should be updated
17 : : * with new command and it's version info.
18 : : */
19 : : static uint32_t otx_ep_cmd_versions[OTX_EP_MBOX_CMD_MAX] = {
20 : : [0 ... OTX_EP_MBOX_CMD_DEV_REMOVE] = OTX_EP_MBOX_VERSION_V1
21 : : };
22 : :
23 : : static int
24 : 0 : __otx_ep_send_mbox_cmd(struct otx_ep_device *otx_ep,
25 : : union otx_ep_mbox_word cmd,
26 : : union otx_ep_mbox_word *rsp)
27 : : {
28 : 0 : volatile uint64_t reg_val = 0ull;
29 : : int count = 0;
30 : :
31 : 0 : cmd.s.type = OTX_EP_MBOX_TYPE_CMD;
32 [ # # ]: 0 : otx2_write64(cmd.u64, otx_ep->hw_addr + CNXK_EP_R_MBOX_VF_PF_DATA(0));
33 : :
34 : : /* No response for notification messages */
35 [ # # ]: 0 : if (!rsp)
36 : : return 0;
37 : :
38 [ # # ]: 0 : for (count = 0; count < OTX_EP_MBOX_TIMEOUT_MS; count++) {
39 : : rte_delay_ms(1);
40 [ # # ]: 0 : reg_val = otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_VF_PF_DATA(0));
41 [ # # ]: 0 : if (reg_val != cmd.u64) {
42 : 0 : rsp->u64 = reg_val;
43 : 0 : break;
44 : : }
45 : : }
46 [ # # ]: 0 : if (count == OTX_EP_MBOX_TIMEOUT_MS) {
47 : 0 : otx_ep_err("mbox send Timeout count:%d\n", count);
48 : 0 : return OTX_EP_MBOX_TIMEOUT_MS;
49 : : }
50 [ # # ]: 0 : if (rsp->s.type != OTX_EP_MBOX_TYPE_RSP_ACK) {
51 : 0 : otx_ep_err("mbox received NACK from PF\n");
52 : 0 : return OTX_EP_MBOX_CMD_STATUS_NACK;
53 : : }
54 : :
55 : 0 : rsp->u64 = reg_val;
56 : 0 : return 0;
57 : : }
58 : :
59 : : static int
60 : 0 : otx_ep_send_mbox_cmd(struct otx_ep_device *otx_ep,
61 : : union otx_ep_mbox_word cmd,
62 : : union otx_ep_mbox_word *rsp)
63 : : {
64 : : int ret;
65 : :
66 : 0 : rte_spinlock_lock(&otx_ep->mbox_lock);
67 [ # # ]: 0 : if (otx_ep_cmd_versions[cmd.s.opcode] > otx_ep->mbox_neg_ver) {
68 : 0 : otx_ep_dbg("CMD:%d not supported in Version:%d\n", cmd.s.opcode,
69 : : otx_ep->mbox_neg_ver);
70 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
71 : 0 : return -EOPNOTSUPP;
72 : : }
73 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, rsp);
74 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
75 : 0 : return ret;
76 : : }
77 : :
78 : : static int
79 : 0 : otx_ep_mbox_bulk_read(struct otx_ep_device *otx_ep,
80 : : enum otx_ep_mbox_opcode opcode,
81 : : uint8_t *data, int32_t *size)
82 : : {
83 : : union otx_ep_mbox_word cmd;
84 : : union otx_ep_mbox_word rsp;
85 : : int read_cnt, i = 0, ret;
86 : 0 : int data_len = 0, tmp_len = 0;
87 : :
88 : 0 : rte_spinlock_lock(&otx_ep->mbox_lock);
89 : 0 : cmd.u64 = 0;
90 : 0 : cmd.s_data.opcode = opcode;
91 : : cmd.s_data.frag = 0;
92 : : /* Send cmd to read data from PF */
93 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
94 [ # # ]: 0 : if (ret) {
95 : 0 : otx_ep_err("mbox bulk read data request failed\n");
96 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
97 : 0 : return ret;
98 : : }
99 : : /* PF sends the data length of requested CMD
100 : : * in ACK
101 : : */
102 : : memcpy(&data_len, rsp.s_data.data, sizeof(data_len));
103 : : tmp_len = data_len;
104 : 0 : cmd.u64 = 0;
105 : 0 : rsp.u64 = 0;
106 : 0 : cmd.s_data.opcode = opcode;
107 : 0 : cmd.s_data.frag = 1;
108 [ # # ]: 0 : while (data_len) {
109 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
110 [ # # ]: 0 : if (ret) {
111 : 0 : otx_ep_err("mbox bulk read data request failed\n");
112 : 0 : otx_ep->mbox_data_index = 0;
113 : 0 : memset(otx_ep->mbox_data_buf, 0, OTX_EP_MBOX_MAX_DATA_BUF_SIZE);
114 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
115 : 0 : return ret;
116 : : }
117 [ # # ]: 0 : if (data_len > OTX_EP_MBOX_MAX_DATA_SIZE) {
118 : 0 : data_len -= OTX_EP_MBOX_MAX_DATA_SIZE;
119 : : read_cnt = OTX_EP_MBOX_MAX_DATA_SIZE;
120 : : } else {
121 : : read_cnt = data_len;
122 : 0 : data_len = 0;
123 : : }
124 [ # # ]: 0 : for (i = 0; i < read_cnt; i++) {
125 : 0 : otx_ep->mbox_data_buf[otx_ep->mbox_data_index] =
126 : 0 : rsp.s_data.data[i];
127 : 0 : otx_ep->mbox_data_index++;
128 : : }
129 : 0 : cmd.u64 = 0;
130 : 0 : rsp.u64 = 0;
131 : 0 : cmd.s_data.opcode = opcode;
132 : 0 : cmd.s_data.frag = 1;
133 : : }
134 : 0 : memcpy(data, otx_ep->mbox_data_buf, tmp_len);
135 : 0 : *size = tmp_len;
136 : 0 : otx_ep->mbox_data_index = 0;
137 : : memset(otx_ep->mbox_data_buf, 0, OTX_EP_MBOX_MAX_DATA_BUF_SIZE);
138 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
139 : 0 : return 0;
140 : : }
141 : :
142 : : int
143 : 0 : otx_ep_mbox_set_mtu(struct rte_eth_dev *eth_dev, uint16_t mtu)
144 : : {
145 : 0 : struct otx_ep_device *otx_ep =
146 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
147 : : union otx_ep_mbox_word cmd;
148 : : union otx_ep_mbox_word rsp;
149 : : int ret = 0;
150 : :
151 : 0 : cmd.u64 = 0;
152 : 0 : cmd.s_set_mtu.opcode = OTX_EP_MBOX_CMD_SET_MTU;
153 : 0 : cmd.s_set_mtu.mtu = mtu;
154 : :
155 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
156 [ # # ]: 0 : if (ret) {
157 : 0 : otx_ep_err("set MTU failed\n");
158 : 0 : return -EINVAL;
159 : : }
160 : 0 : otx_ep_dbg("mtu set success mtu %u\n", mtu);
161 : :
162 : 0 : return 0;
163 : : }
164 : :
165 : : int
166 : 0 : otx_ep_mbox_set_mac_addr(struct rte_eth_dev *eth_dev,
167 : : struct rte_ether_addr *mac_addr)
168 : : {
169 : 0 : struct otx_ep_device *otx_ep =
170 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
171 : : union otx_ep_mbox_word cmd;
172 : : union otx_ep_mbox_word rsp;
173 : : int i, ret;
174 : :
175 : 0 : cmd.u64 = 0;
176 : 0 : cmd.s_set_mac.opcode = OTX_EP_MBOX_CMD_SET_MAC_ADDR;
177 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
178 : 0 : cmd.s_set_mac.mac_addr[i] = mac_addr->addr_bytes[i];
179 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
180 [ # # ]: 0 : if (ret) {
181 : 0 : otx_ep_err("set MAC address failed\n");
182 : 0 : return -EINVAL;
183 : : }
184 : 0 : otx_ep_dbg("%s VF MAC " RTE_ETHER_ADDR_PRT_FMT "\n",
185 : : __func__, RTE_ETHER_ADDR_BYTES(mac_addr));
186 : 0 : rte_ether_addr_copy(mac_addr, eth_dev->data->mac_addrs);
187 : 0 : return 0;
188 : : }
189 : :
190 : : int
191 : 0 : otx_ep_mbox_get_mac_addr(struct rte_eth_dev *eth_dev,
192 : : struct rte_ether_addr *mac_addr)
193 : : {
194 : 0 : struct otx_ep_device *otx_ep =
195 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
196 : : union otx_ep_mbox_word cmd;
197 : : union otx_ep_mbox_word rsp;
198 : : int i, ret;
199 : :
200 : 0 : cmd.u64 = 0;
201 : 0 : cmd.s_set_mac.opcode = OTX_EP_MBOX_CMD_GET_MAC_ADDR;
202 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
203 [ # # ]: 0 : if (ret) {
204 : 0 : otx_ep_err("get MAC address failed\n");
205 : 0 : return -EINVAL;
206 : : }
207 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
208 : 0 : mac_addr->addr_bytes[i] = rsp.s_set_mac.mac_addr[i];
209 : 0 : otx_ep_dbg("%s VF MAC " RTE_ETHER_ADDR_PRT_FMT "\n",
210 : : __func__, RTE_ETHER_ADDR_BYTES(mac_addr));
211 : 0 : return 0;
212 : : }
213 : :
214 : 0 : int otx_ep_mbox_get_link_status(struct rte_eth_dev *eth_dev,
215 : : uint8_t *oper_up)
216 : : {
217 : 0 : struct otx_ep_device *otx_ep =
218 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
219 : : union otx_ep_mbox_word cmd;
220 : : union otx_ep_mbox_word rsp;
221 : : int ret;
222 : :
223 : 0 : cmd.u64 = 0;
224 : 0 : cmd.s_link_status.opcode = OTX_EP_MBOX_CMD_GET_LINK_STATUS;
225 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
226 [ # # ]: 0 : if (ret) {
227 : 0 : otx_ep_err("Get link status failed\n");
228 : 0 : return -EINVAL;
229 : : }
230 : 0 : *oper_up = rsp.s_link_status.status;
231 : 0 : return 0;
232 : : }
233 : :
234 : 0 : int otx_ep_mbox_get_link_info(struct rte_eth_dev *eth_dev,
235 : : struct rte_eth_link *link)
236 : : {
237 : : int32_t ret, size;
238 : : struct otx_ep_iface_link_info link_info;
239 : 0 : struct otx_ep_device *otx_ep =
240 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
241 : : memset(&link_info, 0, sizeof(struct otx_ep_iface_link_info));
242 : 0 : ret = otx_ep_mbox_bulk_read(otx_ep, OTX_EP_MBOX_CMD_GET_LINK_INFO,
243 : : (uint8_t *)&link_info, (int32_t *)&size);
244 [ # # ]: 0 : if (ret) {
245 : 0 : otx_ep_err("Get link info failed\n");
246 : 0 : return ret;
247 : : }
248 : 0 : link->link_status = RTE_ETH_LINK_UP;
249 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
250 : 0 : link->link_autoneg = (link_info.autoneg ==
251 : : OTX_EP_LINK_AUTONEG) ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
252 : :
253 : 0 : link->link_autoneg = link_info.autoneg;
254 : 0 : link->link_speed = link_info.speed;
255 : 0 : return 0;
256 : : }
257 : :
258 : : void
259 : 0 : otx_ep_mbox_enable_interrupt(struct otx_ep_device *otx_ep)
260 : : {
261 : 0 : rte_write64(0x2, (uint8_t *)otx_ep->hw_addr +
262 : : CNXK_EP_R_MBOX_PF_VF_INT(0));
263 : 0 : }
264 : :
265 : : void
266 : 0 : otx_ep_mbox_disable_interrupt(struct otx_ep_device *otx_ep)
267 : : {
268 : 0 : rte_write64(0x00, (uint8_t *)otx_ep->hw_addr +
269 : : CNXK_EP_R_MBOX_PF_VF_INT(0));
270 : 0 : }
271 : :
272 : : int
273 : 0 : otx_ep_mbox_get_max_pkt_len(struct rte_eth_dev *eth_dev)
274 : : {
275 : 0 : struct otx_ep_device *otx_ep =
276 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
277 : : union otx_ep_mbox_word cmd;
278 : : union otx_ep_mbox_word rsp;
279 : : int ret;
280 : :
281 : 0 : rsp.u64 = 0;
282 : 0 : cmd.u64 = 0;
283 : 0 : cmd.s_get_mtu.opcode = OTX_EP_MBOX_CMD_GET_MTU;
284 : :
285 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
286 [ # # ]: 0 : if (ret)
287 : : return ret;
288 : 0 : return rsp.s_get_mtu.mtu;
289 : : }
290 : :
291 : 0 : int otx_ep_mbox_version_check(struct rte_eth_dev *eth_dev)
292 : : {
293 : 0 : struct otx_ep_device *otx_ep =
294 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
295 : : union otx_ep_mbox_word cmd;
296 : : union otx_ep_mbox_word rsp;
297 : : int ret;
298 : :
299 : 0 : cmd.u64 = 0;
300 : : cmd.s_version.opcode = OTX_EP_MBOX_CMD_VERSION;
301 : 0 : cmd.s_version.version = OTX_EP_MBOX_VERSION_CURRENT;
302 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
303 : :
304 : : /*
305 : : * VF receives NACK or version info as zero
306 : : * only if PF driver running old version of Mailbox
307 : : * In this case VF mailbox version fallbacks to base
308 : : * mailbox vesrion OTX_EP_MBOX_VERSION_V1.
309 : : * Default VF mbox_neg_ver is set to OTX_EP_MBOX_VERSION_V1
310 : : * during initialization of PMD driver.
311 : : */
312 [ # # # # ]: 0 : if (ret == OTX_EP_MBOX_CMD_STATUS_NACK || rsp.s_version.version == 0) {
313 : 0 : otx_ep_dbg("VF Mbox version fallback to base version from:%u\n",
314 : : (uint32_t)cmd.s_version.version);
315 : 0 : return 0;
316 : : }
317 : 0 : otx_ep->mbox_neg_ver = (uint32_t)rsp.s_version.version;
318 : 0 : otx_ep_dbg("VF Mbox version:%u Negotiated VF version with PF:%u\n",
319 : : (uint32_t)cmd.s_version.version,
320 : : (uint32_t)rsp.s_version.version);
321 : 0 : return 0;
322 : : }
323 : :
324 : 0 : int otx_ep_mbox_send_dev_exit(struct rte_eth_dev *eth_dev)
325 : : {
326 : 0 : struct otx_ep_device *otx_ep =
327 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
328 : : union otx_ep_mbox_word cmd;
329 : : int ret;
330 : :
331 : 0 : cmd.u64 = 0;
332 : 0 : cmd.s_version.opcode = OTX_EP_MBOX_CMD_DEV_REMOVE;
333 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, NULL);
334 : 0 : return ret;
335 : : }
|