GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / crypto / cavium / cpt / cptvf_mbox.c
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 }