}
#define ENETC_PSIMSGRR 0x204
-#define ENETC_PSIMSGRR_MR_MASK GENMASK(2, 1)
-#define ENETC_PSIMSGRR_MR(n) BIT((n) + 1) /* n = VSI index */
#define ENETC_PSIVMSGRCVAR0(n) (0x210 + (n) * 0x8) /* n = VSI index */
#define ENETC_PSIVMSGRCVAR1(n) (0x214 + (n) * 0x8)
+/* Message received mask, n is the active number of VSIs.
+ * It is available for ENETC_PSIMSGRR, ENETC_PSIIER, and
+ * ENETC_PSIIDR registers.
+ */
+#define ENETC_PSIMR_MASK(n) \
+ ({ typeof(n) _n = (n); (_n) ? GENMASK((_n), 1) : 0; })
+
+/* Message received bit, n is VSI index. It is available for
+ * ENETC_PSIMSGRR, ENETC_PSIIER, and ENETC_PSIIDR registers.
+ */
+#define ENETC_PSIMR_BIT(n) BIT((n) + 1)
+
#define ENETC_VSIMSGSR 0x204 /* RO */
#define ENETC_VSIMSGSR_MB BIT(0)
#define ENETC_VSIMSGSR_MS BIT(1)
#define ENETC_SICAPR1 0x904
#define ENETC_PSIIER 0xa00
-#define ENETC_PSIIER_MR_MASK GENMASK(2, 1)
#define ENETC_PSIIDR 0xa08
#define ENETC_SITXIDR 0xa18
#define ENETC_SIRXIDR 0xa28
#include "enetc_pf.h"
-static void enetc_msg_disable_mr_int(struct enetc_hw *hw)
+static void enetc_msg_disable_mr_int(struct enetc_pf *pf)
{
- u32 psiier = enetc_rd(hw, ENETC_PSIIER);
+ struct enetc_hw *hw = &pf->si->hw;
+ u32 psiier;
+
+ psiier = enetc_rd(hw, ENETC_PSIIER) & ~ENETC_PSIMR_MASK(pf->num_vfs);
+
/* disable MR int source(s) */
- enetc_wr(hw, ENETC_PSIIER, psiier & ~ENETC_PSIIER_MR_MASK);
+ enetc_wr(hw, ENETC_PSIIER, psiier);
}
-static void enetc_msg_enable_mr_int(struct enetc_hw *hw)
+static void enetc_msg_enable_mr_int(struct enetc_pf *pf)
{
- u32 psiier = enetc_rd(hw, ENETC_PSIIER);
+ struct enetc_hw *hw = &pf->si->hw;
+ u32 psiier;
- enetc_wr(hw, ENETC_PSIIER, psiier | ENETC_PSIIER_MR_MASK);
+ psiier = enetc_rd(hw, ENETC_PSIIER) | ENETC_PSIMR_MASK(pf->num_vfs);
+
+ enetc_wr(hw, ENETC_PSIIER, psiier);
}
static irqreturn_t enetc_msg_psi_msix(int irq, void *data)
struct enetc_si *si = (struct enetc_si *)data;
struct enetc_pf *pf = enetc_si_priv(si);
- enetc_msg_disable_mr_int(&si->hw);
+ enetc_msg_disable_mr_int(pf);
schedule_work(&pf->msg_task);
return IRQ_HANDLED;
static void enetc_msg_task(struct work_struct *work)
{
struct enetc_pf *pf = container_of(work, struct enetc_pf, msg_task);
+ u32 mr_mask = ENETC_PSIMR_MASK(pf->num_vfs);
struct enetc_hw *hw = &pf->si->hw;
- unsigned long mr_mask;
+ u32 mr_status;
int i;
- for (;;) {
- mr_mask = enetc_rd(hw, ENETC_PSIMSGRR) & ENETC_PSIMSGRR_MR_MASK;
- if (!mr_mask) {
- /* re-arm MR interrupts, w1c the IDR reg */
- enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIIER_MR_MASK);
- enetc_msg_enable_mr_int(hw);
- return;
- }
+ mr_status = (enetc_rd(hw, ENETC_PSIMSGRR) & mr_mask) |
+ (enetc_rd(hw, ENETC_PSIIDR) & mr_mask);
+ if (!mr_status)
+ goto out;
+
+ for (i = 0; i < pf->num_vfs; i++) {
+ u32 psimsgrr;
+ u16 msg_code;
- for (i = 0; i < pf->num_vfs; i++) {
- u32 psimsgrr;
- u16 msg_code;
+ if (!(ENETC_PSIMR_BIT(i) & mr_status))
+ continue;
- if (!(ENETC_PSIMSGRR_MR(i) & mr_mask))
- continue;
+ enetc_msg_handle_rxmsg(pf, i, &msg_code);
- enetc_msg_handle_rxmsg(pf, i, &msg_code);
+ /* w1c to clear the corresponding VF MR bit */
+ enetc_wr(hw, ENETC_PSIIDR, ENETC_PSIMR_BIT(i));
- psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
- psimsgrr |= ENETC_PSIMSGRR_MR(i); /* w1c */
- enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
- }
+ psimsgrr = ENETC_SIMSGSR_SET_MC(msg_code);
+ psimsgrr |= ENETC_PSIMR_BIT(i); /* w1c */
+ enetc_wr(hw, ENETC_PSIMSGRR, psimsgrr);
}
+
+out:
+ enetc_msg_enable_mr_int(pf);
}
/* Init */
}
/* enable MR interrupts */
- enetc_msg_enable_mr_int(&si->hw);
+ enetc_msg_enable_mr_int(pf);
return 0;
cancel_work_sync(&pf->msg_task);
/* disable MR interrupts */
- enetc_msg_disable_mr_int(&si->hw);
+ enetc_msg_disable_mr_int(pf);
for (i = 0; i < pf->num_vfs; i++)
enetc_msg_free_mbx(si, i);