1
2
3
4
5
6
7
8#include <linux/module.h>
9#include "cptpf.h"
10
11static void cpt_send_msg_to_vf(struct cpt_device *cpt, int vf,
12 struct cpt_mbox *mbx)
13{
14
15 cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1),
16 mbx->data);
17 cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0), mbx->msg);
18}
19
20
21
22
23static void cpt_mbox_send_ack(struct cpt_device *cpt, int vf,
24 struct cpt_mbox *mbx)
25{
26 mbx->data = 0ull;
27 mbx->msg = CPT_MBOX_MSG_TYPE_ACK;
28 cpt_send_msg_to_vf(cpt, vf, mbx);
29}
30
31static void cpt_clear_mbox_intr(struct cpt_device *cpt, u32 vf)
32{
33
34 cpt_write_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0), (1 << vf));
35}
36
37
38
39
40static void cpt_cfg_qlen_for_vf(struct cpt_device *cpt, int vf, u32 size)
41{
42 union cptx_pf_qx_ctl pf_qx_ctl;
43
44 pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
45 pf_qx_ctl.s.size = size;
46 pf_qx_ctl.s.cont_err = true;
47 cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
48}
49
50
51
52
53static void cpt_cfg_vq_priority(struct cpt_device *cpt, int vf, u32 pri)
54{
55 union cptx_pf_qx_ctl pf_qx_ctl;
56
57 pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
58 pf_qx_ctl.s.pri = pri;
59 cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
60}
61
62static int cpt_bind_vq_to_grp(struct cpt_device *cpt, u8 q, u8 grp)
63{
64 struct microcode *mcode = cpt->mcode;
65 union cptx_pf_qx_ctl pf_qx_ctl;
66 struct device *dev = &cpt->pdev->dev;
67
68 if (q >= CPT_MAX_VF_NUM) {
69 dev_err(dev, "Queues are more than cores in the group");
70 return -EINVAL;
71 }
72 if (grp >= CPT_MAX_CORE_GROUPS) {
73 dev_err(dev, "Request group is more than possible groups");
74 return -EINVAL;
75 }
76 if (grp >= cpt->next_mc_idx) {
77 dev_err(dev, "Request group is higher than available functional groups");
78 return -EINVAL;
79 }
80 pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q));
81 pf_qx_ctl.s.grp = mcode[grp].group;
82 cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q), pf_qx_ctl.u);
83 dev_dbg(dev, "VF %d TYPE %s", q, (mcode[grp].is_ae ? "AE" : "SE"));
84
85 return mcode[grp].is_ae ? AE_TYPES : SE_TYPES;
86}
87
88
89static void cpt_handle_mbox_intr(struct cpt_device *cpt, int vf)
90{
91 struct cpt_vf_info *vfx = &cpt->vfinfo[vf];
92 struct cpt_mbox mbx = {};
93 int vftype;
94 struct device *dev = &cpt->pdev->dev;
95
96
97
98
99 mbx.msg = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0));
100 mbx.data = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1));
101 dev_dbg(dev, "%s: Mailbox msg 0x%llx from VF%d", __func__, mbx.msg, vf);
102 switch (mbx.msg) {
103 case CPT_MSG_VF_UP:
104 vfx->state = VF_STATE_UP;
105 try_module_get(THIS_MODULE);
106 cpt_mbox_send_ack(cpt, vf, &mbx);
107 break;
108 case CPT_MSG_READY:
109 mbx.msg = CPT_MSG_READY;
110 mbx.data = vf;
111 cpt_send_msg_to_vf(cpt, vf, &mbx);
112 break;
113 case CPT_MSG_VF_DOWN:
114
115 vfx->state = VF_STATE_DOWN;
116 module_put(THIS_MODULE);
117 cpt_mbox_send_ack(cpt, vf, &mbx);
118 break;
119 case CPT_MSG_QLEN:
120 vfx->qlen = mbx.data;
121 cpt_cfg_qlen_for_vf(cpt, vf, vfx->qlen);
122 cpt_mbox_send_ack(cpt, vf, &mbx);
123 break;
124 case CPT_MSG_QBIND_GRP:
125 vftype = cpt_bind_vq_to_grp(cpt, vf, (u8)mbx.data);
126 if ((vftype != AE_TYPES) && (vftype != SE_TYPES))
127 dev_err(dev, "Queue %d binding to group %llu failed",
128 vf, mbx.data);
129 else {
130 dev_dbg(dev, "Queue %d binding to group %llu successful",
131 vf, mbx.data);
132 mbx.msg = CPT_MSG_QBIND_GRP;
133 mbx.data = vftype;
134 cpt_send_msg_to_vf(cpt, vf, &mbx);
135 }
136 break;
137 case CPT_MSG_VQ_PRIORITY:
138 vfx->priority = mbx.data;
139 cpt_cfg_vq_priority(cpt, vf, vfx->priority);
140 cpt_mbox_send_ack(cpt, vf, &mbx);
141 break;
142 default:
143 dev_err(&cpt->pdev->dev, "Invalid msg from VF%d, msg 0x%llx\n",
144 vf, mbx.msg);
145 break;
146 }
147}
148
149void cpt_mbox_intr_handler (struct cpt_device *cpt, int mbx)
150{
151 u64 intr;
152 u8 vf;
153
154 intr = cpt_read_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0));
155 dev_dbg(&cpt->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
156 for (vf = 0; vf < CPT_MAX_VF_NUM; vf++) {
157 if (intr & (1ULL << vf)) {
158 dev_dbg(&cpt->pdev->dev, "Intr from VF %d\n", vf);
159 cpt_handle_mbox_intr(cpt, vf);
160 cpt_clear_mbox_intr(cpt, vf);
161 }
162 }
163}
164