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