1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2020 Marvell. */
4 #include "otx2_cpt_common.h"
5 #include "otx2_cptpf.h"
9 * CPT PF driver version, It will be incremented by 1 for every feature
10 * addition in CPT mailbox messages.
12 #define OTX2_CPT_PF_DRV_VERSION 0x1
14 static int forward_to_af(struct otx2_cptpf_dev *cptpf,
15 struct otx2_cptvf_info *vf,
16 struct mbox_msghdr *req, int size)
18 struct mbox_msghdr *msg;
21 msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
25 memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),
26 (uint8_t *)req + sizeof(struct mbox_msghdr), size);
28 msg->pcifunc = req->pcifunc;
32 otx2_mbox_msg_send(&cptpf->afpf_mbox, 0);
33 ret = otx2_mbox_wait_for_rsp(&cptpf->afpf_mbox, 0);
35 dev_err(&cptpf->pdev->dev, "RVU MBOX timeout.\n");
38 dev_err(&cptpf->pdev->dev, "RVU MBOX error: %d.\n", ret);
44 static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,
45 struct otx2_cptvf_info *vf,
46 struct mbox_msghdr *req)
48 struct otx2_cpt_caps_rsp *rsp;
50 rsp = (struct otx2_cpt_caps_rsp *)
51 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,
56 rsp->hdr.id = MBOX_MSG_GET_CAPS;
57 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
58 rsp->hdr.pcifunc = req->pcifunc;
59 rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;
60 rsp->cpt_revision = cptpf->pdev->revision;
61 memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));
66 static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,
67 struct otx2_cptvf_info *vf,
68 struct mbox_msghdr *req)
70 struct otx2_cpt_egrp_num_msg *grp_req;
71 struct otx2_cpt_egrp_num_rsp *rsp;
73 grp_req = (struct otx2_cpt_egrp_num_msg *)req;
74 rsp = (struct otx2_cpt_egrp_num_rsp *)
75 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
79 rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;
80 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
81 rsp->hdr.pcifunc = req->pcifunc;
82 rsp->eng_type = grp_req->eng_type;
83 rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
89 static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
90 struct otx2_cptvf_info *vf,
91 struct mbox_msghdr *req)
93 struct otx2_cpt_kvf_limits_rsp *rsp;
95 rsp = (struct otx2_cpt_kvf_limits_rsp *)
96 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
100 rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;
101 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
102 rsp->hdr.pcifunc = req->pcifunc;
103 rsp->kvf_limits = cptpf->kvf_limits;
108 static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
109 struct otx2_cptvf_info *vf,
110 struct mbox_msghdr *req, int size)
114 /* Check if msg is valid, if not reply with an invalid msg */
115 if (req->sig != OTX2_MBOX_REQ_SIG)
119 case MBOX_MSG_GET_ENG_GRP_NUM:
120 err = handle_msg_get_eng_grp_num(cptpf, vf, req);
122 case MBOX_MSG_GET_CAPS:
123 err = handle_msg_get_caps(cptpf, vf, req);
125 case MBOX_MSG_GET_KVF_LIMITS:
126 err = handle_msg_kvf_limits(cptpf, vf, req);
129 err = forward_to_af(cptpf, vf, req, size);
135 otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);
136 otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);
140 irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)
142 struct otx2_cptpf_dev *cptpf = arg;
143 struct otx2_cptvf_info *vf;
148 * Check which VF has raised an interrupt and schedule
149 * corresponding work queue to process the messages
151 for (i = 0; i < 2; i++) {
152 /* Read the interrupt bits */
153 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,
154 RVU_PF_VFPF_MBOX_INTX(i));
156 for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {
157 vf = &cptpf->vf[vf_idx];
158 if (intr & (1ULL << vf->intr_idx)) {
159 queue_work(cptpf->vfpf_mbox_wq,
160 &vf->vfpf_mbox_work);
161 /* Clear the interrupt */
162 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,
163 0, RVU_PF_VFPF_MBOX_INTX(i),
164 BIT_ULL(vf->intr_idx));
171 void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
173 struct otx2_cptpf_dev *cptpf;
174 struct otx2_cptvf_info *vf;
175 struct otx2_mbox_dev *mdev;
176 struct mbox_hdr *req_hdr;
177 struct mbox_msghdr *msg;
178 struct otx2_mbox *mbox;
181 vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);
183 mbox = &cptpf->vfpf_mbox;
184 /* sync with mbox memory region */
186 mdev = &mbox->dev[vf->vf_id];
187 /* Process received mbox messages */
188 req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
189 offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
191 for (i = 0; i < req_hdr->num_msgs; i++) {
192 msg = (struct mbox_msghdr *)(mdev->mbase + offset);
194 /* Set which VF sent this message based on mbox IRQ */
195 msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |
196 ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);
198 err = cptpf_handle_vf_req(cptpf, vf, msg,
199 msg->next_msgoff - offset);
201 * Behave as the AF, drop the msg if there is
202 * no memory, timeout handling also goes here
204 if (err == -ENOMEM || err == -EIO)
206 offset = msg->next_msgoff;
208 /* Send mbox responses to VF */
210 otx2_mbox_msg_send(mbox, vf->vf_id);
213 irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
215 struct otx2_cptpf_dev *cptpf = arg;
218 /* Read the interrupt bits */
219 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
222 /* Schedule work queue function to process the MBOX request */
223 queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
224 /* Clear and ack the interrupt */
225 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
231 static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
232 struct mbox_msghdr *msg)
234 struct device *dev = &cptpf->pdev->dev;
235 struct cpt_rd_wr_reg_msg *rsp_rd_wr;
237 if (msg->id >= MBOX_MSG_MAX) {
238 dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);
241 if (msg->sig != OTX2_MBOX_RSP_SIG) {
242 dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",
249 cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &
252 case MBOX_MSG_CPT_RD_WR_REGISTER:
253 rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;
255 dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",
256 rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,
260 if (!rsp_rd_wr->is_write)
261 *rsp_rd_wr->ret_val = rsp_rd_wr->val;
263 case MBOX_MSG_ATTACH_RESOURCES:
265 cptpf->lfs.are_lfs_attached = 1;
267 case MBOX_MSG_DETACH_RESOURCES:
269 cptpf->lfs.are_lfs_attached = 0;
274 "Unsupported msg %d received.\n", msg->id);
279 static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,
282 struct otx2_mbox *vfpf_mbox;
283 struct mbox_msghdr *fwd;
285 if (msg->id >= MBOX_MSG_MAX) {
286 dev_err(&cptpf->pdev->dev,
287 "MBOX msg with unknown ID %d\n", msg->id);
290 if (msg->sig != OTX2_MBOX_RSP_SIG) {
291 dev_err(&cptpf->pdev->dev,
292 "MBOX msg with wrong signature %x, ID %d\n",
296 vfpf_mbox = &cptpf->vfpf_mbox;
298 if (vf_id >= cptpf->enabled_vfs) {
299 dev_err(&cptpf->pdev->dev,
300 "MBOX msg to unknown VF: %d >= %d\n",
301 vf_id, cptpf->enabled_vfs);
304 if (msg->id == MBOX_MSG_VF_FLR)
307 fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);
309 dev_err(&cptpf->pdev->dev,
310 "Forwarding to VF%d failed.\n", vf_id);
313 memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),
314 (uint8_t *)msg + sizeof(struct mbox_msghdr), size);
316 fwd->pcifunc = msg->pcifunc;
322 /* Handle mailbox messages received from AF */
323 void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
325 struct otx2_cptpf_dev *cptpf;
326 struct otx2_mbox *afpf_mbox;
327 struct otx2_mbox_dev *mdev;
328 struct mbox_hdr *rsp_hdr;
329 struct mbox_msghdr *msg;
330 int offset, vf_id, i;
332 cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);
333 afpf_mbox = &cptpf->afpf_mbox;
334 mdev = &afpf_mbox->dev[0];
335 /* Sync mbox data into memory */
338 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);
339 offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
341 for (i = 0; i < rsp_hdr->num_msgs; i++) {
342 msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +
344 vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &
347 forward_to_vf(cptpf, msg, vf_id,
348 msg->next_msgoff - offset);
350 process_afpf_mbox_msg(cptpf, msg);
352 offset = msg->next_msgoff;
355 otx2_mbox_reset(afpf_mbox, 0);