Commit a36740f6 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-af: Add mbox API to validate all responses

Added a new mailbox API which goes through all responses
to check their IDs and response codes.

Also added logic to prevent queuing multiple works to
process the same mailbox message. This scenario happens
when AF is processing a PF's request and menawhile PF
sends ACK to AF sent UP message, then mbox_hdr->num_msgs
in the PF->AF DOWN mbox region will be nonzero and AF
will end up processing PF's request again. This is fixed
by taking a backup of num_msgs counter and clearing the
same in the mbox region before scheduling work.
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e07fb507
...@@ -236,8 +236,10 @@ struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid, ...@@ -236,8 +236,10 @@ struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid,
struct otx2_mbox_dev *mdev = &mbox->dev[devid]; struct otx2_mbox_dev *mdev = &mbox->dev[devid];
u16 msgs; u16 msgs;
spin_lock(&mdev->mbox_lock);
if (mdev->num_msgs != mdev->msgs_acked) if (mdev->num_msgs != mdev->msgs_acked)
return ERR_PTR(-ENODEV); goto error;
for (msgs = 0; msgs < mdev->msgs_acked; msgs++) { for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
struct mbox_msghdr *pmsg = mdev->mbase + imsg; struct mbox_msghdr *pmsg = mdev->mbase + imsg;
...@@ -245,18 +247,55 @@ struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid, ...@@ -245,18 +247,55 @@ struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid,
if (msg == pmsg) { if (msg == pmsg) {
if (pmsg->id != prsp->id) if (pmsg->id != prsp->id)
return ERR_PTR(-ENODEV); goto error;
spin_unlock(&mdev->mbox_lock);
return prsp; return prsp;
} }
imsg = pmsg->next_msgoff; imsg = mbox->tx_start + pmsg->next_msgoff;
irsp = prsp->next_msgoff; irsp = mbox->rx_start + prsp->next_msgoff;
} }
error:
spin_unlock(&mdev->mbox_lock);
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
EXPORT_SYMBOL(otx2_mbox_get_rsp); EXPORT_SYMBOL(otx2_mbox_get_rsp);
int otx2_mbox_check_rsp_msgs(struct otx2_mbox *mbox, int devid)
{
unsigned long ireq = mbox->tx_start + msgs_offset;
unsigned long irsp = mbox->rx_start + msgs_offset;
struct otx2_mbox_dev *mdev = &mbox->dev[devid];
int rc = -ENODEV;
u16 msgs;
spin_lock(&mdev->mbox_lock);
if (mdev->num_msgs != mdev->msgs_acked)
goto exit;
for (msgs = 0; msgs < mdev->msgs_acked; msgs++) {
struct mbox_msghdr *preq = mdev->mbase + ireq;
struct mbox_msghdr *prsp = mdev->mbase + irsp;
if (preq->id != prsp->id)
goto exit;
if (prsp->rc) {
rc = prsp->rc;
goto exit;
}
ireq = mbox->tx_start + preq->next_msgoff;
irsp = mbox->rx_start + prsp->next_msgoff;
}
rc = 0;
exit:
spin_unlock(&mdev->mbox_lock);
return rc;
}
EXPORT_SYMBOL(otx2_mbox_check_rsp_msgs);
int int
otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, u16 pcifunc, u16 id) otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, u16 pcifunc, u16 id)
{ {
......
...@@ -103,6 +103,7 @@ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid, ...@@ -103,6 +103,7 @@ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
int size, int size_rsp); int size, int size_rsp);
struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid, struct mbox_msghdr *otx2_mbox_get_rsp(struct otx2_mbox *mbox, int devid,
struct mbox_msghdr *msg); struct mbox_msghdr *msg);
int otx2_mbox_check_rsp_msgs(struct otx2_mbox *mbox, int devid);
int otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid, int otx2_reply_invalid_msg(struct otx2_mbox *mbox, int devid,
u16 pcifunc, u16 id); u16 pcifunc, u16 id);
bool otx2_mbox_nonempty(struct otx2_mbox *mbox, int devid); bool otx2_mbox_nonempty(struct otx2_mbox *mbox, int devid);
......
...@@ -1440,12 +1440,12 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type) ...@@ -1440,12 +1440,12 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
/* Process received mbox messages */ /* Process received mbox messages */
req_hdr = mdev->mbase + mbox->rx_start; req_hdr = mdev->mbase + mbox->rx_start;
if (req_hdr->num_msgs == 0) if (mw->mbox_wrk[devid].num_msgs == 0)
return; return;
offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN); offset = mbox->rx_start + ALIGN(sizeof(*req_hdr), MBOX_MSG_ALIGN);
for (id = 0; id < req_hdr->num_msgs; id++) { for (id = 0; id < mw->mbox_wrk[devid].num_msgs; id++) {
msg = mdev->mbase + offset; msg = mdev->mbase + offset;
/* Set which PF/VF sent this message based on mbox IRQ */ /* Set which PF/VF sent this message based on mbox IRQ */
...@@ -1471,13 +1471,14 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type) ...@@ -1471,13 +1471,14 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
if (msg->pcifunc & RVU_PFVF_FUNC_MASK) if (msg->pcifunc & RVU_PFVF_FUNC_MASK)
dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d:VF%d\n", dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d:VF%d\n",
err, otx2_mbox_id2name(msg->id), err, otx2_mbox_id2name(msg->id),
msg->id, devid, msg->id, rvu_get_pf(msg->pcifunc),
(msg->pcifunc & RVU_PFVF_FUNC_MASK) - 1); (msg->pcifunc & RVU_PFVF_FUNC_MASK) - 1);
else else
dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d\n", dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d\n",
err, otx2_mbox_id2name(msg->id), err, otx2_mbox_id2name(msg->id),
msg->id, devid); msg->id, devid);
} }
mw->mbox_wrk[devid].num_msgs = 0;
/* Send mbox responses to VF/PF */ /* Send mbox responses to VF/PF */
otx2_mbox_msg_send(mbox, devid); otx2_mbox_msg_send(mbox, devid);
...@@ -1523,14 +1524,14 @@ static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type) ...@@ -1523,14 +1524,14 @@ static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type)
mdev = &mbox->dev[devid]; mdev = &mbox->dev[devid];
rsp_hdr = mdev->mbase + mbox->rx_start; rsp_hdr = mdev->mbase + mbox->rx_start;
if (rsp_hdr->num_msgs == 0) { if (mw->mbox_wrk_up[devid].up_num_msgs == 0) {
dev_warn(rvu->dev, "mbox up handler: num_msgs = 0\n"); dev_warn(rvu->dev, "mbox up handler: num_msgs = 0\n");
return; return;
} }
offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN); offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
for (id = 0; id < rsp_hdr->num_msgs; id++) { for (id = 0; id < mw->mbox_wrk_up[devid].up_num_msgs; id++) {
msg = mdev->mbase + offset; msg = mdev->mbase + offset;
if (msg->id >= MBOX_MSG_MAX) { if (msg->id >= MBOX_MSG_MAX) {
...@@ -1560,6 +1561,7 @@ static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type) ...@@ -1560,6 +1561,7 @@ static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type)
offset = mbox->rx_start + msg->next_msgoff; offset = mbox->rx_start + msg->next_msgoff;
mdev->msgs_acked++; mdev->msgs_acked++;
} }
mw->mbox_wrk_up[devid].up_num_msgs = 0;
otx2_mbox_reset(mbox, devid); otx2_mbox_reset(mbox, devid);
} }
...@@ -1697,15 +1699,29 @@ static void rvu_queue_work(struct mbox_wq_info *mw, int first, ...@@ -1697,15 +1699,29 @@ static void rvu_queue_work(struct mbox_wq_info *mw, int first,
mbox = &mw->mbox; mbox = &mw->mbox;
mdev = &mbox->dev[i]; mdev = &mbox->dev[i];
hdr = mdev->mbase + mbox->rx_start; hdr = mdev->mbase + mbox->rx_start;
if (hdr->num_msgs)
queue_work(mw->mbox_wq, &mw->mbox_wrk[i].work);
/*The hdr->num_msgs is set to zero immediately in the interrupt
* handler to ensure that it holds a correct value next time
* when the interrupt handler is called.
* pf->mbox.num_msgs holds the data for use in pfaf_mbox_handler
* pf>mbox.up_num_msgs holds the data for use in
* pfaf_mbox_up_handler.
*/
if (hdr->num_msgs) {
mw->mbox_wrk[i].num_msgs = hdr->num_msgs;
hdr->num_msgs = 0;
queue_work(mw->mbox_wq, &mw->mbox_wrk[i].work);
}
mbox = &mw->mbox_up; mbox = &mw->mbox_up;
mdev = &mbox->dev[i]; mdev = &mbox->dev[i];
hdr = mdev->mbase + mbox->rx_start; hdr = mdev->mbase + mbox->rx_start;
if (hdr->num_msgs) if (hdr->num_msgs) {
mw->mbox_wrk_up[i].up_num_msgs = hdr->num_msgs;
hdr->num_msgs = 0;
queue_work(mw->mbox_wq, &mw->mbox_wrk_up[i].work); queue_work(mw->mbox_wq, &mw->mbox_wrk_up[i].work);
} }
}
} }
static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq) static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
......
...@@ -63,6 +63,8 @@ struct rvu_debugfs { ...@@ -63,6 +63,8 @@ struct rvu_debugfs {
struct rvu_work { struct rvu_work {
struct work_struct work; struct work_struct work;
struct rvu *rvu; struct rvu *rvu;
int num_msgs;
int up_num_msgs;
}; };
struct rsrc_bmap { struct rsrc_bmap {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment