Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include <string.h>
5 : :
6 : : #include <bus_pci_driver.h>
7 : : #include <rte_rawdev.h>
8 : : #include <rte_rawdev_pmd.h>
9 : :
10 : : #include <roc_api.h>
11 : :
12 : : #include "cnxk_bphy_cgx.h"
13 : : #include "rte_pmd_bphy.h"
14 : :
15 : : struct cnxk_bphy_cgx_queue {
16 : : unsigned int lmac;
17 : : /* queue holds up to one response */
18 : : void *rsp;
19 : : };
20 : :
21 : : struct cnxk_bphy_cgx {
22 : : struct roc_bphy_cgx *rcgx;
23 : : struct cnxk_bphy_cgx_queue queues[MAX_LMACS_PER_CGX];
24 : : unsigned int num_queues;
25 : : };
26 : :
27 : : static void
28 : : cnxk_bphy_cgx_format_name(char *name, unsigned int len,
29 : : struct rte_pci_device *pci_dev)
30 : : {
31 : 0 : snprintf(name, len, "BPHY_CGX:%02x:%02x.%x", pci_dev->addr.bus,
32 : 0 : pci_dev->addr.devid, pci_dev->addr.function);
33 : : }
34 : :
35 : : static int
36 : 0 : cnxk_bphy_cgx_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
37 : : rte_rawdev_obj_t queue_conf,
38 : : size_t queue_conf_size)
39 : : {
40 : : unsigned int *conf;
41 : :
42 : : RTE_SET_USED(dev);
43 : : RTE_SET_USED(queue_id);
44 : :
45 [ # # ]: 0 : if (queue_conf_size != sizeof(*conf))
46 : : return -EINVAL;
47 : :
48 : : conf = (unsigned int *)queue_conf;
49 : 0 : *conf = 1;
50 : :
51 : 0 : return 0;
52 : : }
53 : :
54 : : static int
55 : 0 : cnxk_bphy_cgx_process_buf(struct cnxk_bphy_cgx *cgx, unsigned int queue,
56 : : struct rte_rawdev_buf *buf)
57 : : {
58 : : struct cnxk_bphy_cgx_queue *qp = &cgx->queues[queue];
59 : : struct cnxk_bphy_cgx_msg_cpri_mode_change *cpri_mode;
60 : : struct cnxk_bphy_cgx_msg_set_link_state *link_state;
61 : : struct cnxk_bphy_cgx_msg_cpri_mode_tx_ctrl *tx_ctrl;
62 : : struct cnxk_bphy_cgx_msg_cpri_mode_misc *mode_misc;
63 : 0 : struct cnxk_bphy_cgx_msg *msg = buf->buf_addr;
64 : : struct cnxk_bphy_cgx_msg_link_mode *link_mode;
65 : : struct cnxk_bphy_cgx_msg_link_info *link_info;
66 : : struct roc_bphy_cgx_cpri_mode_change rcpri_mode;
67 : : struct roc_bphy_cgx_cpri_mode_misc rmode_misc;
68 : : struct roc_bphy_cgx_cpri_mode_tx_ctrl rtx_ctrl;
69 : : struct roc_bphy_cgx_link_state rlink_state;
70 : : struct roc_bphy_cgx_link_info rlink_info;
71 : : struct roc_bphy_cgx_link_mode rlink_mode;
72 : : enum roc_bphy_cgx_eth_link_fec *fec;
73 : 0 : unsigned int lmac = qp->lmac;
74 : : void *rsp = NULL;
75 : : int ret;
76 : :
77 [ # # # # : 0 : switch (msg->type) {
# # # # #
# # # # #
# ]
78 : : case CNXK_BPHY_CGX_MSG_TYPE_GET_LINKINFO:
79 : : memset(&rlink_info, 0, sizeof(rlink_info));
80 : 0 : ret = roc_bphy_cgx_get_linkinfo(cgx->rcgx, lmac, &rlink_info);
81 [ # # ]: 0 : if (ret)
82 : : break;
83 : :
84 : 0 : link_info = rte_zmalloc(NULL, sizeof(*link_info), 0);
85 [ # # ]: 0 : if (!link_info)
86 : : return -ENOMEM;
87 : :
88 : 0 : link_info->link_up = rlink_info.link_up;
89 : 0 : link_info->full_duplex = rlink_info.full_duplex;
90 : 0 : link_info->speed =
91 : 0 : (enum cnxk_bphy_cgx_eth_link_speed)rlink_info.speed;
92 : 0 : link_info->autoneg = rlink_info.an;
93 : 0 : link_info->fec =
94 : 0 : (enum cnxk_bphy_cgx_eth_link_fec)rlink_info.fec;
95 : 0 : link_info->mode =
96 : 0 : (enum cnxk_bphy_cgx_eth_link_mode)rlink_info.mode;
97 : : rsp = link_info;
98 : 0 : break;
99 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_INTLBK_DISABLE:
100 : 0 : ret = roc_bphy_cgx_intlbk_disable(cgx->rcgx, lmac);
101 : 0 : break;
102 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_INTLBK_ENABLE:
103 : 0 : ret = roc_bphy_cgx_intlbk_enable(cgx->rcgx, lmac);
104 : 0 : break;
105 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_PTP_RX_DISABLE:
106 : 0 : ret = roc_bphy_cgx_ptp_rx_disable(cgx->rcgx, lmac);
107 : 0 : break;
108 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_PTP_RX_ENABLE:
109 : 0 : ret = roc_bphy_cgx_ptp_rx_enable(cgx->rcgx, lmac);
110 : 0 : break;
111 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_SET_LINK_MODE:
112 [ # # # ]: 0 : link_mode = msg->data;
113 : : memset(&rlink_mode, 0, sizeof(rlink_mode));
114 : 0 : rlink_mode.full_duplex = link_mode->full_duplex;
115 : 0 : rlink_mode.an = link_mode->autoneg;
116 : 0 : rlink_mode.use_portm_idx = link_mode->use_portm_idx;
117 : 0 : rlink_mode.portm_idx = link_mode->portm_idx;
118 : 0 : rlink_mode.mode_group_idx =
119 : 0 : (enum roc_bphy_cgx_mode_group)link_mode->mode_group_idx;
120 : 0 : rlink_mode.speed =
121 [ # # # ]: 0 : (enum roc_bphy_cgx_eth_link_speed)link_mode->speed;
122 : : switch (link_mode->mode_group_idx) {
123 : 0 : case CNXK_BPHY_CGX_MODE_GROUP_ETH:
124 : 0 : rlink_mode.mode =
125 : : (enum roc_bphy_cgx_eth_link_mode)
126 : 0 : link_mode->mode;
127 : 0 : break;
128 : 0 : case CNXK_BPHY_CGX_MODE_GROUP_CPRI:
129 : 0 : rlink_mode.mode_cpri =
130 : : (enum roc_bphy_cgx_eth_mode_cpri)
131 : 0 : link_mode->mode_cpri;
132 : 0 : break;
133 : : }
134 : 0 : ret = roc_bphy_cgx_set_link_mode(cgx->rcgx, lmac, &rlink_mode);
135 : 0 : break;
136 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_SET_LINK_STATE:
137 : 0 : link_state = msg->data;
138 : 0 : rlink_state.state = link_state->state;
139 : 0 : rlink_state.timeout = link_state->timeout;
140 : 0 : rlink_state.rx_tx_dis = link_state->rx_tx_dis;
141 : 0 : ret = roc_bphy_cgx_set_link_state(cgx->rcgx, lmac, &rlink_state);
142 : 0 : break;
143 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_START_RXTX:
144 : 0 : ret = roc_bphy_cgx_start_rxtx(cgx->rcgx, lmac);
145 : 0 : break;
146 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_STOP_RXTX:
147 : 0 : ret = roc_bphy_cgx_stop_rxtx(cgx->rcgx, lmac);
148 : 0 : break;
149 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_GET_SUPPORTED_FEC:
150 : 0 : fec = rte_zmalloc(NULL, sizeof(*fec), 0);
151 [ # # ]: 0 : if (!fec)
152 : : return -ENOMEM;
153 : :
154 : 0 : ret = roc_bphy_cgx_fec_supported_get(cgx->rcgx, lmac, fec);
155 : : rsp = fec;
156 : 0 : break;
157 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_SET_FEC:
158 : 0 : fec = msg->data;
159 : 0 : ret = roc_bphy_cgx_fec_set(cgx->rcgx, lmac, *fec);
160 : 0 : break;
161 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_CPRI_MODE_CHANGE:
162 : 0 : cpri_mode = msg->data;
163 : : memset(&rcpri_mode, 0, sizeof(rcpri_mode));
164 : 0 : rcpri_mode.gserc_idx = cpri_mode->gserc_idx;
165 : 0 : rcpri_mode.lane_idx = cpri_mode->lane_idx;
166 : 0 : rcpri_mode.rate = cpri_mode->rate;
167 : 0 : rcpri_mode.disable_leq = cpri_mode->disable_leq;
168 : 0 : rcpri_mode.disable_dfe = cpri_mode->disable_dfe;
169 : 0 : ret = roc_bphy_cgx_cpri_mode_change(cgx->rcgx, lmac,
170 : : &rcpri_mode);
171 : 0 : break;
172 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_CPRI_TX_CONTROL:
173 : 0 : tx_ctrl = msg->data;
174 : : memset(&rtx_ctrl, 0, sizeof(rtx_ctrl));
175 : 0 : rtx_ctrl.gserc_idx = tx_ctrl->gserc_idx;
176 : 0 : rtx_ctrl.lane_idx = tx_ctrl->lane_idx;
177 : 0 : rtx_ctrl.enable = tx_ctrl->enable;
178 : 0 : ret = roc_bphy_cgx_cpri_mode_tx_control(cgx->rcgx, lmac,
179 : : &rtx_ctrl);
180 : 0 : break;
181 : 0 : case CNXK_BPHY_CGX_MSG_TYPE_CPRI_MODE_MISC:
182 : 0 : mode_misc = msg->data;
183 : : memset(&rmode_misc, 0, sizeof(rmode_misc));
184 : 0 : rmode_misc.gserc_idx = mode_misc->gserc_idx;
185 : 0 : rmode_misc.lane_idx = mode_misc->lane_idx;
186 : 0 : rmode_misc.flags = mode_misc->flags;
187 : 0 : ret = roc_bphy_cgx_cpri_mode_misc(cgx->rcgx, lmac, &rmode_misc);
188 : 0 : break;
189 : : default:
190 : : return -EINVAL;
191 : : }
192 : :
193 : : /* get rid of last response if any */
194 [ # # ]: 0 : if (qp->rsp) {
195 : 0 : CNXK_BPHY_LOG(WARNING, "Previous response got overwritten");
196 : 0 : rte_free(qp->rsp);
197 : : }
198 : 0 : qp->rsp = rsp;
199 : :
200 : 0 : return ret;
201 : : }
202 : :
203 : : static int
204 : 0 : cnxk_bphy_cgx_enqueue_bufs(struct rte_rawdev *dev,
205 : : struct rte_rawdev_buf **buffers, unsigned int count,
206 : : rte_rawdev_obj_t context)
207 : : {
208 : 0 : struct cnxk_bphy_cgx *cgx = dev->dev_private;
209 : 0 : unsigned int queue = (size_t)context;
210 : : int ret;
211 : :
212 [ # # ]: 0 : if (queue >= cgx->num_queues)
213 : : return -EINVAL;
214 : :
215 [ # # ]: 0 : if (count == 0)
216 : : return 0;
217 : :
218 : 0 : ret = cnxk_bphy_cgx_process_buf(cgx, queue, buffers[0]);
219 [ # # ]: 0 : if (ret)
220 : 0 : return ret;
221 : :
222 : : return 1;
223 : : }
224 : :
225 : : static int
226 : 0 : cnxk_bphy_cgx_dequeue_bufs(struct rte_rawdev *dev,
227 : : struct rte_rawdev_buf **buffers, unsigned int count,
228 : : rte_rawdev_obj_t context)
229 : : {
230 : 0 : struct cnxk_bphy_cgx *cgx = dev->dev_private;
231 : 0 : unsigned int queue = (size_t)context;
232 : : struct cnxk_bphy_cgx_queue *qp;
233 : :
234 [ # # ]: 0 : if (queue >= cgx->num_queues)
235 : : return -EINVAL;
236 : :
237 [ # # ]: 0 : if (count == 0)
238 : : return 0;
239 : :
240 : : qp = &cgx->queues[queue];
241 [ # # ]: 0 : if (qp->rsp) {
242 : 0 : buffers[0]->buf_addr = qp->rsp;
243 : 0 : qp->rsp = NULL;
244 : :
245 : 0 : return 1;
246 : : }
247 : :
248 : : return 0;
249 : : }
250 : :
251 : : static uint16_t
252 : 0 : cnxk_bphy_cgx_queue_count(struct rte_rawdev *dev)
253 : : {
254 : 0 : struct cnxk_bphy_cgx *cgx = dev->dev_private;
255 : :
256 : 0 : return cgx->num_queues;
257 : : }
258 : :
259 : : static const struct rte_rawdev_ops cnxk_bphy_cgx_rawdev_ops = {
260 : : .queue_def_conf = cnxk_bphy_cgx_queue_def_conf,
261 : : .enqueue_bufs = cnxk_bphy_cgx_enqueue_bufs,
262 : : .dequeue_bufs = cnxk_bphy_cgx_dequeue_bufs,
263 : : .queue_count = cnxk_bphy_cgx_queue_count,
264 : : .dev_selftest = cnxk_bphy_cgx_dev_selftest,
265 : : };
266 : :
267 : : static void
268 : : cnxk_bphy_cgx_init_queues(struct cnxk_bphy_cgx *cgx)
269 : : {
270 : 0 : struct roc_bphy_cgx *rcgx = cgx->rcgx;
271 : : unsigned int i;
272 : :
273 [ # # ]: 0 : for (i = 0; i < RTE_DIM(cgx->queues); i++) {
274 [ # # ]: 0 : if (!(rcgx->lmac_bmap & BIT_ULL(i)))
275 : 0 : continue;
276 : :
277 : 0 : cgx->queues[cgx->num_queues++].lmac = i;
278 : : }
279 : : }
280 : :
281 : : static void
282 : : cnxk_bphy_cgx_fini_queues(struct cnxk_bphy_cgx *cgx)
283 : : {
284 : : unsigned int i;
285 : :
286 [ # # ]: 0 : for (i = 0; i < cgx->num_queues; i++) {
287 : 0 : rte_free(cgx->queues[i].rsp);
288 : : }
289 : :
290 : 0 : cgx->num_queues = 0;
291 : : }
292 : :
293 : : static int
294 : 0 : cnxk_bphy_cgx_rawdev_probe(struct rte_pci_driver *pci_drv,
295 : : struct rte_pci_device *pci_dev)
296 : : {
297 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
298 : : struct rte_rawdev *rawdev;
299 : : struct cnxk_bphy_cgx *cgx;
300 : : struct roc_bphy_cgx *rcgx;
301 : : int ret;
302 : :
303 : : RTE_SET_USED(pci_drv);
304 : :
305 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
306 : : return 0;
307 : :
308 [ # # ]: 0 : if (!pci_dev->mem_resource[0].addr)
309 : : return -ENODEV;
310 : :
311 : 0 : ret = roc_plt_init();
312 [ # # ]: 0 : if (ret)
313 : : return ret;
314 : :
315 : : cnxk_bphy_cgx_format_name(name, sizeof(name), pci_dev);
316 : 0 : rawdev = rte_rawdev_pmd_allocate(name, sizeof(*cgx), rte_socket_id());
317 [ # # ]: 0 : if (!rawdev)
318 : : return -ENOMEM;
319 : :
320 : 0 : rawdev->dev_ops = &cnxk_bphy_cgx_rawdev_ops;
321 : 0 : rawdev->device = &pci_dev->device;
322 : 0 : rawdev->driver_name = pci_dev->driver->driver.name;
323 : :
324 : 0 : cgx = rawdev->dev_private;
325 : 0 : cgx->rcgx = rte_zmalloc(NULL, sizeof(*rcgx), 0);
326 [ # # ]: 0 : if (!cgx->rcgx) {
327 : : ret = -ENOMEM;
328 : 0 : goto out_pmd_release;
329 : : }
330 : :
331 : : rcgx = cgx->rcgx;
332 : 0 : rcgx->bar0_pa = pci_dev->mem_resource[0].phys_addr;
333 : 0 : rcgx->bar0_va = pci_dev->mem_resource[0].addr;
334 : 0 : ret = roc_bphy_cgx_dev_init(rcgx);
335 [ # # ]: 0 : if (ret)
336 : 0 : goto out_free;
337 : :
338 : : cnxk_bphy_cgx_init_queues(cgx);
339 : :
340 : : return 0;
341 : : out_free:
342 : 0 : rte_free(rcgx);
343 : 0 : out_pmd_release:
344 : 0 : rte_rawdev_pmd_release(rawdev);
345 : :
346 : 0 : return ret;
347 : : }
348 : :
349 : : static int
350 [ # # ]: 0 : cnxk_bphy_cgx_rawdev_remove(struct rte_pci_device *pci_dev)
351 : : {
352 : : char name[RTE_RAWDEV_NAME_MAX_LEN];
353 : : struct rte_rawdev *rawdev;
354 : : struct cnxk_bphy_cgx *cgx;
355 : :
356 : : cnxk_bphy_cgx_format_name(name, sizeof(name), pci_dev);
357 : 0 : rawdev = rte_rawdev_pmd_get_named_dev(name);
358 [ # # ]: 0 : if (!rawdev)
359 : : return -ENODEV;
360 : :
361 : 0 : cgx = rawdev->dev_private;
362 : : cnxk_bphy_cgx_fini_queues(cgx);
363 : 0 : roc_bphy_cgx_dev_fini(cgx->rcgx);
364 : 0 : rte_free(cgx->rcgx);
365 : :
366 : 0 : return rte_rawdev_pmd_release(rawdev);
367 : : }
368 : :
369 : : static const struct rte_pci_id cnxk_bphy_cgx_map[] = {
370 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN9K_CGX)},
371 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_RPM)},
372 : : {} /* sentinel */
373 : : };
374 : :
375 : : static struct rte_pci_driver bphy_cgx_rawdev_pmd = {
376 : : .id_table = cnxk_bphy_cgx_map,
377 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
378 : : .probe = cnxk_bphy_cgx_rawdev_probe,
379 : : .remove = cnxk_bphy_cgx_rawdev_remove,
380 : : };
381 : :
382 : 238 : RTE_PMD_REGISTER_PCI(cnxk_bphy_cgx_rawdev_pci_driver, bphy_cgx_rawdev_pmd);
383 : : RTE_PMD_REGISTER_PCI_TABLE(cnxk_bphy_cgx_rawdev_pci_driver, cnxk_bphy_cgx_map);
384 : : RTE_PMD_REGISTER_KMOD_DEP(cnxk_bphy_cgx_rawdev_pci_driver, "vfio-pci");
|