0001
0002
0003
0004
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
0148 otx2_mbox_reset(mbox, devid);
0149 }
0150
0151 return 0;
0152 }
0153 EXPORT_SYMBOL(otx2_mbox_init);
0154
0155
0156
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
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
0224
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
0236 mdev->msg_size = 0;
0237 mdev->rsp_size = 0;
0238 mdev->msgs_acked = 0;
0239
0240
0241 smp_wmb();
0242
0243
0244
0245
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
0255
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
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
0284 memset(msghdr, 0, size);
0285
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");