1 // SPDX-License-Identifier: GPL-2.0
2 /* Marvell OcteonTx2 RVU Admin Function driver
4 * Copyright (C) 2018 Marvell International Ltd.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/types.h>
12 #include <linux/module.h>
13 #include <linux/pci.h>
18 struct cgx_evq_entry
{
19 struct list_head evq_node
;
20 struct cgx_link_event link_event
;
23 #define M(_name, _id, _fn_name, _req_type, _rsp_type) \
24 static struct _req_type __maybe_unused \
25 *otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \
27 struct _req_type *req; \
29 req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \
30 &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \
31 sizeof(struct _rsp_type)); \
34 req->hdr.sig = OTX2_MBOX_REQ_SIG; \
42 /* Returns bitmap of mapped PFs */
43 static inline u16
cgxlmac_to_pfmap(struct rvu
*rvu
, u8 cgx_id
, u8 lmac_id
)
45 return rvu
->cgxlmac2pf_map
[CGX_OFFSET(cgx_id
) + lmac_id
];
48 static inline u8
cgxlmac_id_to_bmap(u8 cgx_id
, u8 lmac_id
)
50 return ((cgx_id
& 0xF) << 4) | (lmac_id
& 0xF);
53 void *rvu_cgx_pdata(u8 cgx_id
, struct rvu
*rvu
)
55 if (cgx_id
>= rvu
->cgx_cnt_max
)
58 return rvu
->cgx_idmap
[cgx_id
];
61 static int rvu_map_cgx_lmac_pf(struct rvu
*rvu
)
63 struct npc_pkind
*pkind
= &rvu
->hw
->pkind
;
64 int cgx_cnt_max
= rvu
->cgx_cnt_max
;
65 int cgx
, lmac_cnt
, lmac
;
66 int pf
= PF_CGXMAP_BASE
;
72 if (cgx_cnt_max
> 0xF || MAX_LMAC_PER_CGX
> 0xF)
76 * An additional entry is required since PF id starts from 1 and
77 * hence entry at offset 0 is invalid.
79 size
= (cgx_cnt_max
* MAX_LMAC_PER_CGX
+ 1) * sizeof(u8
);
80 rvu
->pf2cgxlmac_map
= devm_kmalloc(rvu
->dev
, size
, GFP_KERNEL
);
81 if (!rvu
->pf2cgxlmac_map
)
84 /* Initialize all entries with an invalid cgx and lmac id */
85 memset(rvu
->pf2cgxlmac_map
, 0xFF, size
);
87 /* Reverse map table */
88 rvu
->cgxlmac2pf_map
= devm_kzalloc(rvu
->dev
,
89 cgx_cnt_max
* MAX_LMAC_PER_CGX
* sizeof(u16
),
91 if (!rvu
->cgxlmac2pf_map
)
94 rvu
->cgx_mapped_pfs
= 0;
95 for (cgx
= 0; cgx
< cgx_cnt_max
; cgx
++) {
96 if (!rvu_cgx_pdata(cgx
, rvu
))
98 lmac_cnt
= cgx_get_lmac_cnt(rvu_cgx_pdata(cgx
, rvu
));
99 for (lmac
= 0; lmac
< lmac_cnt
; lmac
++, pf
++) {
100 rvu
->pf2cgxlmac_map
[pf
] = cgxlmac_id_to_bmap(cgx
, lmac
);
101 rvu
->cgxlmac2pf_map
[CGX_OFFSET(cgx
) + lmac
] = 1 << pf
;
102 free_pkind
= rvu_alloc_rsrc(&pkind
->rsrc
);
103 pkind
->pfchan_map
[free_pkind
] = ((pf
) & 0x3F) << 16;
104 rvu
->cgx_mapped_pfs
++;
110 static int rvu_cgx_send_link_info(int cgx_id
, int lmac_id
, struct rvu
*rvu
)
112 struct cgx_evq_entry
*qentry
;
116 qentry
= kmalloc(sizeof(*qentry
), GFP_KERNEL
);
120 /* Lock the event queue before we read the local link status */
121 spin_lock_irqsave(&rvu
->cgx_evq_lock
, flags
);
122 err
= cgx_get_link_info(rvu_cgx_pdata(cgx_id
, rvu
), lmac_id
,
123 &qentry
->link_event
.link_uinfo
);
124 qentry
->link_event
.cgx_id
= cgx_id
;
125 qentry
->link_event
.lmac_id
= lmac_id
;
128 list_add_tail(&qentry
->evq_node
, &rvu
->cgx_evq_head
);
130 spin_unlock_irqrestore(&rvu
->cgx_evq_lock
, flags
);
132 /* start worker to process the events */
133 queue_work(rvu
->cgx_evh_wq
, &rvu
->cgx_evh_work
);
138 /* This is called from interrupt context and is expected to be atomic */
139 static int cgx_lmac_postevent(struct cgx_link_event
*event
, void *data
)
141 struct cgx_evq_entry
*qentry
;
142 struct rvu
*rvu
= data
;
144 /* post event to the event queue */
145 qentry
= kmalloc(sizeof(*qentry
), GFP_ATOMIC
);
148 qentry
->link_event
= *event
;
149 spin_lock(&rvu
->cgx_evq_lock
);
150 list_add_tail(&qentry
->evq_node
, &rvu
->cgx_evq_head
);
151 spin_unlock(&rvu
->cgx_evq_lock
);
153 /* start worker to process the events */
154 queue_work(rvu
->cgx_evh_wq
, &rvu
->cgx_evh_work
);
159 static void cgx_notify_pfs(struct cgx_link_event
*event
, struct rvu
*rvu
)
161 struct cgx_link_user_info
*linfo
;
162 struct cgx_link_info_msg
*msg
;
166 linfo
= &event
->link_uinfo
;
167 pfmap
= cgxlmac_to_pfmap(rvu
, event
->cgx_id
, event
->lmac_id
);
170 pfid
= find_first_bit(&pfmap
, 16);
171 clear_bit(pfid
, &pfmap
);
173 /* check if notification is enabled */
174 if (!test_bit(pfid
, &rvu
->pf_notify_bmap
)) {
175 dev_info(rvu
->dev
, "cgx %d: lmac %d Link status %s\n",
176 event
->cgx_id
, event
->lmac_id
,
177 linfo
->link_up
? "UP" : "DOWN");
181 /* Send mbox message to PF */
182 msg
= otx2_mbox_alloc_msg_cgx_link_event(rvu
, pfid
);
185 msg
->link_info
= *linfo
;
186 otx2_mbox_msg_send(&rvu
->afpf_wq_info
.mbox_up
, pfid
);
187 err
= otx2_mbox_wait_for_rsp(&rvu
->afpf_wq_info
.mbox_up
, pfid
);
189 dev_warn(rvu
->dev
, "notification to pf %d failed\n",
194 static void cgx_evhandler_task(struct work_struct
*work
)
196 struct rvu
*rvu
= container_of(work
, struct rvu
, cgx_evh_work
);
197 struct cgx_evq_entry
*qentry
;
198 struct cgx_link_event
*event
;
202 /* Dequeue an event */
203 spin_lock_irqsave(&rvu
->cgx_evq_lock
, flags
);
204 qentry
= list_first_entry_or_null(&rvu
->cgx_evq_head
,
205 struct cgx_evq_entry
,
208 list_del(&qentry
->evq_node
);
209 spin_unlock_irqrestore(&rvu
->cgx_evq_lock
, flags
);
211 break; /* nothing more to process */
213 event
= &qentry
->link_event
;
216 cgx_notify_pfs(event
, rvu
);
221 static int cgx_lmac_event_handler_init(struct rvu
*rvu
)
223 struct cgx_event_cb cb
;
227 spin_lock_init(&rvu
->cgx_evq_lock
);
228 INIT_LIST_HEAD(&rvu
->cgx_evq_head
);
229 INIT_WORK(&rvu
->cgx_evh_work
, cgx_evhandler_task
);
230 rvu
->cgx_evh_wq
= alloc_workqueue("rvu_evh_wq", 0, 0);
231 if (!rvu
->cgx_evh_wq
) {
232 dev_err(rvu
->dev
, "alloc workqueue failed");
236 cb
.notify_link_chg
= cgx_lmac_postevent
; /* link change call back */
239 for (cgx
= 0; cgx
<= rvu
->cgx_cnt_max
; cgx
++) {
240 cgxd
= rvu_cgx_pdata(cgx
, rvu
);
243 for (lmac
= 0; lmac
< cgx_get_lmac_cnt(cgxd
); lmac
++) {
244 err
= cgx_lmac_evh_register(&cb
, cgxd
, lmac
);
247 "%d:%d handler register failed\n",
255 static void rvu_cgx_wq_destroy(struct rvu
*rvu
)
257 if (rvu
->cgx_evh_wq
) {
258 flush_workqueue(rvu
->cgx_evh_wq
);
259 destroy_workqueue(rvu
->cgx_evh_wq
);
260 rvu
->cgx_evh_wq
= NULL
;
264 int rvu_cgx_init(struct rvu
*rvu
)
269 /* CGX port id starts from 0 and are not necessarily contiguous
270 * Hence we allocate resources based on the maximum port id value.
272 rvu
->cgx_cnt_max
= cgx_get_cgxcnt_max();
273 if (!rvu
->cgx_cnt_max
) {
274 dev_info(rvu
->dev
, "No CGX devices found!\n");
278 rvu
->cgx_idmap
= devm_kzalloc(rvu
->dev
, rvu
->cgx_cnt_max
*
279 sizeof(void *), GFP_KERNEL
);
283 /* Initialize the cgxdata table */
284 for (cgx
= 0; cgx
< rvu
->cgx_cnt_max
; cgx
++)
285 rvu
->cgx_idmap
[cgx
] = cgx_get_pdata(cgx
);
287 /* Map CGX LMAC interfaces to RVU PFs */
288 err
= rvu_map_cgx_lmac_pf(rvu
);
292 /* Register for CGX events */
293 err
= cgx_lmac_event_handler_init(rvu
);
297 /* Ensure event handler registration is completed, before
298 * we turn on the links
302 /* Do link up for all CGX ports */
303 for (cgx
= 0; cgx
<= rvu
->cgx_cnt_max
; cgx
++) {
304 cgxd
= rvu_cgx_pdata(cgx
, rvu
);
307 err
= cgx_lmac_linkup_start(cgxd
);
310 "Link up process failed to start on cgx %d\n",
317 int rvu_cgx_exit(struct rvu
*rvu
)
322 for (cgx
= 0; cgx
<= rvu
->cgx_cnt_max
; cgx
++) {
323 cgxd
= rvu_cgx_pdata(cgx
, rvu
);
326 for (lmac
= 0; lmac
< cgx_get_lmac_cnt(cgxd
); lmac
++)
327 cgx_lmac_evh_unregister(cgxd
, lmac
);
330 /* Ensure event handler unregister is completed */
333 rvu_cgx_wq_destroy(rvu
);
337 int rvu_cgx_config_rxtx(struct rvu
*rvu
, u16 pcifunc
, bool start
)
339 int pf
= rvu_get_pf(pcifunc
);
342 /* This msg is expected only from PFs that are mapped to CGX LMACs,
343 * if received from other PF/VF simply ACK, nothing to do.
345 if ((pcifunc
& RVU_PFVF_FUNC_MASK
) || !is_pf_cgxmapped(rvu
, pf
))
348 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
350 cgx_lmac_rx_tx_enable(rvu_cgx_pdata(cgx_id
, rvu
), lmac_id
, start
);
355 int rvu_mbox_handler_cgx_start_rxtx(struct rvu
*rvu
, struct msg_req
*req
,
358 rvu_cgx_config_rxtx(rvu
, req
->hdr
.pcifunc
, true);
362 int rvu_mbox_handler_cgx_stop_rxtx(struct rvu
*rvu
, struct msg_req
*req
,
365 rvu_cgx_config_rxtx(rvu
, req
->hdr
.pcifunc
, false);
369 int rvu_mbox_handler_cgx_stats(struct rvu
*rvu
, struct msg_req
*req
,
370 struct cgx_stats_rsp
*rsp
)
372 int pf
= rvu_get_pf(req
->hdr
.pcifunc
);
373 int stat
= 0, err
= 0;
374 u64 tx_stat
, rx_stat
;
378 if ((req
->hdr
.pcifunc
& RVU_PFVF_FUNC_MASK
) ||
379 !is_pf_cgxmapped(rvu
, pf
))
382 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_idx
, &lmac
);
383 cgxd
= rvu_cgx_pdata(cgx_idx
, rvu
);
386 while (stat
< CGX_RX_STATS_COUNT
) {
387 err
= cgx_get_rx_stats(cgxd
, lmac
, stat
, &rx_stat
);
390 rsp
->rx_stats
[stat
] = rx_stat
;
396 while (stat
< CGX_TX_STATS_COUNT
) {
397 err
= cgx_get_tx_stats(cgxd
, lmac
, stat
, &tx_stat
);
400 rsp
->tx_stats
[stat
] = tx_stat
;
406 int rvu_mbox_handler_cgx_mac_addr_set(struct rvu
*rvu
,
407 struct cgx_mac_addr_set_or_get
*req
,
408 struct cgx_mac_addr_set_or_get
*rsp
)
410 int pf
= rvu_get_pf(req
->hdr
.pcifunc
);
413 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
415 cgx_lmac_addr_set(cgx_id
, lmac_id
, req
->mac_addr
);
420 int rvu_mbox_handler_cgx_mac_addr_get(struct rvu
*rvu
,
421 struct cgx_mac_addr_set_or_get
*req
,
422 struct cgx_mac_addr_set_or_get
*rsp
)
424 int pf
= rvu_get_pf(req
->hdr
.pcifunc
);
429 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
432 cfg
= cgx_lmac_addr_get(cgx_id
, lmac_id
);
433 /* copy 48 bit mac address to req->mac_addr */
434 for (i
= 0; i
< ETH_ALEN
; i
++)
435 rsp
->mac_addr
[i
] = cfg
>> (ETH_ALEN
- 1 - i
) * 8;
439 int rvu_mbox_handler_cgx_promisc_enable(struct rvu
*rvu
, struct msg_req
*req
,
442 u16 pcifunc
= req
->hdr
.pcifunc
;
443 int pf
= rvu_get_pf(pcifunc
);
446 /* This msg is expected only from PFs that are mapped to CGX LMACs,
447 * if received from other PF/VF simply ACK, nothing to do.
449 if ((req
->hdr
.pcifunc
& RVU_PFVF_FUNC_MASK
) ||
450 !is_pf_cgxmapped(rvu
, pf
))
453 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
455 cgx_lmac_promisc_config(cgx_id
, lmac_id
, true);
459 int rvu_mbox_handler_cgx_promisc_disable(struct rvu
*rvu
, struct msg_req
*req
,
462 u16 pcifunc
= req
->hdr
.pcifunc
;
463 int pf
= rvu_get_pf(pcifunc
);
466 /* This msg is expected only from PFs that are mapped to CGX LMACs,
467 * if received from other PF/VF simply ACK, nothing to do.
469 if ((req
->hdr
.pcifunc
& RVU_PFVF_FUNC_MASK
) ||
470 !is_pf_cgxmapped(rvu
, pf
))
473 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
475 cgx_lmac_promisc_config(cgx_id
, lmac_id
, false);
479 static int rvu_cgx_config_linkevents(struct rvu
*rvu
, u16 pcifunc
, bool en
)
481 int pf
= rvu_get_pf(pcifunc
);
484 /* This msg is expected only from PFs that are mapped to CGX LMACs,
485 * if received from other PF/VF simply ACK, nothing to do.
487 if ((pcifunc
& RVU_PFVF_FUNC_MASK
) || !is_pf_cgxmapped(rvu
, pf
))
490 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
493 set_bit(pf
, &rvu
->pf_notify_bmap
);
494 /* Send the current link status to PF */
495 rvu_cgx_send_link_info(cgx_id
, lmac_id
, rvu
);
497 clear_bit(pf
, &rvu
->pf_notify_bmap
);
503 int rvu_mbox_handler_cgx_start_linkevents(struct rvu
*rvu
, struct msg_req
*req
,
506 rvu_cgx_config_linkevents(rvu
, req
->hdr
.pcifunc
, true);
510 int rvu_mbox_handler_cgx_stop_linkevents(struct rvu
*rvu
, struct msg_req
*req
,
513 rvu_cgx_config_linkevents(rvu
, req
->hdr
.pcifunc
, false);
517 int rvu_mbox_handler_cgx_get_linkinfo(struct rvu
*rvu
, struct msg_req
*req
,
518 struct cgx_link_info_msg
*rsp
)
523 pf
= rvu_get_pf(req
->hdr
.pcifunc
);
525 if (!is_pf_cgxmapped(rvu
, pf
))
528 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
530 err
= cgx_get_link_info(rvu_cgx_pdata(cgx_id
, rvu
), lmac_id
,
535 static int rvu_cgx_config_intlbk(struct rvu
*rvu
, u16 pcifunc
, bool en
)
537 int pf
= rvu_get_pf(pcifunc
);
540 /* This msg is expected only from PFs that are mapped to CGX LMACs,
541 * if received from other PF/VF simply ACK, nothing to do.
543 if ((pcifunc
& RVU_PFVF_FUNC_MASK
) || !is_pf_cgxmapped(rvu
, pf
))
546 rvu_get_cgx_lmac_id(rvu
->pf2cgxlmac_map
[pf
], &cgx_id
, &lmac_id
);
548 return cgx_lmac_internal_loopback(rvu_cgx_pdata(cgx_id
, rvu
),
552 int rvu_mbox_handler_cgx_intlbk_enable(struct rvu
*rvu
, struct msg_req
*req
,
555 rvu_cgx_config_intlbk(rvu
, req
->hdr
.pcifunc
, true);
559 int rvu_mbox_handler_cgx_intlbk_disable(struct rvu
*rvu
, struct msg_req
*req
,
562 rvu_cgx_config_intlbk(rvu
, req
->hdr
.pcifunc
, false);