1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2020 Marvell. */
3
4 #include "otx2_cpt_common.h"
5 #include "otx2_cptpf.h"
6 #include "rvu_reg.h"
7
8 /*
9 * CPT PF driver version, It will be incremented by 1 for every feature
10 * addition in CPT mailbox messages.
11 */
12 #define OTX2_CPT_PF_DRV_VERSION 0x1
13
forward_to_af(struct otx2_cptpf_dev * cptpf,struct otx2_cptvf_info * vf,struct mbox_msghdr * req,int size)14 static int forward_to_af(struct otx2_cptpf_dev *cptpf,
15 struct otx2_cptvf_info *vf,
16 struct mbox_msghdr *req, int size)
17 {
18 struct mbox_msghdr *msg;
19 int ret;
20
21 mutex_lock(&cptpf->lock);
22 msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
23 if (msg == NULL) {
24 mutex_unlock(&cptpf->lock);
25 return -ENOMEM;
26 }
27
28 memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),
29 (uint8_t *)req + sizeof(struct mbox_msghdr), size);
30 msg->id = req->id;
31 msg->pcifunc = req->pcifunc;
32 msg->sig = req->sig;
33 msg->ver = req->ver;
34
35 ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);
36 /* Error code -EIO indicate there is a communication failure
37 * to the AF. Rest of the error codes indicate that AF processed
38 * VF messages and set the error codes in response messages
39 * (if any) so simply forward responses to VF.
40 */
41 if (ret == -EIO) {
42 dev_warn(&cptpf->pdev->dev,
43 "AF not responding to VF%d messages\n", vf->vf_id);
44 mutex_unlock(&cptpf->lock);
45 return ret;
46 }
47 mutex_unlock(&cptpf->lock);
48 return 0;
49 }
50
handle_msg_get_caps(struct otx2_cptpf_dev * cptpf,struct otx2_cptvf_info * vf,struct mbox_msghdr * req)51 static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,
52 struct otx2_cptvf_info *vf,
53 struct mbox_msghdr *req)
54 {
55 struct otx2_cpt_caps_rsp *rsp;
56
57 rsp = (struct otx2_cpt_caps_rsp *)
58 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,
59 sizeof(*rsp));
60 if (!rsp)
61 return -ENOMEM;
62
63 rsp->hdr.id = MBOX_MSG_GET_CAPS;
64 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
65 rsp->hdr.pcifunc = req->pcifunc;
66 rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;
67 rsp->cpt_revision = cptpf->pdev->revision;
68 memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));
69
70 return 0;
71 }
72
handle_msg_get_eng_grp_num(struct otx2_cptpf_dev * cptpf,struct otx2_cptvf_info * vf,struct mbox_msghdr * req)73 static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,
74 struct otx2_cptvf_info *vf,
75 struct mbox_msghdr *req)
76 {
77 struct otx2_cpt_egrp_num_msg *grp_req;
78 struct otx2_cpt_egrp_num_rsp *rsp;
79
80 grp_req = (struct otx2_cpt_egrp_num_msg *)req;
81 rsp = (struct otx2_cpt_egrp_num_rsp *)
82 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
83 if (!rsp)
84 return -ENOMEM;
85
86 rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;
87 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
88 rsp->hdr.pcifunc = req->pcifunc;
89 rsp->eng_type = grp_req->eng_type;
90 rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
91 grp_req->eng_type);
92
93 return 0;
94 }
95
handle_msg_kvf_limits(struct otx2_cptpf_dev * cptpf,struct otx2_cptvf_info * vf,struct mbox_msghdr * req)96 static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
97 struct otx2_cptvf_info *vf,
98 struct mbox_msghdr *req)
99 {
100 struct otx2_cpt_kvf_limits_rsp *rsp;
101
102 rsp = (struct otx2_cpt_kvf_limits_rsp *)
103 otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
104 if (!rsp)
105 return -ENOMEM;
106
107 rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;
108 rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
109 rsp->hdr.pcifunc = req->pcifunc;
110 rsp->kvf_limits = cptpf->kvf_limits;
111
112 return 0;
113 }
114
cptpf_handle_vf_req(struct otx2_cptpf_dev * cptpf,struct otx2_cptvf_info * vf,struct mbox_msghdr * req,int size)115 static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
116 struct otx2_cptvf_info *vf,
117 struct mbox_msghdr *req, int size)
118 {
119 int err = 0;
120
121 /* Check if msg is valid, if not reply with an invalid msg */
122 if (req->sig != OTX2_MBOX_REQ_SIG)
123 goto inval_msg;
124
125 switch (req->id) {
126 case MBOX_MSG_GET_ENG_GRP_NUM:
127 err = handle_msg_get_eng_grp_num(cptpf, vf, req);
128 break;
129 case MBOX_MSG_GET_CAPS:
130 err = handle_msg_get_caps(cptpf, vf, req);
131 break;
132 case MBOX_MSG_GET_KVF_LIMITS:
133 err = handle_msg_kvf_limits(cptpf, vf, req);
134 break;
135 default:
136 err = forward_to_af(cptpf, vf, req, size);
137 break;
138 }
139 return err;
140
141 inval_msg:
142 otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);
143 otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);
144 return err;
145 }
146
otx2_cptpf_vfpf_mbox_intr(int __always_unused irq,void * arg)147 irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)
148 {
149 struct otx2_cptpf_dev *cptpf = arg;
150 struct otx2_cptvf_info *vf;
151 int i, vf_idx;
152 u64 intr;
153
154 /*
155 * Check which VF has raised an interrupt and schedule
156 * corresponding work queue to process the messages
157 */
158 for (i = 0; i < 2; i++) {
159 /* Read the interrupt bits */
160 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,
161 RVU_PF_VFPF_MBOX_INTX(i));
162
163 for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {
164 vf = &cptpf->vf[vf_idx];
165 if (intr & (1ULL << vf->intr_idx)) {
166 queue_work(cptpf->vfpf_mbox_wq,
167 &vf->vfpf_mbox_work);
168 /* Clear the interrupt */
169 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,
170 0, RVU_PF_VFPF_MBOX_INTX(i),
171 BIT_ULL(vf->intr_idx));
172 }
173 }
174 }
175 return IRQ_HANDLED;
176 }
177
otx2_cptpf_vfpf_mbox_handler(struct work_struct * work)178 void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
179 {
180 struct otx2_cptpf_dev *cptpf;
181 struct otx2_cptvf_info *vf;
182 struct otx2_mbox_dev *mdev;
183 struct mbox_hdr *req_hdr;
184 struct mbox_msghdr *msg;
185 struct otx2_mbox *mbox;
186 int offset, i, err;
187
188 vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);
189 cptpf = vf->cptpf;
190 mbox = &cptpf->vfpf_mbox;
191 /* sync with mbox memory region */
192 smp_rmb();
193 mdev = &mbox->dev[vf->vf_id];
194 /* Process received mbox messages */
195 req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
196 offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
197
198 for (i = 0; i < req_hdr->num_msgs; i++) {
199 msg = (struct mbox_msghdr *)(mdev->mbase + offset);
200
201 /* Set which VF sent this message based on mbox IRQ */
202 msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |
203 ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);
204
205 err = cptpf_handle_vf_req(cptpf, vf, msg,
206 msg->next_msgoff - offset);
207 /*
208 * Behave as the AF, drop the msg if there is
209 * no memory, timeout handling also goes here
210 */
211 if (err == -ENOMEM || err == -EIO)
212 break;
213 offset = msg->next_msgoff;
214 /* Write barrier required for VF responses which are handled by
215 * PF driver and not forwarded to AF.
216 */
217 smp_wmb();
218 }
219 /* Send mbox responses to VF */
220 if (mdev->num_msgs)
221 otx2_mbox_msg_send(mbox, vf->vf_id);
222 }
223
otx2_cptpf_afpf_mbox_intr(int __always_unused irq,void * arg)224 irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
225 {
226 struct otx2_cptpf_dev *cptpf = arg;
227 u64 intr;
228
229 /* Read the interrupt bits */
230 intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
231
232 if (intr & 0x1ULL) {
233 /* Schedule work queue function to process the MBOX request */
234 queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
235 /* Clear and ack the interrupt */
236 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
237 0x1ULL);
238 }
239 return IRQ_HANDLED;
240 }
241
process_afpf_mbox_msg(struct otx2_cptpf_dev * cptpf,struct mbox_msghdr * msg)242 static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
243 struct mbox_msghdr *msg)
244 {
245 struct device *dev = &cptpf->pdev->dev;
246 struct cpt_rd_wr_reg_msg *rsp_rd_wr;
247
248 if (msg->id >= MBOX_MSG_MAX) {
249 dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);
250 return;
251 }
252 if (msg->sig != OTX2_MBOX_RSP_SIG) {
253 dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",
254 msg->sig, msg->id);
255 return;
256 }
257
258 switch (msg->id) {
259 case MBOX_MSG_READY:
260 cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &
261 RVU_PFVF_PF_MASK;
262 break;
263 case MBOX_MSG_CPT_RD_WR_REGISTER:
264 rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;
265 if (msg->rc) {
266 dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",
267 rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,
268 msg->rc);
269 return;
270 }
271 if (!rsp_rd_wr->is_write)
272 *rsp_rd_wr->ret_val = rsp_rd_wr->val;
273 break;
274 case MBOX_MSG_ATTACH_RESOURCES:
275 if (!msg->rc)
276 cptpf->lfs.are_lfs_attached = 1;
277 break;
278 case MBOX_MSG_DETACH_RESOURCES:
279 if (!msg->rc)
280 cptpf->lfs.are_lfs_attached = 0;
281 break;
282
283 default:
284 dev_err(dev,
285 "Unsupported msg %d received.\n", msg->id);
286 break;
287 }
288 }
289
forward_to_vf(struct otx2_cptpf_dev * cptpf,struct mbox_msghdr * msg,int vf_id,int size)290 static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,
291 int vf_id, int size)
292 {
293 struct otx2_mbox *vfpf_mbox;
294 struct mbox_msghdr *fwd;
295
296 if (msg->id >= MBOX_MSG_MAX) {
297 dev_err(&cptpf->pdev->dev,
298 "MBOX msg with unknown ID %d\n", msg->id);
299 return;
300 }
301 if (msg->sig != OTX2_MBOX_RSP_SIG) {
302 dev_err(&cptpf->pdev->dev,
303 "MBOX msg with wrong signature %x, ID %d\n",
304 msg->sig, msg->id);
305 return;
306 }
307 vfpf_mbox = &cptpf->vfpf_mbox;
308 vf_id--;
309 if (vf_id >= cptpf->enabled_vfs) {
310 dev_err(&cptpf->pdev->dev,
311 "MBOX msg to unknown VF: %d >= %d\n",
312 vf_id, cptpf->enabled_vfs);
313 return;
314 }
315 if (msg->id == MBOX_MSG_VF_FLR)
316 return;
317
318 fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);
319 if (!fwd) {
320 dev_err(&cptpf->pdev->dev,
321 "Forwarding to VF%d failed.\n", vf_id);
322 return;
323 }
324 memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),
325 (uint8_t *)msg + sizeof(struct mbox_msghdr), size);
326 fwd->id = msg->id;
327 fwd->pcifunc = msg->pcifunc;
328 fwd->sig = msg->sig;
329 fwd->ver = msg->ver;
330 fwd->rc = msg->rc;
331 }
332
333 /* Handle mailbox messages received from AF */
otx2_cptpf_afpf_mbox_handler(struct work_struct * work)334 void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
335 {
336 struct otx2_cptpf_dev *cptpf;
337 struct otx2_mbox *afpf_mbox;
338 struct otx2_mbox_dev *mdev;
339 struct mbox_hdr *rsp_hdr;
340 struct mbox_msghdr *msg;
341 int offset, vf_id, i;
342
343 cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);
344 afpf_mbox = &cptpf->afpf_mbox;
345 mdev = &afpf_mbox->dev[0];
346 /* Sync mbox data into memory */
347 smp_wmb();
348
349 rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);
350 offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
351
352 for (i = 0; i < rsp_hdr->num_msgs; i++) {
353 msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +
354 offset);
355 vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &
356 RVU_PFVF_FUNC_MASK;
357 if (vf_id > 0)
358 forward_to_vf(cptpf, msg, vf_id,
359 msg->next_msgoff - offset);
360 else
361 process_afpf_mbox_msg(cptpf, msg);
362
363 offset = msg->next_msgoff;
364 /* Sync VF response ready to be sent */
365 smp_wmb();
366 mdev->msgs_acked++;
367 }
368 otx2_mbox_reset(afpf_mbox, 0);
369 }
370