Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Marvell RVU Admin Function driver
0003  *
0004  * Copyright (C) 2018 Marvell.
0005  *
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/pci.h>
0011 
0012 #include "rvu_reg.h"
0013 #include "mbox.h"
0014 #include "rvu_trace.h"
0015 
0016 static const u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
0017 
0018 void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
0019 {
0020     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0021     struct mbox_hdr *tx_hdr, *rx_hdr;
0022     void *hw_mbase = mdev->hwbase;
0023 
0024     tx_hdr = hw_mbase + mbox->tx_start;
0025     rx_hdr = hw_mbase + mbox->rx_start;
0026 
0027     mdev->msg_size = 0;
0028     mdev->rsp_size = 0;
0029     tx_hdr->num_msgs = 0;
0030     tx_hdr->msg_size = 0;
0031     rx_hdr->num_msgs = 0;
0032     rx_hdr->msg_size = 0;
0033 }
0034 EXPORT_SYMBOL(__otx2_mbox_reset);
0035 
0036 void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
0037 {
0038     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0039 
0040     spin_lock(&mdev->mbox_lock);
0041     __otx2_mbox_reset(mbox, devid);
0042     spin_unlock(&mdev->mbox_lock);
0043 }
0044 EXPORT_SYMBOL(otx2_mbox_reset);
0045 
0046 void otx2_mbox_destroy(struct otx2_mbox *mbox)
0047 {
0048     mbox->reg_base = NULL;
0049     mbox->hwbase = NULL;
0050 
0051     kfree(mbox->dev);
0052     mbox->dev = NULL;
0053 }
0054 EXPORT_SYMBOL(otx2_mbox_destroy);
0055 
0056 static int otx2_mbox_setup(struct otx2_mbox *mbox, struct pci_dev *pdev,
0057                void *reg_base, int direction, int ndevs)
0058 {
0059     switch (direction) {
0060     case MBOX_DIR_AFPF:
0061     case MBOX_DIR_PFVF:
0062         mbox->tx_start = MBOX_DOWN_TX_START;
0063         mbox->rx_start = MBOX_DOWN_RX_START;
0064         mbox->tx_size  = MBOX_DOWN_TX_SIZE;
0065         mbox->rx_size  = MBOX_DOWN_RX_SIZE;
0066         break;
0067     case MBOX_DIR_PFAF:
0068     case MBOX_DIR_VFPF:
0069         mbox->tx_start = MBOX_DOWN_RX_START;
0070         mbox->rx_start = MBOX_DOWN_TX_START;
0071         mbox->tx_size  = MBOX_DOWN_RX_SIZE;
0072         mbox->rx_size  = MBOX_DOWN_TX_SIZE;
0073         break;
0074     case MBOX_DIR_AFPF_UP:
0075     case MBOX_DIR_PFVF_UP:
0076         mbox->tx_start = MBOX_UP_TX_START;
0077         mbox->rx_start = MBOX_UP_RX_START;
0078         mbox->tx_size  = MBOX_UP_TX_SIZE;
0079         mbox->rx_size  = MBOX_UP_RX_SIZE;
0080         break;
0081     case MBOX_DIR_PFAF_UP:
0082     case MBOX_DIR_VFPF_UP:
0083         mbox->tx_start = MBOX_UP_RX_START;
0084         mbox->rx_start = MBOX_UP_TX_START;
0085         mbox->tx_size  = MBOX_UP_RX_SIZE;
0086         mbox->rx_size  = MBOX_UP_TX_SIZE;
0087         break;
0088     default:
0089         return -ENODEV;
0090     }
0091 
0092     switch (direction) {
0093     case MBOX_DIR_AFPF:
0094     case MBOX_DIR_AFPF_UP:
0095         mbox->trigger = RVU_AF_AFPF_MBOX0;
0096         mbox->tr_shift = 4;
0097         break;
0098     case MBOX_DIR_PFAF:
0099     case MBOX_DIR_PFAF_UP:
0100         mbox->trigger = RVU_PF_PFAF_MBOX1;
0101         mbox->tr_shift = 0;
0102         break;
0103     case MBOX_DIR_PFVF:
0104     case MBOX_DIR_PFVF_UP:
0105         mbox->trigger = RVU_PF_VFX_PFVF_MBOX0;
0106         mbox->tr_shift = 12;
0107         break;
0108     case MBOX_DIR_VFPF:
0109     case MBOX_DIR_VFPF_UP:
0110         mbox->trigger = RVU_VF_VFPF_MBOX1;
0111         mbox->tr_shift = 0;
0112         break;
0113     default:
0114         return -ENODEV;
0115     }
0116 
0117     mbox->reg_base = reg_base;
0118     mbox->pdev = pdev;
0119 
0120     mbox->dev = kcalloc(ndevs, sizeof(struct otx2_mbox_dev), GFP_KERNEL);
0121     if (!mbox->dev) {
0122         otx2_mbox_destroy(mbox);
0123         return -ENOMEM;
0124     }
0125     mbox->ndevs = ndevs;
0126 
0127     return 0;
0128 }
0129 
0130 int otx2_mbox_init(struct otx2_mbox *mbox, void *hwbase, struct pci_dev *pdev,
0131            void *reg_base, int direction, int ndevs)
0132 {
0133     struct otx2_mbox_dev *mdev;
0134     int devid, err;
0135 
0136     err = otx2_mbox_setup(mbox, pdev, reg_base, direction, ndevs);
0137     if (err)
0138         return err;
0139 
0140     mbox->hwbase = hwbase;
0141 
0142     for (devid = 0; devid < ndevs; devid++) {
0143         mdev = &mbox->dev[devid];
0144         mdev->mbase = mbox->hwbase + (devid * MBOX_SIZE);
0145         mdev->hwbase = mdev->mbase;
0146         spin_lock_init(&mdev->mbox_lock);
0147         /* Init header to reset value */
0148         otx2_mbox_reset(mbox, devid);
0149     }
0150 
0151     return 0;
0152 }
0153 EXPORT_SYMBOL(otx2_mbox_init);
0154 
0155 /* Initialize mailbox with the set of mailbox region addresses
0156  * in the array hwbase.
0157  */
0158 int otx2_mbox_regions_init(struct otx2_mbox *mbox, void **hwbase,
0159                struct pci_dev *pdev, void *reg_base,
0160                int direction, int ndevs)
0161 {
0162     struct otx2_mbox_dev *mdev;
0163     int devid, err;
0164 
0165     err = otx2_mbox_setup(mbox, pdev, reg_base, direction, ndevs);
0166     if (err)
0167         return err;
0168 
0169     mbox->hwbase = hwbase[0];
0170 
0171     for (devid = 0; devid < ndevs; devid++) {
0172         mdev = &mbox->dev[devid];
0173         mdev->mbase = hwbase[devid];
0174         mdev->hwbase = hwbase[devid];
0175         spin_lock_init(&mdev->mbox_lock);
0176         /* Init header to reset value */
0177         otx2_mbox_reset(mbox, devid);
0178     }
0179 
0180     return 0;
0181 }
0182 EXPORT_SYMBOL(otx2_mbox_regions_init);
0183 
0184 int otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid)
0185 {
0186     unsigned long timeout = jiffies + msecs_to_jiffies(MBOX_RSP_TIMEOUT);
0187     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0188     struct device *sender = &mbox->pdev->dev;
0189 
0190     while (!time_after(jiffies, timeout)) {
0191         if (mdev->num_msgs == mdev->msgs_acked)
0192             return 0;
0193         usleep_range(800, 1000);
0194     }
0195     dev_dbg(sender, "timed out while waiting for rsp\n");
0196     return -EIO;
0197 }
0198 EXPORT_SYMBOL(otx2_mbox_wait_for_rsp);
0199 
0200 int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid)
0201 {
0202     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0203     unsigned long timeout = jiffies + 1 * HZ;
0204 
0205     while (!time_after(jiffies, timeout)) {
0206         if (mdev->num_msgs == mdev->msgs_acked)
0207             return 0;
0208         cpu_relax();
0209     }
0210     return -EIO;
0211 }
0212 EXPORT_SYMBOL(otx2_mbox_busy_poll_for_rsp);
0213 
0214 void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
0215 {
0216     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0217     struct mbox_hdr *tx_hdr, *rx_hdr;
0218     void *hw_mbase = mdev->hwbase;
0219 
0220     tx_hdr = hw_mbase + mbox->tx_start;
0221     rx_hdr = hw_mbase + mbox->rx_start;
0222 
0223     /* If bounce buffer is implemented copy mbox messages from
0224      * bounce buffer to hw mbox memory.
0225      */
0226     if (mdev->mbase != hw_mbase)
0227         memcpy(hw_mbase + mbox->tx_start + msgs_offset,
0228                mdev->mbase + mbox->tx_start + msgs_offset,
0229                mdev->msg_size);
0230 
0231     spin_lock(&mdev->mbox_lock);
0232 
0233     tx_hdr->msg_size = mdev->msg_size;
0234 
0235     /* Reset header for next messages */
0236     mdev->msg_size = 0;
0237     mdev->rsp_size = 0;
0238     mdev->msgs_acked = 0;
0239 
0240     /* Sync mbox data into memory */
0241     smp_wmb();
0242 
0243     /* num_msgs != 0 signals to the peer that the buffer has a number of
0244      * messages.  So this should be written after writing all the messages
0245      * to the shared memory.
0246      */
0247     tx_hdr->num_msgs = mdev->num_msgs;
0248     rx_hdr->num_msgs = 0;
0249 
0250     trace_otx2_msg_send(mbox->pdev, tx_hdr->num_msgs, tx_hdr->msg_size);
0251 
0252     spin_unlock(&mdev->mbox_lock);
0253 
0254     /* The interrupt should be fired after num_msgs is written
0255      * to the shared memory
0256      */
0257     writeq(1, (void __iomem *)mbox->reg_base +
0258            (mbox->trigger | (devid << mbox->tr_shift)));
0259 }
0260 EXPORT_SYMBOL(otx2_mbox_msg_send);
0261 
0262 struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
0263                         int size, int size_rsp)
0264 {
0265     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0266     struct mbox_msghdr *msghdr = NULL;
0267 
0268     spin_lock(&mdev->mbox_lock);
0269     size = ALIGN(size, MBOX_MSG_ALIGN);
0270     size_rsp = ALIGN(size_rsp, MBOX_MSG_ALIGN);
0271     /* Check if there is space in mailbox */
0272     if ((mdev->msg_size + size) > mbox->tx_size - msgs_offset)
0273         goto exit;
0274     if ((mdev->rsp_size + size_rsp) > mbox->rx_size - msgs_offset)
0275         goto exit;
0276 
0277     if (mdev->msg_size == 0)
0278         mdev->num_msgs = 0;
0279     mdev->num_msgs++;
0280 
0281     msghdr = mdev->mbase + mbox->tx_start + msgs_offset + mdev->msg_size;
0282 
0283     /* Clear the whole msg region */
0284     memset(msghdr, 0, size);
0285     /* Init message header with reset values */
0286     msghdr->ver = OTX2_MBOX_VERSION;
0287     mdev->msg_size += size;
0288     mdev->rsp_size += size_rsp;
0289     msghdr->next_msgoff = mdev->msg_size + msgs_offset;
0290 exit:
0291     spin_unlock(&mdev->mbox_lock);
0292 
0293     return msghdr;
0294 }
0295 EXPORT_SYMBOL(otx2_mbox_alloc_msg_rsp);
0296 
0297 struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid,
0298                       struct mbox_msghdr *msg)
0299 {
0300     unsigned long imsg = mbox->tx_start + msgs_offset;
0301     unsigned long irsp = mbox->rx_start + msgs_offset;
0302     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0303     u16 msgs;
0304 
0305     spin_lock(&mdev->mbox_lock);
0306 
0307     if (mdev->num_msgs != mdev->msgs_acked)
0308         goto error;
0309 
0310     for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
0311         struct mbox_msghdr *pmsg = mdev->mbase + imsg;
0312         struct mbox_msghdr *prsp = mdev->mbase + irsp;
0313 
0314         if (msg == pmsg) {
0315             if (pmsg->id != prsp->id)
0316                 goto error;
0317             spin_unlock(&mdev->mbox_lock);
0318             return prsp;
0319         }
0320 
0321         imsg = mbox->tx_start + pmsg->next_msgoff;
0322         irsp = mbox->rx_start + prsp->next_msgoff;
0323     }
0324 
0325 error:
0326     spin_unlock(&mdev->mbox_lock);
0327     return ERR_PTR(-ENODEV);
0328 }
0329 EXPORT_SYMBOL(otx2_mbox_get_rsp);
0330 
0331 int otx2_mbox_check_rsp_msgs(struct otx2_mbox *mbox, int devid)
0332 {
0333     unsigned long ireq = mbox->tx_start + msgs_offset;
0334     unsigned long irsp = mbox->rx_start + msgs_offset;
0335     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0336     int rc = -ENODEV;
0337     u16 msgs;
0338 
0339     spin_lock(&mdev->mbox_lock);
0340 
0341     if (mdev->num_msgs != mdev->msgs_acked)
0342         goto exit;
0343 
0344     for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
0345         struct mbox_msghdr *preq = mdev->mbase + ireq;
0346         struct mbox_msghdr *prsp = mdev->mbase + irsp;
0347 
0348         if (preq->id != prsp->id) {
0349             trace_otx2_msg_check(mbox->pdev, preq->id,
0350                          prsp->id, prsp->rc);
0351             goto exit;
0352         }
0353         if (prsp->rc) {
0354             rc = prsp->rc;
0355             trace_otx2_msg_check(mbox->pdev, preq->id,
0356                          prsp->id, prsp->rc);
0357             goto exit;
0358         }
0359 
0360         ireq = mbox->tx_start + preq->next_msgoff;
0361         irsp = mbox->rx_start + prsp->next_msgoff;
0362     }
0363     rc = 0;
0364 exit:
0365     spin_unlock(&mdev->mbox_lock);
0366     return rc;
0367 }
0368 EXPORT_SYMBOL(otx2_mbox_check_rsp_msgs);
0369 
0370 int
0371 otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, u16 pcifunc, u16 id)
0372 {
0373     struct msg_rsp *rsp;
0374 
0375     rsp = (struct msg_rsp *)
0376            otx2_mbox_alloc_msg(mbox, devid, sizeof(*rsp));
0377     if (!rsp)
0378         return -ENOMEM;
0379     rsp->hdr.id = id;
0380     rsp->hdr.sig = OTX2_MBOX_RSP_SIG;
0381     rsp->hdr.rc = MBOX_MSG_INVALID;
0382     rsp->hdr.pcifunc = pcifunc;
0383     return 0;
0384 }
0385 EXPORT_SYMBOL(otx2_reply_invalid_msg);
0386 
0387 bool otx2_mbox_nonempty(struct otx2_mbox *mbox, int devid)
0388 {
0389     struct otx2_mbox_dev *mdev = &mbox->dev[devid];
0390     bool ret;
0391 
0392     spin_lock(&mdev->mbox_lock);
0393     ret = mdev->num_msgs != 0;
0394     spin_unlock(&mdev->mbox_lock);
0395 
0396     return ret;
0397 }
0398 EXPORT_SYMBOL(otx2_mbox_nonempty);
0399 
0400 const char *otx2_mbox_id2name(u16 id)
0401 {
0402     switch (id) {
0403 #define M(_name, _id, _1, _2, _3) case _id: return # _name;
0404     MBOX_MESSAGES
0405 #undef M
0406     default:
0407         return "INVALID ID";
0408     }
0409 }
0410 EXPORT_SYMBOL(otx2_mbox_id2name);
0411 
0412 MODULE_AUTHOR("Marvell.");
0413 MODULE_LICENSE("GPL v2");