0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "otx_cpt_common.h"
0012 #include "otx_cptpf.h"
0013
0014 static char *get_mbox_opcode_str(int msg_opcode)
0015 {
0016 char *str = "Unknown";
0017
0018 switch (msg_opcode) {
0019 case OTX_CPT_MSG_VF_UP:
0020 str = "UP";
0021 break;
0022
0023 case OTX_CPT_MSG_VF_DOWN:
0024 str = "DOWN";
0025 break;
0026
0027 case OTX_CPT_MSG_READY:
0028 str = "READY";
0029 break;
0030
0031 case OTX_CPT_MSG_QLEN:
0032 str = "QLEN";
0033 break;
0034
0035 case OTX_CPT_MSG_QBIND_GRP:
0036 str = "QBIND_GRP";
0037 break;
0038
0039 case OTX_CPT_MSG_VQ_PRIORITY:
0040 str = "VQ_PRIORITY";
0041 break;
0042
0043 case OTX_CPT_MSG_PF_TYPE:
0044 str = "PF_TYPE";
0045 break;
0046
0047 case OTX_CPT_MSG_ACK:
0048 str = "ACK";
0049 break;
0050
0051 case OTX_CPT_MSG_NACK:
0052 str = "NACK";
0053 break;
0054 }
0055
0056 return str;
0057 }
0058
0059 static void dump_mbox_msg(struct otx_cpt_mbox *mbox_msg, int vf_id)
0060 {
0061 char raw_data_str[OTX_CPT_MAX_MBOX_DATA_STR_SIZE];
0062
0063 hex_dump_to_buffer(mbox_msg, sizeof(struct otx_cpt_mbox), 16, 8,
0064 raw_data_str, OTX_CPT_MAX_MBOX_DATA_STR_SIZE, false);
0065 if (vf_id >= 0)
0066 pr_debug("MBOX opcode %s received from VF%d raw_data %s\n",
0067 get_mbox_opcode_str(mbox_msg->msg), vf_id,
0068 raw_data_str);
0069 else
0070 pr_debug("MBOX opcode %s received from PF raw_data %s\n",
0071 get_mbox_opcode_str(mbox_msg->msg), raw_data_str);
0072 }
0073
0074 static void otx_cpt_send_msg_to_vf(struct otx_cpt_device *cpt, int vf,
0075 struct otx_cpt_mbox *mbx)
0076 {
0077
0078 writeq(mbx->data, cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 1));
0079 writeq(mbx->msg, cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 0));
0080 }
0081
0082
0083
0084
0085
0086 static void otx_cpt_mbox_send_ack(struct otx_cpt_device *cpt, int vf,
0087 struct otx_cpt_mbox *mbx)
0088 {
0089 mbx->data = 0ull;
0090 mbx->msg = OTX_CPT_MSG_ACK;
0091 otx_cpt_send_msg_to_vf(cpt, vf, mbx);
0092 }
0093
0094
0095 static void otx_cptpf_mbox_send_nack(struct otx_cpt_device *cpt, int vf,
0096 struct otx_cpt_mbox *mbx)
0097 {
0098 mbx->data = 0ull;
0099 mbx->msg = OTX_CPT_MSG_NACK;
0100 otx_cpt_send_msg_to_vf(cpt, vf, mbx);
0101 }
0102
0103 static void otx_cpt_clear_mbox_intr(struct otx_cpt_device *cpt, u32 vf)
0104 {
0105
0106 writeq(1ull << vf, cpt->reg_base + OTX_CPT_PF_MBOX_INTX(0));
0107 }
0108
0109
0110
0111
0112 static void otx_cpt_cfg_qlen_for_vf(struct otx_cpt_device *cpt, int vf,
0113 u32 size)
0114 {
0115 union otx_cptx_pf_qx_ctl pf_qx_ctl;
0116
0117 pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
0118 pf_qx_ctl.s.size = size;
0119 pf_qx_ctl.s.cont_err = true;
0120 writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
0121 }
0122
0123
0124
0125
0126 static void otx_cpt_cfg_vq_priority(struct otx_cpt_device *cpt, int vf, u32 pri)
0127 {
0128 union otx_cptx_pf_qx_ctl pf_qx_ctl;
0129
0130 pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
0131 pf_qx_ctl.s.pri = pri;
0132 writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(vf));
0133 }
0134
0135 static int otx_cpt_bind_vq_to_grp(struct otx_cpt_device *cpt, u8 q, u8 grp)
0136 {
0137 struct device *dev = &cpt->pdev->dev;
0138 struct otx_cpt_eng_grp_info *eng_grp;
0139 union otx_cptx_pf_qx_ctl pf_qx_ctl;
0140 struct otx_cpt_ucode *ucode;
0141
0142 if (q >= cpt->max_vfs) {
0143 dev_err(dev, "Requested queue %d is > than maximum avail %d\n",
0144 q, cpt->max_vfs);
0145 return -EINVAL;
0146 }
0147
0148 if (grp >= OTX_CPT_MAX_ENGINE_GROUPS) {
0149 dev_err(dev, "Requested group %d is > than maximum avail %d\n",
0150 grp, OTX_CPT_MAX_ENGINE_GROUPS);
0151 return -EINVAL;
0152 }
0153
0154 eng_grp = &cpt->eng_grps.grp[grp];
0155 if (!eng_grp->is_enabled) {
0156 dev_err(dev, "Requested engine group %d is disabled\n", grp);
0157 return -EINVAL;
0158 }
0159
0160 pf_qx_ctl.u = readq(cpt->reg_base + OTX_CPT_PF_QX_CTL(q));
0161 pf_qx_ctl.s.grp = grp;
0162 writeq(pf_qx_ctl.u, cpt->reg_base + OTX_CPT_PF_QX_CTL(q));
0163
0164 if (eng_grp->mirror.is_ena)
0165 ucode = &eng_grp->g->grp[eng_grp->mirror.idx].ucode[0];
0166 else
0167 ucode = &eng_grp->ucode[0];
0168
0169 if (otx_cpt_uc_supports_eng_type(ucode, OTX_CPT_SE_TYPES))
0170 return OTX_CPT_SE_TYPES;
0171 else if (otx_cpt_uc_supports_eng_type(ucode, OTX_CPT_AE_TYPES))
0172 return OTX_CPT_AE_TYPES;
0173 else
0174 return BAD_OTX_CPTVF_TYPE;
0175 }
0176
0177
0178 static void otx_cpt_handle_mbox_intr(struct otx_cpt_device *cpt, int vf)
0179 {
0180 int vftype = 0;
0181 struct otx_cpt_mbox mbx = {};
0182 struct device *dev = &cpt->pdev->dev;
0183
0184
0185
0186
0187 mbx.msg = readq(cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 0));
0188 mbx.data = readq(cpt->reg_base + OTX_CPT_PF_VFX_MBOXX(vf, 1));
0189
0190 dump_mbox_msg(&mbx, vf);
0191
0192 switch (mbx.msg) {
0193 case OTX_CPT_MSG_VF_UP:
0194 mbx.msg = OTX_CPT_MSG_VF_UP;
0195 mbx.data = cpt->vfs_enabled;
0196 otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
0197 break;
0198 case OTX_CPT_MSG_READY:
0199 mbx.msg = OTX_CPT_MSG_READY;
0200 mbx.data = vf;
0201 otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
0202 break;
0203 case OTX_CPT_MSG_VF_DOWN:
0204
0205 otx_cpt_mbox_send_ack(cpt, vf, &mbx);
0206 break;
0207 case OTX_CPT_MSG_QLEN:
0208 otx_cpt_cfg_qlen_for_vf(cpt, vf, mbx.data);
0209 otx_cpt_mbox_send_ack(cpt, vf, &mbx);
0210 break;
0211 case OTX_CPT_MSG_QBIND_GRP:
0212 vftype = otx_cpt_bind_vq_to_grp(cpt, vf, (u8)mbx.data);
0213 if ((vftype != OTX_CPT_AE_TYPES) &&
0214 (vftype != OTX_CPT_SE_TYPES)) {
0215 dev_err(dev, "VF%d binding to eng group %llu failed\n",
0216 vf, mbx.data);
0217 otx_cptpf_mbox_send_nack(cpt, vf, &mbx);
0218 } else {
0219 mbx.msg = OTX_CPT_MSG_QBIND_GRP;
0220 mbx.data = vftype;
0221 otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
0222 }
0223 break;
0224 case OTX_CPT_MSG_PF_TYPE:
0225 mbx.msg = OTX_CPT_MSG_PF_TYPE;
0226 mbx.data = cpt->pf_type;
0227 otx_cpt_send_msg_to_vf(cpt, vf, &mbx);
0228 break;
0229 case OTX_CPT_MSG_VQ_PRIORITY:
0230 otx_cpt_cfg_vq_priority(cpt, vf, mbx.data);
0231 otx_cpt_mbox_send_ack(cpt, vf, &mbx);
0232 break;
0233 default:
0234 dev_err(&cpt->pdev->dev, "Invalid msg from VF%d, msg 0x%llx\n",
0235 vf, mbx.msg);
0236 break;
0237 }
0238 }
0239
0240 void otx_cpt_mbox_intr_handler (struct otx_cpt_device *cpt, int mbx)
0241 {
0242 u64 intr;
0243 u8 vf;
0244
0245 intr = readq(cpt->reg_base + OTX_CPT_PF_MBOX_INTX(0));
0246 pr_debug("PF interrupt mbox%d mask 0x%llx\n", mbx, intr);
0247 for (vf = 0; vf < cpt->max_vfs; vf++) {
0248 if (intr & (1ULL << vf)) {
0249 otx_cpt_handle_mbox_intr(cpt, vf);
0250 otx_cpt_clear_mbox_intr(cpt, vf);
0251 }
0252 }
0253 }