From: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
To: intel-wired-lan@lists.osuosl.org
Cc: netdev@vger.kernel.org,
Michal Swiatkowski <michal.swiatkowski@linux.intel.com>,
Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Subject: [PATCH iwl-next v2 10/10] ixd: use interrupt for mailbox communication
Date: Fri, 11 Sep 2026 14:49:21 +0200 [thread overview]
Message-ID: <20260911124921.2881348-11-michal.swiatkowski@linux.intel.com> (raw)
In-Reply-To: <20260911124921.2881348-1-michal.swiatkowski@linux.intel.com>
Switch from polling to interrupt for invoking mailbox operations when it
is available.
Add flag to store the information about the mailbox interrupt. If
interrupt is turned off mailbox will be handled by periodic workqueue.
If it is enabled interrupt will take care of it.
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
---
drivers/net/ethernet/intel/ixd/Kconfig | 1 +
drivers/net/ethernet/intel/ixd/ixd.h | 28 ++++
drivers/net/ethernet/intel/ixd/ixd_ctlq.c | 8 +-
drivers/net/ethernet/intel/ixd/ixd_lan_regs.h | 10 ++
drivers/net/ethernet/intel/ixd/ixd_lib.c | 126 ++++++++++++++++++
drivers/net/ethernet/intel/ixd/ixd_main.c | 2 +
6 files changed, 173 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixd/Kconfig b/drivers/net/ethernet/intel/ixd/Kconfig
index 0a48b3bb7bc2..69c37c2cdb67 100644
--- a/drivers/net/ethernet/intel/ixd/Kconfig
+++ b/drivers/net/ethernet/intel/ixd/Kconfig
@@ -6,6 +6,7 @@ config IXD
depends on PCI_MSI
select LIBIE_CP
select LIBIE_PCI
+ select LIBIE_IRQ
select NET_DEVLINK
help
This driver supports Intel(R) Control Plane PCI Function
diff --git a/drivers/net/ethernet/intel/ixd/ixd.h b/drivers/net/ethernet/intel/ixd/ixd.h
index 4a1590f937b5..ed5ffe04f48d 100644
--- a/drivers/net/ethernet/intel/ixd/ixd.h
+++ b/drivers/net/ethernet/intel/ixd/ixd.h
@@ -5,9 +5,20 @@
#define _IXD_H_
#include <linux/net/intel/libie/controlq.h>
+#include <linux/net/intel/libie/irq.h>
#define IXD_INIT_TASK_DELAY_JIFFIES msecs_to_jiffies(500)
+/**
+ * enum ixd_flags - Whole device flags
+ * @IXD_MB_INTR_MODE: Mailbox in interrupt mode
+ * @IXD_FLAGS_NBITS: Must be last
+ */
+enum ixd_flags {
+ IXD_MB_INTR_MODE,
+ IXD_FLAGS_NBITS,
+};
+
/**
* struct ixd_adapter - Data structure representing a CPF
* @cp_ctx: Control plane communication context
@@ -24,6 +35,11 @@
* @vc_ver.major: Negotiated major virtchnl version
* @vc_ver.minor: Negotiated minor virtchnl version
* @caps: Negotiated virtchnl capabilities
+ * @mb_irq: index and virq to track mailbox
+ * @irq: libie irq for interrupts management
+ * @mb_dyn_ctl: mailbox dynamic control register address
+ * @oicr_ena: direct OICR enable register address
+ * @flags: look at enum ixd_flags for more details
*/
struct ixd_adapter {
struct libie_ctlq_ctx cp_ctx;
@@ -42,6 +58,11 @@ struct ixd_adapter {
u32 minor;
} vc_ver;
struct virtchnl2_get_capabilities caps;
+ struct msi_map mb_irq;
+ struct libie_irq irq;
+ void __iomem *mb_dyn_ctl;
+ void __iomem *oicr_ena;
+ DECLARE_BITMAP(flags, IXD_FLAGS_NBITS);
};
/**
@@ -55,6 +76,11 @@ static inline struct device *ixd_to_dev(struct ixd_adapter *adapter)
return &adapter->cp_ctx.mmio_info.pdev->dev;
}
+static inline struct pci_dev *ixd_to_pdev(struct ixd_adapter *adapter)
+{
+ return adapter->cp_ctx.mmio_info.pdev;
+}
+
void ixd_ctlq_reg_init(struct ixd_adapter *adapter,
struct libie_ctlq_reg *ctlq_reg_tx,
struct libie_ctlq_reg *ctlq_reg_rx);
@@ -66,5 +92,7 @@ void ixd_deinit_dflt_mbx(struct ixd_adapter *adapter);
int ixd_iomap_running_regions(struct ixd_adapter *adapter);
bool ixd_iomap_is_not_start_region(struct libie_mmio_info *info,
struct libie_pci_mmio_region *reg);
+void ixd_deinit_interrupts(struct ixd_adapter *adapter);
+void ixd_mailbox_irq_enable(struct ixd_adapter *adapter);
#endif /* _IXD_H_ */
diff --git a/drivers/net/ethernet/intel/ixd/ixd_ctlq.c b/drivers/net/ethernet/intel/ixd/ixd_ctlq.c
index 8712e10c8c50..43daef30689a 100644
--- a/drivers/net/ethernet/intel/ixd/ixd_ctlq.c
+++ b/drivers/net/ethernet/intel/ixd/ixd_ctlq.c
@@ -134,8 +134,12 @@ void ixd_ctlq_rx_task(struct work_struct *work)
adapter = container_of(work, struct ixd_adapter, mbx_task.work);
- queue_delayed_work(system_dfl_wq, &adapter->mbx_task,
- IXD_CTLQ_RX_TASK_DELAY_JIFFIES);
+ if (test_bit(IXD_MB_INTR_MODE, adapter->flags))
+ /* Just re-enable irq in HW. */
+ ixd_mailbox_irq_enable(adapter);
+ else
+ queue_delayed_work(system_dfl_wq, &adapter->mbx_task,
+ IXD_CTLQ_RX_TASK_DELAY_JIFFIES);
ixd_ctlq_recv_mb_msg(adapter);
}
diff --git a/drivers/net/ethernet/intel/ixd/ixd_lan_regs.h b/drivers/net/ethernet/intel/ixd/ixd_lan_regs.h
index 58e58c75981b..b924ada5f831 100644
--- a/drivers/net/ethernet/intel/ixd/ixd_lan_regs.h
+++ b/drivers/net/ethernet/intel/ixd/ixd_lan_regs.h
@@ -31,6 +31,16 @@
#define PF_FW_ATQH (PF_FW_MBX + 0x20)
#define PF_FW_ATQT (PF_FW_MBX + 0x24)
+/* Interrupts */
+#define PF_GLINT_DYN_CTL_INTENA_S 0
+#define PF_GLINT_DYN_CTL_INTENA_M BIT(PF_GLINT_DYN_CTL_INTENA_S)
+#define PF_GLINT_DYN_CTL_ITR_INDX_S 3
+#define PF_GLINT_DYN_CTL_ITR_INDX_M GENMASK(4, 3)
+
+/* Generic registers */
+#define PF_INT_DIR_OICR_ENA 0x08406000
+#define PF_INT_DIR_OICR_ENA_M GENMASK(31, 0)
+
/* Reset registers */
#define PFGEN_RTRIG_REG_LEN 2048
#define PFGEN_RTRIG 0x08407000 /* Device resets */
diff --git a/drivers/net/ethernet/intel/ixd/ixd_lib.c b/drivers/net/ethernet/intel/ixd/ixd_lib.c
index 8311f7590666..e13614603a9e 100644
--- a/drivers/net/ethernet/intel/ixd/ixd_lib.c
+++ b/drivers/net/ethernet/intel/ixd/ixd_lib.c
@@ -4,6 +4,7 @@
#include "ixd.h"
#include "ixd_ctlq.h"
#include "ixd_devlink.h"
+#include "ixd_lan_regs.h"
#include "ixd_virtchnl.h"
#define IXD_DFLT_MBX_Q_LEN 64
@@ -57,6 +58,125 @@ static void ixd_adapter_fill_dflt_ctlqs(struct ixd_adapter *adapter)
LIBIE_CTLQ_MBX_ID);
}
+static irqreturn_t ixd_mailbox_irq_handler(int __always_unused irq, void *data)
+{
+ struct ixd_adapter *adapter = (struct ixd_adapter *)data;
+
+ queue_delayed_work(system_dfl_wq, &adapter->mbx_task, 0);
+
+ return IRQ_HANDLED;
+}
+
+void ixd_mailbox_irq_enable(struct ixd_adapter *adapter)
+{
+ writel(PF_GLINT_DYN_CTL_INTENA_M | PF_GLINT_DYN_CTL_ITR_INDX_M,
+ adapter->mb_dyn_ctl);
+ writel(PF_INT_DIR_OICR_ENA_M, adapter->oicr_ena);
+}
+
+static void ixd_mailbox_irq_disable(struct ixd_adapter *adapter)
+{
+ /* Clear INTENA, keep the ITR index pointing to the no update one. */
+ writel(PF_GLINT_DYN_CTL_ITR_INDX_M, adapter->mb_dyn_ctl);
+ writel(0, adapter->oicr_ena);
+}
+
+static int ixd_mailbox_irq_regs_init(struct ixd_adapter *adapter)
+{
+ struct libie_mmio_info *mmio = &adapter->cp_ctx.mmio_info;
+ u32 dyn_ctl = le32_to_cpu(adapter->caps.mailbox_dyn_ctl);
+
+ adapter->mb_dyn_ctl = libie_pci_get_mmio_addr(mmio, dyn_ctl);
+ adapter->oicr_ena = libie_pci_get_mmio_addr(mmio, PF_INT_DIR_OICR_ENA);
+
+ if (!adapter->mb_dyn_ctl || !adapter->oicr_ena)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void ixd_mailbox_irq_deinit(struct ixd_adapter *adapter)
+{
+ if (!test_and_clear_bit(IXD_MB_INTR_MODE, adapter->flags))
+ return;
+
+ ixd_mailbox_irq_disable(adapter);
+
+ /* The mailbox task re-arms the interrupt, make sure it isn't running
+ * anymore before the irq line is freed.
+ */
+ cancel_delayed_work_sync(&adapter->mbx_task);
+
+ kfree(free_irq(adapter->mb_irq.virq, adapter));
+ libie_irq_free(&adapter->irq, adapter->mb_irq);
+}
+
+static int ixd_mailbox_irq_init(struct ixd_adapter *adapter)
+{
+ struct msi_map *irq = &adapter->mb_irq;
+ char *name;
+ int err;
+
+ *irq = libie_irq_alloc(&adapter->irq, LIBIE_IRQ_STATIC);
+ if (irq->index < 0)
+ return irq->index;
+
+ name = kasprintf(GFP_KERNEL, "%s-%s-%d",
+ dev_driver_string(ixd_to_dev(adapter)), "Mailbox", 0);
+ if (!name) {
+ libie_irq_free(&adapter->irq, adapter->mb_irq);
+
+ return -ENOMEM;
+ }
+
+ err = request_irq(irq->virq, ixd_mailbox_irq_handler, 0, name, adapter);
+ if (err) {
+ kfree(name);
+ libie_irq_free(&adapter->irq, adapter->mb_irq);
+ dev_err(ixd_to_dev(adapter), "IRQ request for mailbox failed, error: %d\n",
+ err);
+
+ return err;
+ }
+
+ set_bit(IXD_MB_INTR_MODE, adapter->flags);
+
+ return 0;
+}
+
+void ixd_deinit_interrupts(struct ixd_adapter *adapter)
+{
+ ixd_mailbox_irq_deinit(adapter);
+ libie_irq_deinit(&adapter->irq);
+}
+
+static int ixd_init_interrupts(struct ixd_adapter *adapter)
+{
+ struct libie_irq *irq = &adapter->irq;
+ int err;
+
+ err = libie_irq_init(irq, ixd_to_pdev(adapter), 1, 1);
+ if (err)
+ return err;
+
+ err = ixd_mailbox_irq_regs_init(adapter);
+ if (err)
+ goto free_irq;
+
+ err = ixd_mailbox_irq_init(adapter);
+ if (err)
+ goto free_irq;
+
+ ixd_mailbox_irq_enable(adapter);
+
+ return 0;
+
+free_irq:
+ libie_irq_deinit(irq);
+
+ return err;
+}
+
/**
* ixd_deinit_dflt_mbx - Deinitialize default mailbox
* @adapter: adapter info struct
@@ -154,6 +274,12 @@ void ixd_init_task(struct work_struct *work)
adapter->init_task.vc_retries = 0;
adapter->init_task.success = true;
ixd_devlink_register(adapter);
+
+ err = ixd_init_interrupts(adapter);
+ if (err)
+ dev_err(ixd_to_dev(adapter),
+ "Failed to initialize interrupts: %d\n",
+ err);
return;
}
diff --git a/drivers/net/ethernet/intel/ixd/ixd_main.c b/drivers/net/ethernet/intel/ixd/ixd_main.c
index 488a919f3b1b..e83550da3e9a 100644
--- a/drivers/net/ethernet/intel/ixd/ixd_main.c
+++ b/drivers/net/ethernet/intel/ixd/ixd_main.c
@@ -9,6 +9,7 @@
MODULE_DESCRIPTION("Intel(R) Control Plane Function Device Driver");
MODULE_IMPORT_NS("LIBIE_CP");
MODULE_IMPORT_NS("LIBIE_PCI");
+MODULE_IMPORT_NS("LIBIE_IRQ");
MODULE_LICENSE("GPL");
/**
@@ -25,6 +26,7 @@ static void ixd_remove(struct pci_dev *pdev)
ixd_devlink_unregister(adapter);
/* Leave the device clean on exit */
+ ixd_deinit_interrupts(adapter);
if (adapter->xnm)
libie_ctlq_xn_shutdown(adapter->xnm);
ixd_trigger_reset(adapter);
--
2.49.0
prev parent reply other threads:[~2026-09-11 13:30 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 12:49 [PATCH iwl-next v2 00/10] Interrupts helper in libie Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 01/10] idpf: store HW vectors information Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 02/10] idpf: fill q_vector interrupt registers one by one Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 03/10] idpf: get rid of msix_entries array Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 04/10] idpf: drop v_idx from q_vector structure Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 05/10] libie, idpf: move irq code to libie Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 06/10] libie, idpf: move hardware irq info struct " Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 07/10] libie, idpf: move parsing alloc vectors command " Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 08/10] ice: use libie_irq for interrupts managing Michal Swiatkowski
2026-09-11 12:49 ` [PATCH iwl-next v2 09/10] ixd: support for getting lan memory regions Michal Swiatkowski
2026-09-11 12:49 ` Michal Swiatkowski [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260911124921.2881348-11-michal.swiatkowski@linux.intel.com \
--to=michal.swiatkowski@linux.intel.com \
--cc=aleksandr.loktionov@intel.com \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox