common/cnxk: fix null pointer dereferences
[dpdk.git] / drivers / common / cnxk / roc_dev.c
index c14f189..0ac50ca 100644 (file)
@@ -152,6 +152,11 @@ af_pf_wait_msg(struct dev *dev, uint16_t vf, int num_msg)
                /* Reserve PF/VF mbox message */
                size = PLT_ALIGN(size, MBOX_MSG_ALIGN);
                rsp = mbox_alloc_msg(&dev->mbox_vfpf, vf, size);
+               if (!rsp) {
+                       plt_err("Failed to reserve VF%d message", vf);
+                       continue;
+               }
+
                mbox_rsp_init(msg->id, rsp);
 
                /* Copy message from AF<->PF mbox to PF<->VF mbox */
@@ -163,6 +168,39 @@ af_pf_wait_msg(struct dev *dev, uint16_t vf, int num_msg)
                rsp->rc = msg->rc;
                rsp->pcifunc = msg->pcifunc;
 
+               /* Whenever a PF comes up, AF sends the link status to it but
+                * when VF comes up no such event is sent to respective VF.
+                * Using MBOX_MSG_NIX_LF_START_RX response from AF for the
+                * purpose and send the link status of PF to VF.
+                */
+               if (msg->id == MBOX_MSG_NIX_LF_START_RX) {
+                       /* Send link status to VF */
+                       struct cgx_link_user_info linfo;
+                       struct mbox_msghdr *vf_msg;
+                       size_t sz;
+
+                       /* Get the link status */
+                       memset(&linfo, 0, sizeof(struct cgx_link_user_info));
+                       if (dev->ops && dev->ops->link_status_get)
+                               dev->ops->link_status_get(dev->roc_nix, &linfo);
+
+                       sz = PLT_ALIGN(mbox_id2size(MBOX_MSG_CGX_LINK_EVENT),
+                                      MBOX_MSG_ALIGN);
+                       /* Prepare the message to be sent */
+                       vf_msg = mbox_alloc_msg(&dev->mbox_vfpf_up, vf, sz);
+                       if (vf_msg) {
+                               mbox_req_init(MBOX_MSG_CGX_LINK_EVENT, vf_msg);
+                               memcpy((uint8_t *)vf_msg +
+                                      sizeof(struct mbox_msghdr), &linfo,
+                                      sizeof(struct cgx_link_user_info));
+
+                               vf_msg->rc = msg->rc;
+                               vf_msg->pcifunc = msg->pcifunc;
+                               /* Send to VF */
+                               mbox_msg_send(&dev->mbox_vfpf_up, vf);
+                       }
+               }
+
                offset = mbox->rx_start + msg->next_msgoff;
        }
        plt_spinlock_unlock(&mdev->mbox_lock);
@@ -203,6 +241,12 @@ vf_pf_process_msgs(struct dev *dev, uint16_t vf)
                                BIT_ULL(vf % max_bits);
                        rsp = (struct ready_msg_rsp *)mbox_alloc_msg(
                                mbox, vf, sizeof(*rsp));
+                       if (!rsp) {
+                               plt_err("Failed to alloc VF%d READY message",
+                                       vf);
+                               continue;
+                       }
+
                        mbox_rsp_init(msg->id, rsp);
 
                        /* PF/VF function ID */
@@ -608,7 +652,7 @@ roc_af_pf_mbox_irq(void *param)
 static int
 mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
        int i, rc;
 
        /* HW clear irq */
@@ -658,7 +702,7 @@ mbox_register_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 static int
 mbox_register_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
        int rc;
 
        /* Clear irq */
@@ -691,7 +735,7 @@ mbox_register_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 static void
 mbox_unregister_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
        int i;
 
        /* HW clear irq */
