Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2016 Cavium, Inc.
0004  */
0005 #include <linux/module.h>
0006 #include "cptpf.h"
0007 
0008 static void cpt_send_msg_to_vf(struct cpt_device *cpt, int vf,
0009                    struct cpt_mbox *mbx)
0010 {
0011     /* Writing mbox(0) causes interrupt */
0012     cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1),
0013             mbx->data);
0014     cpt_write_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0), mbx->msg);
0015 }
0016 
0017 /* ACKs VF's mailbox message
0018  * @vf: VF to which ACK to be sent
0019  */
0020 static void cpt_mbox_send_ack(struct cpt_device *cpt, int vf,
0021                   struct cpt_mbox *mbx)
0022 {
0023     mbx->data = 0ull;
0024     mbx->msg = CPT_MBOX_MSG_TYPE_ACK;
0025     cpt_send_msg_to_vf(cpt, vf, mbx);
0026 }
0027 
0028 static void cpt_clear_mbox_intr(struct cpt_device *cpt, u32 vf)
0029 {
0030     /* W1C for the VF */
0031     cpt_write_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0), (1 << vf));
0032 }
0033 
0034 /*
0035  *  Configure QLEN/Chunk sizes for VF
0036  */
0037 static void cpt_cfg_qlen_for_vf(struct cpt_device *cpt, int vf, u32 size)
0038 {
0039     union cptx_pf_qx_ctl pf_qx_ctl;
0040 
0041     pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
0042     pf_qx_ctl.s.size = size;
0043     pf_qx_ctl.s.cont_err = true;
0044     cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
0045 }
0046 
0047 /*
0048  * Configure VQ priority
0049  */
0050 static void cpt_cfg_vq_priority(struct cpt_device *cpt, int vf, u32 pri)
0051 {
0052     union cptx_pf_qx_ctl pf_qx_ctl;
0053 
0054     pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf));
0055     pf_qx_ctl.s.pri = pri;
0056     cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, vf), pf_qx_ctl.u);
0057 }
0058 
0059 static int cpt_bind_vq_to_grp(struct cpt_device *cpt, u8 q, u8 grp)
0060 {
0061     struct microcode *mcode = cpt->mcode;
0062     union cptx_pf_qx_ctl pf_qx_ctl;
0063     struct device *dev = &cpt->pdev->dev;
0064 
0065     if (q >= CPT_MAX_VF_NUM) {
0066         dev_err(dev, "Queues are more than cores in the group");
0067         return -EINVAL;
0068     }
0069     if (grp >= CPT_MAX_CORE_GROUPS) {
0070         dev_err(dev, "Request group is more than possible groups");
0071         return -EINVAL;
0072     }
0073     if (grp >= cpt->next_mc_idx) {
0074         dev_err(dev, "Request group is higher than available functional groups");
0075         return -EINVAL;
0076     }
0077     pf_qx_ctl.u = cpt_read_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q));
0078     pf_qx_ctl.s.grp = mcode[grp].group;
0079     cpt_write_csr64(cpt->reg_base, CPTX_PF_QX_CTL(0, q), pf_qx_ctl.u);
0080     dev_dbg(dev, "VF %d TYPE %s", q, (mcode[grp].is_ae ? "AE" : "SE"));
0081 
0082     return mcode[grp].is_ae ? AE_TYPES : SE_TYPES;
0083 }
0084 
0085 /* Interrupt handler to handle mailbox messages from VFs */
0086 static void cpt_handle_mbox_intr(struct cpt_device *cpt, int vf)
0087 {
0088     struct cpt_vf_info *vfx = &cpt->vfinfo[vf];
0089     struct cpt_mbox mbx = {};
0090     int vftype;
0091     struct device *dev = &cpt->pdev->dev;
0092     /*
0093      * MBOX[0] contains msg
0094      * MBOX[1] contains data
0095      */
0096     mbx.msg  = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 0));
0097     mbx.data = cpt_read_csr64(cpt->reg_base, CPTX_PF_VFX_MBOXX(0, vf, 1));
0098     dev_dbg(dev, "%s: Mailbox msg 0x%llx from VF%d", __func__, mbx.msg, vf);
0099     switch (mbx.msg) {
0100     case CPT_MSG_VF_UP:
0101         vfx->state = VF_STATE_UP;
0102         try_module_get(THIS_MODULE);
0103         cpt_mbox_send_ack(cpt, vf, &mbx);
0104         break;
0105     case CPT_MSG_READY:
0106         mbx.msg  = CPT_MSG_READY;
0107         mbx.data = vf;
0108         cpt_send_msg_to_vf(cpt, vf, &mbx);
0109         break;
0110     case CPT_MSG_VF_DOWN:
0111         /* First msg in VF teardown sequence */
0112         vfx->state = VF_STATE_DOWN;
0113         module_put(THIS_MODULE);
0114         cpt_mbox_send_ack(cpt, vf, &mbx);
0115         break;
0116     case CPT_MSG_QLEN:
0117         vfx->qlen = mbx.data;
0118         cpt_cfg_qlen_for_vf(cpt, vf, vfx->qlen);
0119         cpt_mbox_send_ack(cpt, vf, &mbx);
0120         break;
0121     case CPT_MSG_QBIND_GRP:
0122         vftype = cpt_bind_vq_to_grp(cpt, vf, (u8)mbx.data);
0123         if ((vftype != AE_TYPES) && (vftype != SE_TYPES))
0124             dev_err(dev, "Queue %d binding to group %llu failed",
0125                 vf, mbx.data);
0126         else {
0127             dev_dbg(dev, "Queue %d binding to group %llu successful",
0128                 vf, mbx.data);
0129             mbx.msg = CPT_MSG_QBIND_GRP;
0130             mbx.data = vftype;
0131             cpt_send_msg_to_vf(cpt, vf, &mbx);
0132         }
0133         break;
0134     case CPT_MSG_VQ_PRIORITY:
0135         vfx->priority = mbx.data;
0136         cpt_cfg_vq_priority(cpt, vf, vfx->priority);
0137         cpt_mbox_send_ack(cpt, vf, &mbx);
0138         break;
0139     default:
0140         dev_err(&cpt->pdev->dev, "Invalid msg from VF%d, msg 0x%llx\n",
0141             vf, mbx.msg);
0142         break;
0143     }
0144 }
0145 
0146 void cpt_mbox_intr_handler (struct cpt_device *cpt, int mbx)
0147 {
0148     u64 intr;
0149     u8  vf;
0150 
0151     intr = cpt_read_csr64(cpt->reg_base, CPTX_PF_MBOX_INTX(0, 0));
0152     dev_dbg(&cpt->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
0153     for (vf = 0; vf < CPT_MAX_VF_NUM; vf++) {
0154         if (intr & (1ULL << vf)) {
0155             dev_dbg(&cpt->pdev->dev, "Intr from VF %d\n", vf);
0156             cpt_handle_mbox_intr(cpt, vf);
0157             cpt_clear_mbox_intr(cpt, vf);
0158         }
0159     }
0160 }