xref: /linux/drivers/crypto/cavium/cpt/cptvf_mbox.c (revision 2f4c53349961c8ca480193e47da4d44fdb8335a8)
1*25763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c694b233SGeorge Cherian /*
3c694b233SGeorge Cherian  * Copyright (C) 2016 Cavium, Inc.
4c694b233SGeorge Cherian  */
5c694b233SGeorge Cherian 
6c694b233SGeorge Cherian #include "cptvf.h"
7c694b233SGeorge Cherian 
8c694b233SGeorge Cherian static void cptvf_send_msg_to_pf(struct cpt_vf *cptvf, struct cpt_mbox *mbx)
9c694b233SGeorge Cherian {
10c694b233SGeorge Cherian 	/* Writing mbox(1) causes interrupt */
11c694b233SGeorge Cherian 	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0),
12c694b233SGeorge Cherian 			mbx->msg);
13c694b233SGeorge Cherian 	cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1),
14c694b233SGeorge Cherian 			mbx->data);
15c694b233SGeorge Cherian }
16c694b233SGeorge Cherian 
17c694b233SGeorge Cherian /* Interrupt handler to handle mailbox messages from VFs */
18c694b233SGeorge Cherian void cptvf_handle_mbox_intr(struct cpt_vf *cptvf)
19c694b233SGeorge Cherian {
20c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
21c694b233SGeorge Cherian 
22c694b233SGeorge Cherian 	/*
23c694b233SGeorge Cherian 	 * MBOX[0] contains msg
24c694b233SGeorge Cherian 	 * MBOX[1] contains data
25c694b233SGeorge Cherian 	 */
26c694b233SGeorge Cherian 	mbx.msg  = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0));
27c694b233SGeorge Cherian 	mbx.data = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1));
28c694b233SGeorge Cherian 	dev_dbg(&cptvf->pdev->dev, "%s: Mailbox msg 0x%llx from PF\n",
29c694b233SGeorge Cherian 		__func__, mbx.msg);
30c694b233SGeorge Cherian 	switch (mbx.msg) {
31c694b233SGeorge Cherian 	case CPT_MSG_READY:
32c694b233SGeorge Cherian 	{
33c694b233SGeorge Cherian 		cptvf->pf_acked = true;
34c694b233SGeorge Cherian 		cptvf->vfid = mbx.data;
35c694b233SGeorge Cherian 		dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid);
36c694b233SGeorge Cherian 		break;
37c694b233SGeorge Cherian 	}
38c694b233SGeorge Cherian 	case CPT_MSG_QBIND_GRP:
39c694b233SGeorge Cherian 		cptvf->pf_acked = true;
40c694b233SGeorge Cherian 		cptvf->vftype = mbx.data;
41c694b233SGeorge Cherian 		dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n",
42c694b233SGeorge Cherian 			cptvf->vfid, ((mbx.data == SE_TYPES) ? "SE" : "AE"),
43c694b233SGeorge Cherian 			cptvf->vfgrp);
44c694b233SGeorge Cherian 		break;
45c694b233SGeorge Cherian 	case CPT_MBOX_MSG_TYPE_ACK:
46c694b233SGeorge Cherian 		cptvf->pf_acked = true;
47c694b233SGeorge Cherian 		break;
48c694b233SGeorge Cherian 	case CPT_MBOX_MSG_TYPE_NACK:
49c694b233SGeorge Cherian 		cptvf->pf_nacked = true;
50c694b233SGeorge Cherian 		break;
51c694b233SGeorge Cherian 	default:
52c694b233SGeorge Cherian 		dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n",
53c694b233SGeorge Cherian 			mbx.msg);
54c694b233SGeorge Cherian 		break;
55c694b233SGeorge Cherian 	}
56c694b233SGeorge Cherian }
57c694b233SGeorge Cherian 
58c694b233SGeorge Cherian static int cptvf_send_msg_to_pf_timeout(struct cpt_vf *cptvf,
59c694b233SGeorge Cherian 					struct cpt_mbox *mbx)
60c694b233SGeorge Cherian {
61c694b233SGeorge Cherian 	int timeout = CPT_MBOX_MSG_TIMEOUT;
62c694b233SGeorge Cherian 	int sleep = 10;
63c694b233SGeorge Cherian 
64c694b233SGeorge Cherian 	cptvf->pf_acked = false;
65c694b233SGeorge Cherian 	cptvf->pf_nacked = false;
66c694b233SGeorge Cherian 	cptvf_send_msg_to_pf(cptvf, mbx);
67c694b233SGeorge Cherian 	/* Wait for previous message to be acked, timeout 2sec */
68c694b233SGeorge Cherian 	while (!cptvf->pf_acked) {
69c694b233SGeorge Cherian 		if (cptvf->pf_nacked)
70c694b233SGeorge Cherian 			return -EINVAL;
71c694b233SGeorge Cherian 		msleep(sleep);
72c694b233SGeorge Cherian 		if (cptvf->pf_acked)
73c694b233SGeorge Cherian 			break;
74c694b233SGeorge Cherian 		timeout -= sleep;
75c694b233SGeorge Cherian 		if (!timeout) {
76c694b233SGeorge Cherian 			dev_err(&cptvf->pdev->dev, "PF didn't ack to mbox msg %llx from VF%u\n",
77c694b233SGeorge Cherian 				(mbx->msg & 0xFF), cptvf->vfid);
78c694b233SGeorge Cherian 			return -EBUSY;
79c694b233SGeorge Cherian 		}
80c694b233SGeorge Cherian 	}
81c694b233SGeorge Cherian 
82c694b233SGeorge Cherian 	return 0;
83c694b233SGeorge Cherian }
84c694b233SGeorge Cherian 
85c694b233SGeorge Cherian /*
86c694b233SGeorge Cherian  * Checks if VF is able to comminicate with PF
87c694b233SGeorge Cherian  * and also gets the CPT number this VF is associated to.
88c694b233SGeorge Cherian  */
89c694b233SGeorge Cherian int cptvf_check_pf_ready(struct cpt_vf *cptvf)
90c694b233SGeorge Cherian {
91c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
92c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
93c694b233SGeorge Cherian 
94c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_READY;
95c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
96c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to READY msg\n");
97c694b233SGeorge Cherian 		return -EBUSY;
98c694b233SGeorge Cherian 	}
99c694b233SGeorge Cherian 
100c694b233SGeorge Cherian 	return 0;
101c694b233SGeorge Cherian }
102c694b233SGeorge Cherian 
103c694b233SGeorge Cherian /*
104c694b233SGeorge Cherian  * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF.
105c694b233SGeorge Cherian  * Must be ACKed.
106c694b233SGeorge Cherian  */
107c694b233SGeorge Cherian int cptvf_send_vq_size_msg(struct cpt_vf *cptvf)
108c694b233SGeorge Cherian {
109c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
110c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
111c694b233SGeorge Cherian 
112c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_QLEN;
113c694b233SGeorge Cherian 	mbx.data = cptvf->qsize;
114c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
115c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to vq_size msg\n");
116c694b233SGeorge Cherian 		return -EBUSY;
117c694b233SGeorge Cherian 	}
118c694b233SGeorge Cherian 
119c694b233SGeorge Cherian 	return 0;
120c694b233SGeorge Cherian }
121c694b233SGeorge Cherian 
122c694b233SGeorge Cherian /*
123c694b233SGeorge Cherian  * Communicate VF group required to PF and get the VQ binded to that group
124c694b233SGeorge Cherian  */
125c694b233SGeorge Cherian int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf)
126c694b233SGeorge Cherian {
127c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
128c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
129c694b233SGeorge Cherian 
130c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_QBIND_GRP;
131c694b233SGeorge Cherian 	/* Convey group of the VF */
132c694b233SGeorge Cherian 	mbx.data = cptvf->vfgrp;
133c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
134c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
135c694b233SGeorge Cherian 		return -EBUSY;
136c694b233SGeorge Cherian 	}
137c694b233SGeorge Cherian 
138c694b233SGeorge Cherian 	return 0;
139c694b233SGeorge Cherian }
140c694b233SGeorge Cherian 
141c694b233SGeorge Cherian /*
142c694b233SGeorge Cherian  * Communicate VF group required to PF and get the VQ binded to that group
143c694b233SGeorge Cherian  */
144c694b233SGeorge Cherian int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf)
145c694b233SGeorge Cherian {
146c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
147c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
148c694b233SGeorge Cherian 
149c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_VQ_PRIORITY;
150c694b233SGeorge Cherian 	/* Convey group of the VF */
151c694b233SGeorge Cherian 	mbx.data = cptvf->priority;
152c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
153c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n");
154c694b233SGeorge Cherian 		return -EBUSY;
155c694b233SGeorge Cherian 	}
156c694b233SGeorge Cherian 	return 0;
157c694b233SGeorge Cherian }
158c694b233SGeorge Cherian 
159c694b233SGeorge Cherian /*
160c694b233SGeorge Cherian  * Communicate to PF that VF is UP and running
161c694b233SGeorge Cherian  */
162c694b233SGeorge Cherian int cptvf_send_vf_up(struct cpt_vf *cptvf)
163c694b233SGeorge Cherian {
164c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
165c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
166c694b233SGeorge Cherian 
167c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_VF_UP;
168c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
169c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to UP msg\n");
170c694b233SGeorge Cherian 		return -EBUSY;
171c694b233SGeorge Cherian 	}
172c694b233SGeorge Cherian 
173c694b233SGeorge Cherian 	return 0;
174c694b233SGeorge Cherian }
175c694b233SGeorge Cherian 
176c694b233SGeorge Cherian /*
177c694b233SGeorge Cherian  * Communicate to PF that VF is DOWN and running
178c694b233SGeorge Cherian  */
179c694b233SGeorge Cherian int cptvf_send_vf_down(struct cpt_vf *cptvf)
180c694b233SGeorge Cherian {
181c694b233SGeorge Cherian 	struct pci_dev *pdev = cptvf->pdev;
182c694b233SGeorge Cherian 	struct cpt_mbox mbx = {};
183c694b233SGeorge Cherian 
184c694b233SGeorge Cherian 	mbx.msg = CPT_MSG_VF_DOWN;
185c694b233SGeorge Cherian 	if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) {
186c694b233SGeorge Cherian 		dev_err(&pdev->dev, "PF didn't respond to DOWN msg\n");
187c694b233SGeorge Cherian 		return -EBUSY;
188c694b233SGeorge Cherian 	}
189c694b233SGeorge Cherian 
190c694b233SGeorge Cherian 	return 0;
191c694b233SGeorge Cherian }
192