mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-26 07:35:44 +08:00
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: Harman Kalra <hkalra@marvell.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
8208285632
commit
4363f3d3ce
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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,16 +152,19 @@ 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;
|
||||
vf = vf - 64;
|
||||
if (vf >= 64) {
|
||||
reg = 1;
|
||||
vf = vf - 64;
|
||||
}
|
||||
/* Clear transaction pending register */
|
||||
otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0,
|
||||
RVU_PF_VFTRPENDX(reg), BIT_ULL(vf));
|
||||
otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0,
|
||||
RVU_PF_VFFLR_INT_ENA_W1SX(reg), BIT_ULL(vf));
|
||||
}
|
||||
/* Clear transaction pending register */
|
||||
otx2_cpt_write64(pf->reg_base, BLKADDR_RVUM, 0,
|
||||
RVU_PF_VFTRPENDX(reg), BIT_ULL(vf));
|
||||
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:
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user