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