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