Skip to content

Commit

Permalink
Merge branch 'octeontx2-pf-mbox-fixes'
Browse files Browse the repository at this point in the history
Subbaraya Sundeep says:

====================
octeontx2-pf: RVU Mailbox fixes

This patchset fixes the problems related to RVU mailbox.
During long run tests some times VF commands like setting
MTU or toggling interface fails because VF mailbox is timedout
waiting for response from PF.

Below are the fixes
Patch 1: There are two types of messages in RVU mailbox namely up and down
messages. Down messages are synchronous messages where a PF/VF sends
a message to AF and AF replies back with response. UP messages are
notifications and are asynchronous like AF sending link events to
PF. When VF sends a down message to PF, PF forwards to AF and sends
the response from AF back to VF. PF has to forward VF messages since
there is no path in hardware for VF to send directly to AF.
There is one mailbox interrupt from AF to PF when raised could mean
two scenarios one is where AF sending reply to PF for a down message
sent by PF and another one is AF sending up message asynchronously
when link changed for that PF. Receiving the up message interrupt while
PF is in middle of forwarding down message causes mailbox errors.
Fix this by receiver detecting the type of message from the mbox data register
set by sender.

Patch 2:
During VF driver remove, VF has to wait until last message is
completed and then turn off mailbox interrupts from PF.

Patch 3:
Do not use ordered workqueue for message processing since multiple works are
queued simultaneously by all the VFs and PF link UP messages.

Patch 4:
When sending link event to VF by PF check whether VF is really up to
receive this message.

Patch 5:
In AF driver, use separate interrupt handlers for the AF-VF interrupt and
AF-PF interrupt. Sometimes both interrupts are raised to two CPUs at same
time and both CPUs execute same function at same time corrupting the data.

v2 changes:
	Added missing mutex unlock in error path in patch 1
	Refactored if else logic in patch 1 as suggested by Paolo Abeni
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 20, 2024
2 parents 94e3ca2 + 50e60de commit 9c6a595
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 88 deletions.
43 changes: 41 additions & 2 deletions drivers/net/ethernet/marvell/octeontx2/af/mbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,12 @@ int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid)
}
EXPORT_SYMBOL(otx2_mbox_busy_poll_for_rsp);

void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)
{
struct otx2_mbox_dev *mdev = &mbox->dev[devid];
struct mbox_hdr *tx_hdr, *rx_hdr;
void *hw_mbase = mdev->hwbase;
u64 intr_val;

tx_hdr = hw_mbase + mbox->tx_start;
rx_hdr = hw_mbase + mbox->rx_start;
Expand Down Expand Up @@ -254,14 +255,52 @@ void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)

spin_unlock(&mdev->mbox_lock);

/* Check if interrupt pending */
intr_val = readq((void __iomem *)mbox->reg_base +
(mbox->trigger | (devid << mbox->tr_shift)));

intr_val |= data;
/* The interrupt should be fired after num_msgs is written
* to the shared memory
*/
writeq(1, (void __iomem *)mbox->reg_base +
writeq(intr_val, (void __iomem *)mbox->reg_base +
(mbox->trigger | (devid << mbox->tr_shift)));
}

void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
{
otx2_mbox_msg_send_data(mbox, devid, MBOX_DOWN_MSG);
}
EXPORT_SYMBOL(otx2_mbox_msg_send);

void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid)
{
otx2_mbox_msg_send_data(mbox, devid, MBOX_UP_MSG);
}
EXPORT_SYMBOL(otx2_mbox_msg_send_up);

bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid)
{
u64 data;

data = readq((void __iomem *)mbox->reg_base +
(mbox->trigger | (devid << mbox->tr_shift)));

/* If data is non-zero wait for ~1ms and return to caller
* whether data has changed to zero or not after the wait.
*/
if (!data)
return true;

usleep_range(950, 1000);

data = readq((void __iomem *)mbox->reg_base +
(mbox->trigger | (devid << mbox->tr_shift)));

return data == 0;
}
EXPORT_SYMBOL(otx2_mbox_wait_for_zero);

struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
int size, int size_rsp)
{
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/mbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

#define MBOX_SIZE SZ_64K

#define MBOX_DOWN_MSG 1
#define MBOX_UP_MSG 2

/* AF/PF: PF initiated, PF/VF VF initiated */
#define MBOX_DOWN_RX_START 0
#define MBOX_DOWN_RX_SIZE (46 * SZ_1K)
Expand Down Expand Up @@ -101,6 +104,7 @@ int otx2_mbox_regions_init(struct otx2_mbox *mbox, void __force **hwbase,
struct pci_dev *pdev, void __force *reg_base,
int direction, int ndevs, unsigned long *bmap);
void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid);
void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid);
int otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid);
int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid);
struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
Expand All @@ -118,6 +122,8 @@ static inline struct mbox_msghdr *otx2_mbox_alloc_msg(struct otx2_mbox *mbox,
return otx2_mbox_alloc_msg_rsp(mbox, devid, size, 0);
}

bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid);

