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