Commit 4363f3d3 authored by Harman Kalra's avatar Harman Kalra Committed by Herbert Xu
Browse files

crypto: octeontx2 - add synchronization between mailbox accesses



Since there are two workqueues implemented in CPTPF driver - one
for handling mailbox requests from VFs and another for handling FLR.
In both cases PF driver will forward the request to AF driver by
writing to mailbox memory. A race condition may arise if two
simultaneous requests are written to mailbox memory. Introducing
locking mechanism to maintain synchronization between multiple
mailbox accesses.

Signed-off-by: default avatarHarman Kalra <hkalra@marvell.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 82082856
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -157,5 +157,6 @@ struct otx2_cptlfs_info;
int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs);
int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs);
int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs);
int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox);

#endif /* __OTX2_CPT_COMMON_H */
+14 −0
Original line number Diff line number Diff line
@@ -202,3 +202,17 @@ int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs)
	}
	return ret;
}

int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox)
{
	int err;

	if (!otx2_mbox_nonempty(mbox, 0))
		return 0;
	otx2_mbox_msg_send(mbox, 0);
	err = otx2_mbox_wait_for_rsp(mbox, 0);
	if (err)
		return err;

	return otx2_mbox_check_rsp_msgs(mbox, 0);
}
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct otx2_cptpf_dev {

	struct workqueue_struct	*flr_wq;
	struct cptpf_flr_work   *flr_work;
	struct mutex            lock;   /* serialize mailbox access */

	unsigned long cap_flag;
	u8 pf_id;               /* RVU PF number */
+13 −8
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ static void cptpf_flr_wq_handler(struct work_struct *work)

	vf = flr_work - pf->flr_work;

	mutex_lock(&pf->lock);
	req = otx2_mbox_alloc_msg_rsp(mbox, 0, sizeof(*req),
				      sizeof(struct msg_rsp));
	if (!req)
@@ -151,6 +152,7 @@ static void cptpf_flr_wq_handler(struct work_struct *work)
	req->pcifunc |= (vf + 1) & RVU_PFVF_FUNC_MASK;

	otx2_cpt_send_mbox_msg(mbox, pf->pdev);
	if (!otx2_cpt_sync_mbox_msg(&pf->afpf_mbox)) {

		if (vf >= 64) {
			reg = 1;
@@ -162,6 +164,8 @@ static void cptpf_flr_wq_handler(struct work_struct *work)
		otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0,
				 RVU_PF_VFFLR_INT_ENA_W1SX(reg), BIT_ULL(vf));
	}
	mutex_unlock(&pf->lock);
}

static irqreturn_t cptpf_vf_flr_intr(int __always_unused irq, void *arg)
{
@@ -468,6 +472,7 @@ static int cptpf_afpf_mbox_init(struct otx2_cptpf_dev *cptpf)
		goto error;

	INIT_WORK(&cptpf->afpf_mbox_work, otx2_cptpf_afpf_mbox_handler);
	mutex_init(&cptpf->lock);
	return 0;

error:
+17 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ static int forward_to_af(struct otx2_cptpf_dev *cptpf,
	struct mbox_msghdr *msg;
	int ret;

	mutex_lock(&cptpf->lock);
	msg = otx2_mbox_alloc_msg(&cptpf->afpf_mbox, 0, size);
	if (msg == NULL)
		return -ENOMEM;
@@ -29,15 +30,19 @@ static int forward_to_af(struct otx2_cptpf_dev *cptpf,
	msg->sig = req->sig;
	msg->ver = req->ver;

	otx2_mbox_msg_send(&cptpf->afpf_mbox, 0);
	ret = otx2_mbox_wait_for_rsp(&cptpf->afpf_mbox, 0);
	ret = otx2_cpt_sync_mbox_msg(&cptpf->afpf_mbox);
	/* Error code -EIO indicate there is a communication failure
	 * to the AF. Rest of the error codes indicate that AF processed
	 * VF messages and set the error codes in response messages
	 * (if any) so simply forward responses to VF.
	 */
	if (ret == -EIO) {
		dev_err(&cptpf->pdev->dev, "RVU MBOX timeout.\n");
		dev_warn(&cptpf->pdev->dev,
			 "AF not responding to VF%d messages\n", vf->vf_id);
		mutex_unlock(&cptpf->lock);
		return ret;
	} else if (ret) {
		dev_err(&cptpf->pdev->dev, "RVU MBOX error: %d.\n", ret);
		return -EFAULT;
	}
	mutex_unlock(&cptpf->lock);
	return 0;
}

@@ -204,6 +209,10 @@ void otx2_cptpf_vfpf_mbox_handler(struct work_struct *work)
		if (err == -ENOMEM || err == -EIO)
			break;
		offset = msg->next_msgoff;
		/* Write barrier required for VF responses which are handled by
		 * PF driver and not forwarded to AF.
		 */
		smp_wmb();
	}
	/* Send mbox responses to VF */
	if (mdev->num_msgs)
@@ -350,6 +359,8 @@ void otx2_cptpf_afpf_mbox_handler(struct work_struct *work)
			process_afpf_mbox_msg(cptpf, msg);

		offset = msg->next_msgoff;
		/* Sync VF response ready to be sent */
		smp_wmb();
		mdev->msgs_acked++;
	}
	otx2_mbox_reset(afpf_mbox, 0);