/* Mailbox message types */
#define MBOX_MSG_MASK 0xFFFF
#define MBOX_MSG_INVALID 0xFFFE
Expand Down
17 changes: 11 additions & 6 deletions drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,29 @@ int mcs_add_intr_wq_entry(struct mcs *mcs, struct mcs_intr_event *event)
static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)
{
struct mcs_intr_info *req;
int err, pf;
int pf;

pf = rvu_get_pf(event->pcifunc);

mutex_lock(&rvu->mbox_lock);

req = otx2_mbox_alloc_msg_mcs_intr_notify(rvu, pf);
if (!req)
if (!req) {
mutex_unlock(&rvu->mbox_lock);
return -ENOMEM;
}

req->mcs_id = event->mcs_id;
req->intr_mask = event->intr_mask;
req->sa_id = event->sa_id;
req->hdr.pcifunc = event->pcifunc;
req->lmac_id = event->lmac_id;

otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pf);
err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pf);
if (err)
dev_warn(rvu->dev, "MCS notification to pf %d failed\n", pf);
otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);

otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);

mutex_unlock(&rvu->mbox_lock);

return 0;
}
Expand Down
31 changes: 25 additions & 6 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,7 +2119,7 @@ MBOX_MESSAGES
}
}

static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll)
{
struct rvu *rvu = mwork->rvu;
int offset, err, id, devid;
Expand Down Expand Up @@ -2186,22 +2186,28 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
}
mw->mbox_wrk[devid].num_msgs = 0;

if (poll)
otx2_mbox_wait_for_zero(mbox, devid);

/* Send mbox responses to VF/PF */
otx2_mbox_msg_send(mbox, devid);
}

static inline void rvu_afpf_mbox_handler(struct work_struct *work)
{
struct rvu_work *mwork = container_of(work, struct rvu_work, work);
struct rvu *rvu = mwork->rvu;

__rvu_mbox_handler(mwork, TYPE_AFPF);
mutex_lock(&rvu->mbox_lock);
__rvu_mbox_handler(mwork, TYPE_AFPF, true);
mutex_unlock(&rvu->mbox_lock);
}

static inline void rvu_afvf_mbox_handler(struct work_struct *work)
{
struct rvu_work *mwork = container_of(work, struct rvu_work, work);

__rvu_mbox_handler(mwork, TYPE_AFVF);
__rvu_mbox_handler(mwork, TYPE_AFVF, false);
}

static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type)
Expand Down Expand Up @@ -2376,6 +2382,8 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
}
}

mutex_init(&rvu->mbox_lock);

mbox_regions = kcalloc(num, sizeof(void *), GFP_KERNEL);
if (!mbox_regions) {
err = -ENOMEM;
Expand Down Expand Up @@ -2525,10 +2533,9 @@ static void rvu_queue_work(struct mbox_wq_info *mw, int first,
}
}

static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
static irqreturn_t rvu_mbox_pf_intr_handler(int irq, void *rvu_irq)
{
struct rvu *rvu = (struct rvu *)rvu_irq;
int vfs = rvu->vfs;
u64 intr;

intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFAF_MBOX_INT);
Expand All @@ -2542,6 +2549,18 @@ static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)

rvu_queue_work(&rvu->afpf_wq_info, 0, rvu->hw->total_pfs, intr);

return IRQ_HANDLED;
}

static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
{
struct rvu *rvu = (struct rvu *)rvu_irq;
int vfs = rvu->vfs;
u64 intr;

/* Sync with mbox memory region */
rmb();

/* Handle VF interrupts */
if (vfs > 64) {
intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(1));
Expand Down Expand Up @@ -2886,7 +2905,7 @@ static int rvu_register_interrupts(struct rvu *rvu)
/* Register mailbox interrupt handler */
sprintf(&rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], "RVUAF Mbox");
ret = request_irq(pci_irq_vector(rvu->pdev, RVU_AF_INT_VEC_MBOX),
rvu_mbox_intr_handler, 0,
rvu_mbox_pf_intr_handler, 0,
&rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], rvu);
if (ret) {
dev_err(rvu->dev,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ struct rvu {
spinlock_t mcs_intrq_lock;
/* CPT interrupt lock */
spinlock_t cpt_intr_lock;

struct mutex mbox_lock; /* Serialize mbox up and down msgs */
};

static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
Expand Down
20 changes: 13 additions & 7 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
struct cgx_link_user_info *linfo;
struct cgx_link_info_msg *msg;
unsigned long pfmap;
int err, pfid;
int pfid;

linfo = &event->link_uinfo;
pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id);
Expand All @@ -255,16 +255,22 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
continue;
}

mutex_lock(&rvu->mbox_lock);

/* Send mbox message to PF */
msg = otx2_mbox_alloc_msg_cgx_link_event(rvu, pfid);
if (!msg)
if (!msg) {
mutex_unlock(&rvu->mbox_lock);
continue;
}

msg->link_info = *linfo;
otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pfid);
err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pfid);
if (err)
dev_warn(rvu->dev, "notification to pf %d failed\n",
pfid);

otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pfid);

otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pfid);

mutex_unlock(&rvu->mbox_lock);
} while (pfmap);
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1592,7 +1592,7 @@ int otx2_detach_resources(struct mbox *mbox)
detach->partial = false;

/* Send detach request to AF */
otx2_mbox_msg_send(&mbox->mbox, 0);
otx2_sync_mbox_msg(mbox);
mutex_unlock(&mbox->lock);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ static inline int otx2_sync_mbox_up_msg(struct mbox *mbox, int devid)

if (!otx2_mbox_nonempty(&mbox->mbox_up, devid))
return 0;
otx2_mbox_msg_send(&mbox->mbox_up, devid);
otx2_mbox_msg_send_up(&mbox->mbox_up, devid);
err = otx2_mbox_wait_for_rsp(&mbox->mbox_up, devid);
if (err)
return err;
Expand Down
Loading

0 comments on commit 9c6a595

Please sign in to comment.