@@ -722,7 +766,7 @@ mbox_unregister_pf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 static void
 mbox_unregister_vf_irq(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
 
        /* Clear irq */
        plt_write64(~0ull, dev->bar2 + RVU_VF_INT_ENA_W1C);
@@ -806,7 +850,7 @@ roc_pf_vf_flr_irq(void *param)
 static int
 vf_flr_unregister_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
        int i;
 
        plt_base_dbg("Unregister VF FLR interrupts for %s", pci_dev->name);
@@ -827,7 +871,7 @@ vf_flr_unregister_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
 static int
 vf_flr_register_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
 {
-       struct plt_intr_handle *handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *handle = pci_dev->intr_handle;
        int i, rc;
 
        plt_base_dbg("Register VF FLR interrupts for %s", pci_dev->name);
@@ -851,6 +895,38 @@ vf_flr_register_irqs(struct plt_pci_device *pci_dev, struct dev *dev)
        return 0;
 }
 
+static void
+clear_rvum_interrupts(struct dev *dev)
+{
+       uint64_t intr;
+       int i;
+
+       if (dev_is_vf(dev)) {
+               /* Clear VF mbox interrupt */
+               intr = plt_read64(dev->bar2 + RVU_VF_INT);
+               if (intr)
+                       plt_write64(intr, dev->bar2 + RVU_VF_INT);
+       } else {
+               /* Clear AF PF interrupt line */
+               intr = plt_read64(dev->bar2 + RVU_PF_INT);
+               if (intr)
+                       plt_write64(intr, dev->bar2 + RVU_PF_INT);
+               for (i = 0; i < MAX_VFPF_DWORD_BITS; ++i) {
+                       /* Clear MBOX interrupts */
+                       intr = plt_read64(dev->bar2 + RVU_PF_VFPF_MBOX_INTX(i));
+                       if (intr)
+                               plt_write64(intr,
+                                           dev->bar2 +
+                                                   RVU_PF_VFPF_MBOX_INTX(i));
+                       /* Clear VF FLR interrupts */
+                       intr = plt_read64(dev->bar2 + RVU_PF_VFFLR_INTX(i));
+                       if (intr)
+                               plt_write64(intr,
+                                           dev->bar2 + RVU_PF_VFFLR_INTX(i));
+               }
+       }
+}
+
 int
 dev_active_vfs(struct dev *dev)
 {
@@ -923,6 +999,9 @@ dev_setup_shared_lmt_region(struct mbox *mbox, bool valid_iova, uint64_t iova)
        struct lmtst_tbl_setup_req *req;
 
        req = mbox_alloc_msg_lmtst_tbl_setup(mbox);
+       if (!req)
+               return -ENOSPC;
+
        /* This pcifunc is defined with primary pcifunc whose LMT address
         * will be shared. If call contains valid IOVA, following pcifunc
         * field is of no use.
@@ -996,6 +1075,11 @@ dev_lmt_setup(struct dev *dev)
         */
        if (!dev->disable_shared_lmt) {
                idev = idev_get_cfg();
+               if (!idev) {
+                       errno = EFAULT;
+                       goto free;
+               }
+
                if (!__atomic_load_n(&idev->lmt_pf_func, __ATOMIC_ACQUIRE)) {
                        idev->lmt_base_addr = dev->lmt_base;
                        idev->lmt_pf_func = dev->pf_func;
@@ -1057,6 +1141,9 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev)
                intr_offset = RVU_PF_INT;
        }
 
+       /* Clear all RVUM interrupts */
+       clear_rvum_interrupts(dev);
+
        /* Initialize the local mbox */
        rc = mbox_init(&dev->mbox_local, mbox, bar2, direction, 1, intr_offset);
        if (rc)
@@ -1143,7 +1230,7 @@ error:
 int
 dev_fini(struct dev *dev, struct plt_pci_device *pci_dev)
 {
-       struct plt_intr_handle *intr_handle = &pci_dev->intr_handle;
+       struct plt_intr_handle *intr_handle = pci_dev->intr_handle;
        struct mbox *mbox;
 
        /* Check if this dev hosts npalf and has 1+ refs */