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 : : [OTX_EP_MBOX_CMD_GET_FW_INFO ... OTX_EP_MBOX_NOTIF_LINK_STATUS] = OTX_EP_MBOX_VERSION_V2,
22 : : [OTX_EP_MBOX_NOTIF_PF_FLR] = OTX_EP_MBOX_VERSION_V3
23 : :
24 : : };
25 : :
26 : : static int
27 : 0 : __otx_ep_send_mbox_cmd(struct otx_ep_device *otx_ep,
28 : : union otx_ep_mbox_word cmd,
29 : : union otx_ep_mbox_word *rsp)
30 : : {
31 : 0 : volatile uint64_t reg_val = 0ull;
32 : : int count = 0;
33 : :
34 [ # # ]: 0 : reg_val = otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_VF_PF_DATA(0));
35 [ # # ]: 0 : if (reg_val == UINT64_MAX)
36 : : return -ENODEV;
37 : :
38 : 0 : cmd.s.type = OTX_EP_MBOX_TYPE_CMD;
39 [ # # ]: 0 : otx2_write64(cmd.u64, otx_ep->hw_addr + CNXK_EP_R_MBOX_VF_PF_DATA(0));
40 : :
41 : : /* No response for notification messages */
42 [ # # ]: 0 : if (!rsp)
43 : : return 0;
44 : :
45 [ # # ]: 0 : for (count = 0; count < OTX_EP_MBOX_TIMEOUT_MS; count++) {
46 : : rte_delay_ms(1);
47 [ # # ]: 0 : reg_val = otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_VF_PF_DATA(0));
48 [ # # ]: 0 : if (reg_val == UINT64_MAX)
49 : : return -ENODEV;
50 [ # # ]: 0 : if (reg_val != cmd.u64) {
51 : 0 : rsp->u64 = reg_val;
52 : 0 : break;
53 : : }
54 : : }
55 [ # # ]: 0 : if (count == OTX_EP_MBOX_TIMEOUT_MS) {
56 : 0 : otx_ep_err("mbox send Timeout count:%d", count);
57 : 0 : return OTX_EP_MBOX_TIMEOUT_MS;
58 : : }
59 [ # # ]: 0 : if (rsp->s.type != OTX_EP_MBOX_TYPE_RSP_ACK) {
60 : 0 : otx_ep_err("mbox received NACK from PF");
61 : 0 : return OTX_EP_MBOX_CMD_STATUS_NACK;
62 : : }
63 : :
64 : 0 : rsp->u64 = reg_val;
65 : 0 : return 0;
66 : : }
67 : :
68 : : static int
69 : 0 : otx_ep_send_mbox_cmd(struct otx_ep_device *otx_ep,
70 : : union otx_ep_mbox_word cmd,
71 : : union otx_ep_mbox_word *rsp)
72 : : {
73 : : int ret;
74 : :
75 : 0 : rte_spinlock_lock(&otx_ep->mbox_lock);
76 [ # # ]: 0 : if (otx_ep_cmd_versions[cmd.s.opcode] > otx_ep->mbox_neg_ver) {
77 : 0 : otx_ep_dbg("CMD:%d not supported in Version:%d", cmd.s.opcode,
78 : : otx_ep->mbox_neg_ver);
79 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
80 : 0 : return -EOPNOTSUPP;
81 : : }
82 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, rsp);
83 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
84 : 0 : return ret;
85 : : }
86 : :
87 : : static int
88 : 0 : otx_ep_mbox_bulk_read(struct otx_ep_device *otx_ep,
89 : : enum otx_ep_mbox_opcode opcode,
90 : : uint8_t *data, int32_t *size)
91 : : {
92 : : union otx_ep_mbox_word cmd;
93 : : union otx_ep_mbox_word rsp;
94 : : int read_cnt, i = 0, ret;
95 : 0 : int data_len = 0, tmp_len = 0;
96 : :
97 : 0 : rte_spinlock_lock(&otx_ep->mbox_lock);
98 : 0 : cmd.u64 = 0;
99 : 0 : cmd.s_data.opcode = opcode;
100 : : cmd.s_data.frag = 0;
101 : : /* Send cmd to read data from PF */
102 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
103 [ # # ]: 0 : if (ret) {
104 : 0 : otx_ep_err("mbox bulk read data request failed");
105 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
106 : 0 : return ret;
107 : : }
108 : : /* PF sends the data length of requested CMD
109 : : * in ACK
110 : : */
111 : : memcpy(&data_len, rsp.s_data.data, sizeof(data_len));
112 : : tmp_len = data_len;
113 : 0 : cmd.u64 = 0;
114 : 0 : rsp.u64 = 0;
115 : 0 : cmd.s_data.opcode = opcode;
116 : 0 : cmd.s_data.frag = 1;
117 [ # # ]: 0 : while (data_len) {
118 : 0 : ret = __otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
119 [ # # ]: 0 : if (ret) {
120 : 0 : otx_ep_err("mbox bulk read data request failed");
121 : 0 : otx_ep->mbox_data_index = 0;
122 : 0 : memset(otx_ep->mbox_data_buf, 0, OTX_EP_MBOX_MAX_DATA_BUF_SIZE);
123 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
124 : 0 : return ret;
125 : : }
126 [ # # ]: 0 : if (data_len > OTX_EP_MBOX_MAX_DATA_SIZE) {
127 : 0 : data_len -= OTX_EP_MBOX_MAX_DATA_SIZE;
128 : : read_cnt = OTX_EP_MBOX_MAX_DATA_SIZE;
129 : : } else {
130 : : read_cnt = data_len;
131 : 0 : data_len = 0;
132 : : }
133 [ # # ]: 0 : for (i = 0; i < read_cnt; i++) {
134 : 0 : otx_ep->mbox_data_buf[otx_ep->mbox_data_index] =
135 : 0 : rsp.s_data.data[i];
136 : 0 : otx_ep->mbox_data_index++;
137 : : }
138 : 0 : cmd.u64 = 0;
139 : 0 : rsp.u64 = 0;
140 : 0 : cmd.s_data.opcode = opcode;
141 : 0 : cmd.s_data.frag = 1;
142 : : }
143 : 0 : memcpy(data, otx_ep->mbox_data_buf, tmp_len);
144 : 0 : *size = tmp_len;
145 : 0 : otx_ep->mbox_data_index = 0;
146 : : memset(otx_ep->mbox_data_buf, 0, OTX_EP_MBOX_MAX_DATA_BUF_SIZE);
147 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
148 : 0 : return 0;
149 : : }
150 : :
151 : : int
152 : 0 : otx_ep_mbox_set_mtu(struct rte_eth_dev *eth_dev, uint16_t mtu)
153 : : {
154 : 0 : struct otx_ep_device *otx_ep =
155 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
156 : : union otx_ep_mbox_word cmd;
157 : : union otx_ep_mbox_word rsp;
158 : : int ret = 0;
159 : :
160 : 0 : cmd.u64 = 0;
161 : 0 : cmd.s_set_mtu.opcode = OTX_EP_MBOX_CMD_SET_MTU;
162 : 0 : cmd.s_set_mtu.mtu = mtu;
163 : :
164 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
165 [ # # ]: 0 : if (ret) {
166 : 0 : otx_ep_err("set MTU failed");
167 : 0 : return -EINVAL;
168 : : }
169 : 0 : otx_ep_dbg("mtu set success mtu %u", mtu);
170 : :
171 : 0 : return 0;
172 : : }
173 : :
174 : : int
175 : 0 : otx_ep_mbox_set_mac_addr(struct rte_eth_dev *eth_dev,
176 : : struct rte_ether_addr *mac_addr)
177 : : {
178 : 0 : struct otx_ep_device *otx_ep =
179 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
180 : : union otx_ep_mbox_word cmd;
181 : : union otx_ep_mbox_word rsp;
182 : : int i, ret;
183 : :
184 : 0 : cmd.u64 = 0;
185 : 0 : cmd.s_set_mac.opcode = OTX_EP_MBOX_CMD_SET_MAC_ADDR;
186 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
187 : 0 : cmd.s_set_mac.mac_addr[i] = mac_addr->addr_bytes[i];
188 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
189 [ # # ]: 0 : if (ret) {
190 : 0 : otx_ep_err("set MAC address failed");
191 : 0 : return -EINVAL;
192 : : }
193 : 0 : otx_ep_dbg("%s VF MAC " RTE_ETHER_ADDR_PRT_FMT,
194 : : __func__, RTE_ETHER_ADDR_BYTES(mac_addr));
195 : 0 : rte_ether_addr_copy(mac_addr, eth_dev->data->mac_addrs);
196 : 0 : return 0;
197 : : }
198 : :
199 : : int
200 : 0 : otx_ep_mbox_get_mac_addr(struct rte_eth_dev *eth_dev,
201 : : struct rte_ether_addr *mac_addr)
202 : : {
203 : 0 : struct otx_ep_device *otx_ep =
204 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
205 : : union otx_ep_mbox_word cmd;
206 : : union otx_ep_mbox_word rsp;
207 : : int i, ret;
208 : :
209 : 0 : cmd.u64 = 0;
210 : 0 : cmd.s_set_mac.opcode = OTX_EP_MBOX_CMD_GET_MAC_ADDR;
211 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
212 [ # # ]: 0 : if (ret) {
213 : 0 : otx_ep_err("get MAC address failed");
214 : 0 : return -EINVAL;
215 : : }
216 [ # # ]: 0 : for (i = 0; i < RTE_ETHER_ADDR_LEN; i++)
217 : 0 : mac_addr->addr_bytes[i] = rsp.s_set_mac.mac_addr[i];
218 : 0 : otx_ep_dbg("%s VF MAC " RTE_ETHER_ADDR_PRT_FMT,
219 : : __func__, RTE_ETHER_ADDR_BYTES(mac_addr));
220 : 0 : return 0;
221 : : }
222 : :
223 : 0 : int otx_ep_mbox_get_link_status(struct rte_eth_dev *eth_dev,
224 : : uint8_t *oper_up)
225 : : {
226 : 0 : struct otx_ep_device *otx_ep =
227 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
228 : : union otx_ep_mbox_word cmd;
229 : : union otx_ep_mbox_word rsp;
230 : : int ret;
231 : :
232 : 0 : cmd.u64 = 0;
233 : 0 : cmd.s_link_status.opcode = OTX_EP_MBOX_CMD_GET_LINK_STATUS;
234 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
235 [ # # ]: 0 : if (ret) {
236 : 0 : otx_ep_err("Get link status failed");
237 : 0 : return -EINVAL;
238 : : }
239 : 0 : *oper_up = rsp.s_link_status.status;
240 : 0 : return 0;
241 : : }
242 : :
243 : 0 : int otx_ep_mbox_get_link_info(struct rte_eth_dev *eth_dev,
244 : : struct rte_eth_link *link)
245 : : {
246 : : int32_t ret, size;
247 : : struct otx_ep_iface_link_info link_info;
248 : 0 : struct otx_ep_device *otx_ep =
249 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
250 : : memset(&link_info, 0, sizeof(struct otx_ep_iface_link_info));
251 : 0 : ret = otx_ep_mbox_bulk_read(otx_ep, OTX_EP_MBOX_CMD_GET_LINK_INFO,
252 : : (uint8_t *)&link_info, (int32_t *)&size);
253 [ # # ]: 0 : if (ret) {
254 : 0 : otx_ep_err("Get link info failed");
255 : 0 : return ret;
256 : : }
257 : 0 : link->link_status = RTE_ETH_LINK_UP;
258 : 0 : link->link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
259 : 0 : link->link_autoneg = (link_info.autoneg ==
260 : : OTX_EP_LINK_AUTONEG) ? RTE_ETH_LINK_AUTONEG : RTE_ETH_LINK_FIXED;
261 : :
262 : 0 : link->link_autoneg = link_info.autoneg;
263 : 0 : link->link_speed = link_info.speed;
264 : 0 : return 0;
265 : : }
266 : :
267 : : void
268 : 0 : otx_ep_mbox_enable_interrupt(struct otx_ep_device *otx_ep)
269 : : {
270 : 0 : rte_write64(0x2, (uint8_t *)otx_ep->hw_addr +
271 : : CNXK_EP_R_MBOX_PF_VF_INT(0));
272 : 0 : }
273 : :
274 : : void
275 : 0 : otx_ep_mbox_disable_interrupt(struct otx_ep_device *otx_ep)
276 : : {
277 : 0 : rte_write64(0x00, (uint8_t *)otx_ep->hw_addr +
278 : : CNXK_EP_R_MBOX_PF_VF_INT(0));
279 : 0 : }
280 : :
281 : : int
282 : 0 : otx_ep_mbox_get_max_pkt_len(struct rte_eth_dev *eth_dev)
283 : : {
284 : 0 : struct otx_ep_device *otx_ep =
285 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
286 : : union otx_ep_mbox_word cmd;
287 : : union otx_ep_mbox_word rsp;
288 : : int ret;
289 : :
290 : 0 : rsp.u64 = 0;
291 : 0 : cmd.u64 = 0;
292 : 0 : cmd.s_get_mtu.opcode = OTX_EP_MBOX_CMD_GET_MTU;
293 : :
294 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
295 [ # # ]: 0 : if (ret)
296 : : return ret;
297 : 0 : return rsp.s_get_mtu.mtu;
298 : : }
299 : :
300 : : static void
301 : 0 : otx_ep_mbox_version_check(struct otx_ep_device *otx_ep)
302 : : {
303 : : union otx_ep_mbox_word cmd;
304 : : union otx_ep_mbox_word rsp;
305 : : int ret;
306 : :
307 : 0 : cmd.u64 = 0;
308 : : cmd.s_version.opcode = OTX_EP_MBOX_CMD_VERSION;
309 : 0 : cmd.s_version.version = OTX_EP_MBOX_VERSION_CURRENT;
310 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, &rsp);
311 : :
312 : : /*
313 : : * VF receives NACK or version info as zero
314 : : * only if PF driver running old version of Mailbox
315 : : * In this case VF mailbox version fallbacks to base
316 : : * mailbox vesrion OTX_EP_MBOX_VERSION_V1.
317 : : * Default VF mbox_neg_ver is set to OTX_EP_MBOX_VERSION_V1
318 : : * during initialization of PMD driver.
319 : : */
320 [ # # # # ]: 0 : if (ret == OTX_EP_MBOX_CMD_STATUS_NACK || rsp.s_version.version == 0) {
321 : 0 : otx_ep_dbg("VF Mbox version fallback to base version from:%u",
322 : : (uint32_t)cmd.s_version.version);
323 : 0 : return;
324 : : }
325 : 0 : otx_ep->mbox_neg_ver = (uint32_t)rsp.s_version.version;
326 : 0 : otx_ep_dbg("VF Mbox version:%u Negotiated VF version with PF:%u",
327 : : (uint32_t)cmd.s_version.version,
328 : : (uint32_t)rsp.s_version.version);
329 : : }
330 : :
331 : : static void
332 : 0 : otx_ep_mbox_intr_handler(void *param)
333 : : {
334 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)param;
335 : 0 : struct otx_ep_device *otx_ep = (struct otx_ep_device *)eth_dev->data->dev_private;
336 : 0 : struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
337 : : union otx_ep_mbox_word mbox_cmd;
338 : :
339 [ # # ]: 0 : if (otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_INT(0)) & CNXK_EP_MBOX_INTR) {
340 [ # # ]: 0 : mbox_cmd.u64 = otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_DATA(0));
341 : : otx2_write64(CNXK_EP_MBOX_ENAB | CNXK_EP_MBOX_INTR,
342 : : otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_INT(0));
343 [ # # ]: 0 : if (mbox_cmd.s.opcode == OTX_EP_MBOX_NOTIF_PF_FLR) {
344 : 0 : rte_spinlock_lock(&otx_ep->mbox_lock);
345 : 0 : mbox_cmd.s.type = OTX_EP_MBOX_TYPE_RSP_ACK;
346 : 0 : otx2_write64(mbox_cmd.u64, otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_DATA(0));
347 : : rte_spinlock_unlock(&otx_ep->mbox_lock);
348 : 0 : rte_dev_event_callback_process(pdev->name, RTE_DEV_EVENT_REMOVE);
349 : : } else {
350 : 0 : otx_ep_err("Invalid mbox opcode");
351 : : }
352 : : }
353 : 0 : }
354 : :
355 : : int
356 : 0 : otx_ep_mbox_init(struct rte_eth_dev *eth_dev)
357 : : {
358 : 0 : struct otx_ep_device *otx_ep = (struct otx_ep_device *)eth_dev->data->dev_private;
359 : 0 : struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
360 : : uint64_t reg_val;
361 : :
362 : 0 : otx_ep_mbox_version_check(otx_ep);
363 : :
364 : 0 : rte_intr_callback_register(pdev->intr_handle, otx_ep_mbox_intr_handler, (void *)eth_dev);
365 : :
366 [ # # ]: 0 : if (rte_intr_enable(pdev->intr_handle)) {
367 : 0 : otx_ep_err("rte_intr_enable failed");
368 : 0 : return -1;
369 : : }
370 : :
371 [ # # ]: 0 : reg_val = otx2_read64(otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_INT(0));
372 [ # # ]: 0 : if (reg_val == UINT64_MAX)
373 : : return -ENODEV;
374 : :
375 : : /* Enable pf-vf mbox interrupt & clear the status */
376 : : otx2_write64(CNXK_EP_MBOX_ENAB | CNXK_EP_MBOX_INTR,
377 : : otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_INT(0));
378 : :
379 : 0 : return 0;
380 : : }
381 : :
382 : : void
383 : 0 : otx_ep_mbox_uninit(struct rte_eth_dev *eth_dev)
384 : : {
385 : 0 : struct otx_ep_device *otx_ep = (struct otx_ep_device *)eth_dev->data->dev_private;
386 : 0 : struct rte_pci_device *pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
387 : :
388 : 0 : otx2_write64(0, otx_ep->hw_addr + CNXK_EP_R_MBOX_PF_VF_INT(0));
389 : :
390 : 0 : rte_intr_disable(pdev->intr_handle);
391 : :
392 : 0 : rte_intr_callback_unregister(pdev->intr_handle, otx_ep_mbox_intr_handler, (void *)eth_dev);
393 : 0 : }
394 : :
395 : 0 : int otx_ep_mbox_send_dev_exit(struct rte_eth_dev *eth_dev)
396 : : {
397 : 0 : struct otx_ep_device *otx_ep =
398 : 0 : (struct otx_ep_device *)(eth_dev)->data->dev_private;
399 : : union otx_ep_mbox_word cmd;
400 : : int ret;
401 : :
402 : 0 : cmd.u64 = 0;
403 : 0 : cmd.s_version.opcode = OTX_EP_MBOX_CMD_DEV_REMOVE;
404 : 0 : ret = otx_ep_send_mbox_cmd(otx_ep, cmd, NULL);
405 : 0 : return ret;
406 : : }
|