1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/bitmap.h>
3 #include <linux/workqueue.h>
5 #include "nitrox_csr.h"
6 #include "nitrox_hal.h"
7 #include "nitrox_dev.h"
8 #include "nitrox_mbx.h"
10 #define RING_TO_VFNO(_x, _y) ((_x) / (_y))
13 * mbx_msg_type - Mailbox message types
23 * mbx_msg_opcode - Mailbox message opcodes
30 MSG_OP_MCODE_INFO
= 11,
34 struct nitrox_vfdev
*vfdev
;
35 struct nitrox_device
*ndev
;
36 struct work_struct pf2vf_resp
;
39 static inline u64
pf2vf_read_mbox(struct nitrox_device
*ndev
, int ring
)
43 reg_addr
= NPS_PKT_MBOX_VF_PF_PFDATAX(ring
);
44 return nitrox_read_csr(ndev
, reg_addr
);
47 static inline void pf2vf_write_mbox(struct nitrox_device
*ndev
, u64 value
,
52 reg_addr
= NPS_PKT_MBOX_PF_VF_PFDATAX(ring
);
53 nitrox_write_csr(ndev
, reg_addr
, value
);
56 static void pf2vf_send_response(struct nitrox_device
*ndev
,
57 struct nitrox_vfdev
*vfdev
)
61 msg
.value
= vfdev
->msg
.value
;
63 switch (vfdev
->msg
.opcode
) {
65 msg
.data
= ndev
->mode
;
68 vfdev
->nr_queues
= vfdev
->msg
.data
;
69 atomic_set(&vfdev
->state
, __NDEV_READY
);
71 case MSG_OP_CHIPID_VFID
:
72 msg
.id
.chipid
= ndev
->idx
;
73 msg
.id
.vfid
= vfdev
->vfno
;
77 atomic_set(&vfdev
->state
, __NDEV_NOT_READY
);
79 case MSG_OP_MCODE_INFO
:
81 msg
.mcode_info
.count
= 2;
82 msg
.mcode_info
.info
= MCODE_TYPE_SE_SSL
| (MCODE_TYPE_AE
<< 5);
83 msg
.mcode_info
.next_se_grp
= 1;
84 msg
.mcode_info
.next_ae_grp
= 1;
87 msg
.type
= MBX_MSG_TYPE_NOP
;
91 if (msg
.type
== MBX_MSG_TYPE_NOP
)
95 msg
.type
= MBX_MSG_TYPE_ACK
;
96 pf2vf_write_mbox(ndev
, msg
.value
, vfdev
->ring
);
99 atomic64_inc(&vfdev
->mbx_resp
);
102 static void pf2vf_resp_handler(struct work_struct
*work
)
104 struct pf2vf_work
*pf2vf_resp
= container_of(work
, struct pf2vf_work
,
106 struct nitrox_vfdev
*vfdev
= pf2vf_resp
->vfdev
;
107 struct nitrox_device
*ndev
= pf2vf_resp
->ndev
;
109 switch (vfdev
->msg
.type
) {
110 case MBX_MSG_TYPE_REQ
:
111 /* process the request from VF */
112 pf2vf_send_response(ndev
, vfdev
);
114 case MBX_MSG_TYPE_ACK
:
115 case MBX_MSG_TYPE_NACK
:
122 void nitrox_pf2vf_mbox_handler(struct nitrox_device
*ndev
)
124 DECLARE_BITMAP(csr
, BITS_PER_TYPE(u64
));
125 struct nitrox_vfdev
*vfdev
;
126 struct pf2vf_work
*pfwork
;
131 /* loop for VF(0..63) */
132 reg_addr
= NPS_PKT_MBOX_INT_LO
;
133 value
= nitrox_read_csr(ndev
, reg_addr
);
134 bitmap_from_u64(csr
, value
);
135 for_each_set_bit(i
, csr
, BITS_PER_TYPE(csr
)) {
136 /* get the vfno from ring */
137 vfno
= RING_TO_VFNO(i
, ndev
->iov
.max_vf_queues
);
138 vfdev
= ndev
->iov
.vfdev
+ vfno
;
140 /* fill the vf mailbox data */
141 vfdev
->msg
.value
= pf2vf_read_mbox(ndev
, vfdev
->ring
);
142 pfwork
= kzalloc(sizeof(*pfwork
), GFP_ATOMIC
);
146 pfwork
->vfdev
= vfdev
;
148 INIT_WORK(&pfwork
->pf2vf_resp
, pf2vf_resp_handler
);
149 queue_work(ndev
->iov
.pf2vf_wq
, &pfwork
->pf2vf_resp
);
150 /* clear the corresponding vf bit */
151 nitrox_write_csr(ndev
, reg_addr
, BIT_ULL(i
));
154 /* loop for VF(64..127) */
155 reg_addr
= NPS_PKT_MBOX_INT_HI
;
156 value
= nitrox_read_csr(ndev
, reg_addr
);
157 bitmap_from_u64(csr
, value
);
158 for_each_set_bit(i
, csr
, BITS_PER_TYPE(csr
)) {
159 /* get the vfno from ring */
160 vfno
= RING_TO_VFNO(i
+ 64, ndev
->iov
.max_vf_queues
);
161 vfdev
= ndev
->iov
.vfdev
+ vfno
;
162 vfdev
->ring
= (i
+ 64);
163 /* fill the vf mailbox data */
164 vfdev
->msg
.value
= pf2vf_read_mbox(ndev
, vfdev
->ring
);
166 pfwork
= kzalloc(sizeof(*pfwork
), GFP_ATOMIC
);
170 pfwork
->vfdev
= vfdev
;
172 INIT_WORK(&pfwork
->pf2vf_resp
, pf2vf_resp_handler
);
173 queue_work(ndev
->iov
.pf2vf_wq
, &pfwork
->pf2vf_resp
);
174 /* clear the corresponding vf bit */
175 nitrox_write_csr(ndev
, reg_addr
, BIT_ULL(i
));
179 int nitrox_mbox_init(struct nitrox_device
*ndev
)
181 struct nitrox_vfdev
*vfdev
;
184 ndev
->iov
.vfdev
= kcalloc(ndev
->iov
.num_vfs
,
185 sizeof(struct nitrox_vfdev
), GFP_KERNEL
);
186 if (!ndev
->iov
.vfdev
)
189 for (i
= 0; i
< ndev
->iov
.num_vfs
; i
++) {
190 vfdev
= ndev
->iov
.vfdev
+ i
;
194 /* allocate pf2vf response workqueue */
195 ndev
->iov
.pf2vf_wq
= alloc_workqueue("nitrox_pf2vf", 0, 0);
196 if (!ndev
->iov
.pf2vf_wq
) {
197 kfree(ndev
->iov
.vfdev
);
198 ndev
->iov
.vfdev
= NULL
;
201 /* enable pf2vf mailbox interrupts */
202 enable_pf2vf_mbox_interrupts(ndev
);
207 void nitrox_mbox_cleanup(struct nitrox_device
*ndev
)
209 /* disable pf2vf mailbox interrupts */
210 disable_pf2vf_mbox_interrupts(ndev
);
211 /* destroy workqueue */
212 if (ndev
->iov
.pf2vf_wq
)
213 destroy_workqueue(ndev
->iov
.pf2vf_wq
);
215 kfree(ndev
->iov
.vfdev
);
216 ndev
->iov
.pf2vf_wq
= NULL
;
217 ndev
->iov
.vfdev
= NULL
;