Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Copyright (C) 2020 Marvell. */
0003 
0004 #include "otx2_cpt_common.h"
0005 #include "otx2_cptpf.h"
0006 #include "rvu_reg.h"
0007 
0008 /*
0009  * CPT PF driver version, It will be incremented by 1 for every feature
0010  * addition in CPT mailbox messages.
0011  */
0012 #define OTX2_CPT_PF_DRV_VERSION 0x1
0013 
0014 static int forward_to_af(struct otx2_cptpf_dev *cptpf,
0015              struct otx2_cptvf_info *vf,
0016              struct mbox_msghdr *req, int size)
0017 {
0018     struct mbox_msghdr *msg;
0019     int ret;
0020 
0021     mutex_lock(&cptpf->lock);
0022     msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
0023     if (msg == NULL) {
0024         mutex_unlock(&cptpf->lock);
0025         return -ENOMEM;
0026     }
0027 
0028     memcpy((uint8_t *)msg + sizeof(struct mbox_msghdr),
0029            (uint8_t *)req + sizeof(struct mbox_msghdr), size);
0030     msg->id = req->id;
0031     msg->pcifunc = req->pcifunc;
0032     msg->sig = req->sig;
0033     msg->ver = req->ver;
0034 
0035     ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);
0036     /* Error code -EIO indicate there is a communication failure
0037      * to the AF. Rest of the error codes indicate that AF processed
0038      * VF messages and set the error codes in response messages
0039      * (if any) so simply forward responses to VF.
0040      */
0041     if (ret == -EIO) {
0042         dev_warn(&cptpf->pdev->dev,
0043              "AF not responding to VF%d messages\n", vf->vf_id);
0044         mutex_unlock(&cptpf->lock);
0045         return ret;
0046     }
0047     mutex_unlock(&cptpf->lock);
0048     return 0;
0049 }
0050 
0051 static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf,
0052                    struct otx2_cptvf_info *vf,
0053                    struct mbox_msghdr *req)
0054 {
0055     struct otx2_cpt_caps_rsp *rsp;
0056 
0057     rsp = (struct otx2_cpt_caps_rsp *)
0058           otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id,
0059                   sizeof(*rsp));
0060     if (!rsp)
0061         return -ENOMEM;
0062 
0063     rsp->hdr.id = MBOX_MSG_GET_CAPS;
0064     rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
0065     rsp->hdr.pcifunc = req->pcifunc;
0066     rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION;
0067     rsp->cpt_revision = cptpf->pdev->revision;
0068     memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps));
0069 
0070     return 0;
0071 }
0072 
0073 static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf,
0074                       struct otx2_cptvf_info *vf,
0075                       struct mbox_msghdr *req)
0076 {
0077     struct otx2_cpt_egrp_num_msg *grp_req;
0078     struct otx2_cpt_egrp_num_rsp *rsp;
0079 
0080     grp_req = (struct otx2_cpt_egrp_num_msg *)req;
0081     rsp = (struct otx2_cpt_egrp_num_rsp *)
0082            otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
0083     if (!rsp)
0084         return -ENOMEM;
0085 
0086     rsp->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM;
0087     rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
0088     rsp->hdr.pcifunc = req->pcifunc;
0089     rsp->eng_type = grp_req->eng_type;
0090     rsp->eng_grp_num = otx2_cpt_get_eng_grp(&cptpf->eng_grps,
0091                         grp_req->eng_type);
0092 
0093     return 0;
0094 }
0095 
0096 static int handle_msg_kvf_limits(struct otx2_cptpf_dev *cptpf,
0097                  struct otx2_cptvf_info *vf,
0098                  struct mbox_msghdr *req)
0099 {
0100     struct otx2_cpt_kvf_limits_rsp *rsp;
0101 
0102     rsp = (struct otx2_cpt_kvf_limits_rsp *)
0103           otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, sizeof(*rsp));
0104     if (!rsp)
0105         return -ENOMEM;
0106 
0107     rsp->hdr.id = MBOX_MSG_GET_KVF_LIMITS;
0108     rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
0109     rsp->hdr.pcifunc = req->pcifunc;
0110     rsp->kvf_limits = cptpf->kvf_limits;
0111 
0112     return 0;
0113 }
0114 
0115 static int cptpf_handle_vf_req(struct otx2_cptpf_dev *cptpf,
0116                    struct otx2_cptvf_info *vf,
0117                    struct mbox_msghdr *req, int size)
0118 {
0119     int err = 0;
0120 
0121     /* Check if msg is valid, if not reply with an invalid msg */
0122     if (req->sig != OTX2_MBOX_REQ_SIG)
0123         goto inval_msg;
0124 
0125     switch (req->id) {
0126     case MBOX_MSG_GET_ENG_GRP_NUM:
0127         err = handle_msg_get_eng_grp_num(cptpf, vf, req);
0128         break;
0129     case MBOX_MSG_GET_CAPS:
0130         err = handle_msg_get_caps(cptpf, vf, req);
0131         break;
0132     case MBOX_MSG_GET_KVF_LIMITS:
0133         err = handle_msg_kvf_limits(cptpf, vf, req);
0134         break;
0135     default:
0136         err = forward_to_af(cptpf, vf, req, size);
0137         break;
0138     }
0139     return err;
0140 
0141 inval_msg:
0142     otx2_reply_invalid_msg(&cptpf->vfpf_mbox, vf->vf_id, 0, req->id);
0143     otx2_mbox_msg_send(&cptpf->vfpf_mbox, vf->vf_id);
0144     return err;
0145 }
0146 
0147 irqreturn_t otx2_cptpf_vfpf_mbox_intr(int __always_unused irq, void *arg)
0148 {
0149     struct otx2_cptpf_dev *cptpf = arg;
0150     struct otx2_cptvf_info *vf;
0151     int i, vf_idx;
0152     u64 intr;
0153 
0154     /*
0155      * Check which VF has raised an interrupt and schedule
0156      * corresponding work queue to process the messages
0157      */
0158     for (i = 0; i < 2; i++) {
0159         /* Read the interrupt bits */
0160         intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0,
0161                        RVU_PF_VFPF_MBOX_INTX(i));
0162 
0163         for (vf_idx = i * 64; vf_idx < cptpf->enabled_vfs; vf_idx++) {
0164             vf = &cptpf->vf[vf_idx];
0165             if (intr & (1ULL << vf->intr_idx)) {
0166                 queue_work(cptpf->vfpf_mbox_wq,
0167                        &vf->vfpf_mbox_work);
0168                 /* Clear the interrupt */
0169                 otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM,
0170                          0, RVU_PF_VFPF_MBOX_INTX(i),
0171                          BIT_ULL(vf->intr_idx));
0172             }
0173         }
0174     }
0175     return IRQ_HANDLED;
0176 }
0177 
0178 void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
0179 {
0180     struct otx2_cptpf_dev *cptpf;
0181     struct otx2_cptvf_info *vf;
0182     struct otx2_mbox_dev *mdev;
0183     struct mbox_hdr *req_hdr;
0184     struct mbox_msghdr *msg;
0185     struct otx2_mbox *mbox;
0186     int offset, i, err;
0187 
0188     vf = container_of(work, struct otx2_cptvf_info, vfpf_mbox_work);
0189     cptpf = vf->cptpf;
0190     mbox = &cptpf->vfpf_mbox;
0191     /* sync with mbox memory region */
0192     smp_rmb();
0193     mdev = &mbox->dev[vf->vf_id];
0194     /* Process received mbox messages */
0195     req_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
0196     offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
0197 
0198     for (i = 0; i < req_hdr->num_msgs; i++) {
0199         msg = (struct mbox_msghdr *)(mdev->mbase + offset);
0200 
0201         /* Set which VF sent this message based on mbox IRQ */
0202         msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) |
0203                 ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK);
0204 
0205         err = cptpf_handle_vf_req(cptpf, vf, msg,
0206                       msg->next_msgoff - offset);
0207         /*
0208          * Behave as the AF, drop the msg if there is
0209          * no memory, timeout handling also goes here
0210          */
0211         if (err == -ENOMEM || err == -EIO)
0212             break;
0213         offset = msg->next_msgoff;
0214         /* Write barrier required for VF responses which are handled by
0215          * PF driver and not forwarded to AF.
0216          */
0217         smp_wmb();
0218     }
0219     /* Send mbox responses to VF */
0220     if (mdev->num_msgs)
0221         otx2_mbox_msg_send(mbox, vf->vf_id);
0222 }
0223 
0224 irqreturn_t otx2_cptpf_afpf_mbox_intr(int __always_unused irq, void *arg)
0225 {
0226     struct otx2_cptpf_dev *cptpf = arg;
0227     u64 intr;
0228 
0229     /* Read the interrupt bits */
0230     intr = otx2_cpt_read64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT);
0231 
0232     if (intr & 0x1ULL) {
0233         /* Schedule work queue function to process the MBOX request */
0234         queue_work(cptpf->afpf_mbox_wq, &cptpf->afpf_mbox_work);
0235         /* Clear and ack the interrupt */
0236         otx2_cpt_write64(cptpf->reg_base, BLKADDR_RVUM, 0, RVU_PF_INT,
0237                  0x1ULL);
0238     }
0239     return IRQ_HANDLED;
0240 }
0241 
0242 static void process_afpf_mbox_msg(struct otx2_cptpf_dev *cptpf,
0243                   struct mbox_msghdr *msg)
0244 {
0245     struct device *dev = &cptpf->pdev->dev;
0246     struct cpt_rd_wr_reg_msg *rsp_rd_wr;
0247 
0248     if (msg->id >= MBOX_MSG_MAX) {
0249         dev_err(dev, "MBOX msg with unknown ID %d\n", msg->id);
0250         return;
0251     }
0252     if (msg->sig != OTX2_MBOX_RSP_SIG) {
0253         dev_err(dev, "MBOX msg with wrong signature %x, ID %d\n",
0254             msg->sig, msg->id);
0255         return;
0256     }
0257 
0258     switch (msg->id) {
0259     case MBOX_MSG_READY:
0260         cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) &
0261                 RVU_PFVF_PF_MASK;
0262         break;
0263     case MBOX_MSG_CPT_RD_WR_REGISTER:
0264         rsp_rd_wr = (struct cpt_rd_wr_reg_msg *)msg;
0265         if (msg->rc) {
0266             dev_err(dev, "Reg %llx rd/wr(%d) failed %d\n",
0267                 rsp_rd_wr->reg_offset, rsp_rd_wr->is_write,
0268                 msg->rc);
0269             return;
0270         }
0271         if (!rsp_rd_wr->is_write)
0272             *rsp_rd_wr->ret_val = rsp_rd_wr->val;
0273         break;
0274     case MBOX_MSG_ATTACH_RESOURCES:
0275         if (!msg->rc)
0276             cptpf->lfs.are_lfs_attached = 1;
0277         break;
0278     case MBOX_MSG_DETACH_RESOURCES:
0279         if (!msg->rc)
0280             cptpf->lfs.are_lfs_attached = 0;
0281         break;
0282 
0283     default:
0284         dev_err(dev,
0285             "Unsupported msg %d received.\n", msg->id);
0286         break;
0287     }
0288 }
0289 
0290 static void forward_to_vf(struct otx2_cptpf_dev *cptpf, struct mbox_msghdr *msg,
0291               int vf_id, int size)
0292 {
0293     struct otx2_mbox *vfpf_mbox;
0294     struct mbox_msghdr *fwd;
0295 
0296     if (msg->id >= MBOX_MSG_MAX) {
0297         dev_err(&cptpf->pdev->dev,
0298             "MBOX msg with unknown ID %d\n", msg->id);
0299         return;
0300     }
0301     if (msg->sig != OTX2_MBOX_RSP_SIG) {
0302         dev_err(&cptpf->pdev->dev,
0303             "MBOX msg with wrong signature %x, ID %d\n",
0304             msg->sig, msg->id);
0305         return;
0306     }
0307     vfpf_mbox = &cptpf->vfpf_mbox;
0308     vf_id--;
0309     if (vf_id >= cptpf->enabled_vfs) {
0310         dev_err(&cptpf->pdev->dev,
0311             "MBOX msg to unknown VF: %d >= %d\n",
0312             vf_id, cptpf->enabled_vfs);
0313         return;
0314     }
0315     if (msg->id == MBOX_MSG_VF_FLR)
0316         return;
0317 
0318     fwd = otx2_mbox_alloc_msg(vfpf_mbox, vf_id, size);
0319     if (!fwd) {
0320         dev_err(&cptpf->pdev->dev,
0321             "Forwarding to VF%d failed.\n", vf_id);
0322         return;
0323     }
0324     memcpy((uint8_t *)fwd + sizeof(struct mbox_msghdr),
0325         (uint8_t *)msg + sizeof(struct mbox_msghdr), size);
0326     fwd->id = msg->id;
0327     fwd->pcifunc = msg->pcifunc;
0328     fwd->sig = msg->sig;
0329     fwd->ver = msg->ver;
0330     fwd->rc = msg->rc;
0331 }
0332 
0333 /* Handle mailbox messages received from AF */
0334 void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
0335 {
0336     struct otx2_cptpf_dev *cptpf;
0337     struct otx2_mbox *afpf_mbox;
0338     struct otx2_mbox_dev *mdev;
0339     struct mbox_hdr *rsp_hdr;
0340     struct mbox_msghdr *msg;
0341     int offset, vf_id, i;
0342 
0343     cptpf = container_of(work, struct otx2_cptpf_dev, afpf_mbox_work);
0344     afpf_mbox = &cptpf->afpf_mbox;
0345     mdev = &afpf_mbox->dev[0];
0346     /* Sync mbox data into memory */
0347     smp_wmb();
0348 
0349     rsp_hdr = (struct mbox_hdr *)(mdev->mbase + afpf_mbox->rx_start);
0350     offset = ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
0351 
0352     for (i = 0; i < rsp_hdr->num_msgs; i++) {
0353         msg = (struct mbox_msghdr *)(mdev->mbase + afpf_mbox->rx_start +
0354                          offset);
0355         vf_id = (msg->pcifunc >> RVU_PFVF_FUNC_SHIFT) &
0356              RVU_PFVF_FUNC_MASK;
0357         if (vf_id > 0)
0358             forward_to_vf(cptpf, msg, vf_id,
0359                       msg->next_msgoff - offset);
0360         else
0361             process_afpf_mbox_msg(cptpf, msg);
0362 
0363         offset = msg->next_msgoff;
0364         /* Sync VF response ready to be sent */
0365         smp_wmb();
0366         mdev->msgs_acked++;
0367     }
0368     otx2_mbox_reset(afpf_mbox, 0);
0369 }