[PATCH net-next 07/15] ixgbe: E610: add ACI dynamic debug

Jacob Keller
2026-05-01T06:38:36Z

From: Piotr Kwapulinski <piotr.kwapulinski@intel.com>

Enable dynamic debug (dyndbg) of Admin Command Interface (ACI) for e610
adapter. Utilizes the standard dynamic debug interface. For example to
enable dyndbg at driver load:

insmod ixgbe.ko dyndbg='+p'

ACI debug output for e610 adapter is immediately printed into a kernel
log (dmesg). Example output:

ixgbe 0000:01:00.0 eth0: CQ CMD: opcode 0x0701, flags 0x3003, datalen 0x0060, retval 0x0000
ixgbe 0000:01:00.0 eth0: cookie (h,l) 0x00000000 0x00000000
ixgbe 0000:01:00.0 eth0: param (0,1) 0x8194E044 0x00600000
ixgbe 0000:01:00.0 eth0: addr (h,l) 0x00000000 0x00000000
ixgbe 0000:01:00.0 eth0: Buffer:
ixgbe 0000:01:00.0 eth0: 00000000: 01 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00
ixgbe 0000:01:00.0 eth0: 00000010: 1d 00 00 00 0b d5 1e 15 5e 4b 90 63 aa 0b 21 31
ixgbe 0000:01:00.0 eth0: 00000020: 69 eb cd ab dc f8 8a fd f4 53 e2 dc 54 e0 81 fa
ixgbe 0000:01:00.0 eth0: 00000030: 12 dc 41 82 01 00 00 00 24 20 08 26 53 08 00 00
ixgbe 0000:01:00.0 eth0: 00000040: 08 00 14 00 00 00 00 00 00 00 00 00 00 00 00 00
ixgbe 0000:01:00.0 eth0: 00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ixgbe 0000:01:00.0 eth0: CQ CMD: opcode 0x0009, flags 0x2003, datalen 0x0000, retval 0x0000
ixgbe 0000:01:00.0 eth0: cookie (h,l) 0x00000000 0x00000000
ixgbe 0000:01:00.0 eth0: param (0,1) 0x00000001 0x00000000
ixgbe 0000:01:00.0 eth0: addr (h,l) 0x00000000 0x00000000

Co-developed-by: Stefan Wegrzyn <stefan.wegrzyn@intel.com>
Signed-off-by: Stefan Wegrzyn <stefan.wegrzyn@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Piotr Kwapulinski <piotr.kwapulinski@intel.com>
Tested-by: Rinitha S <sx.rinitha@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 112 ++++++++++++++++++++++++--
1 file changed, 105 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
index 665a9813e251..b686636beb93 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
@@ -9,6 +9,78 @@
#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"

+#define IXGBE_ACI_DEBUG_ROW_SIZE 16
+#define IXGBE_ACI_DEBUG_GROUP_SIZE 1
+#define IXGBE_NETDEV_PREFIX_BUF_SIZE 64
+
+/**
+ * ixgbe_hex_debug_dump - dump a blob of data in "hex ASCII" format
+ * @hw: hardware structure address
+ * @buf: data blob to dump
+ * @buf_size: number of bytes in the @buf
+ *
+ * Dump a blob of data into a kernel log. The blob is printed in lines
+ * consisting of 16 or 32 bytes decorated with PCI device string. Each byte is
+ * printed in a "hex ASCII" format.
+ * Example output:
+ * ixgbe 0000:01:00.1 eth14: 00000000: 01 00 17 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * ixgbe 0000:01:00.1 eth14: 00000010: 1d 00 00 00 0b d5 1e 15 5e 4b 90 63 aa 0b 21 31
+ * ixgbe 0000:01:00.1 eth14: 00000020: 69 eb cd ab dc f8 8a fd f4 53 e2 dc 54 e0 81 fa
+ */
+static void ixgbe_hex_debug_dump(struct ixgbe_hw *hw, void *buf,
+ size_t buf_size)
+{
+ char netdev_info[IXGBE_NETDEV_PREFIX_BUF_SIZE];
+ struct ixgbe_adapter *adapter = hw->back;
+ struct pci_dev *pdev = adapter->pdev;
+
+ snprintf(netdev_info, IXGBE_NETDEV_PREFIX_BUF_SIZE,
+ "%s %s %s: ", ixgbe_driver_name, pci_name(pdev),
+ netdev_name(adapter->netdev));
+ print_hex_dump_debug(netdev_info, DUMP_PREFIX_OFFSET,
+ IXGBE_ACI_DEBUG_ROW_SIZE,
+ IXGBE_ACI_DEBUG_GROUP_SIZE,
+ buf, buf_size, false);
+}
+
+/**
+ * ixgbe_aci_debug - dump the ACI content
+ * @hw: pointer to the hardware structure
+ * @desc: pointer to control queue descriptor
+ * @buf: pointer to command buffer
+ * @buf_len: max length of buf
+ *
+ * Dump individual ACI commands and its descriptor details.
+ */
+static void ixgbe_aci_debug(struct ixgbe_hw *hw, void *desc, void *buf,
+ u16 buf_len)
+{
+ struct libie_aq_desc *aq_desc = desc;
+ u16 datalen, flags;
+
+ datalen = le16_to_cpu(aq_desc->datalen);
+ flags = le16_to_cpu(aq_desc->flags);
+
+ hw_dbg(hw, "CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
+ le16_to_cpu(aq_desc->opcode), flags, datalen,
+ le16_to_cpu(aq_desc->retval));
+ hw_dbg(hw, "\tcookie (h,l) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->cookie_high),
+ le32_to_cpu(aq_desc->cookie_low));
+ hw_dbg(hw, "\tparam (0,1) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->params.generic.param0),
+ le32_to_cpu(aq_desc->params.generic.param1));
+ hw_dbg(hw, "\taddr (h,l) 0x%08X 0x%08X\n",
+ le32_to_cpu(aq_desc->params.generic.addr_high),
+ le32_to_cpu(aq_desc->params.generic.addr_low));
+
+ if (buf && datalen && (flags & (LIBIE_AQ_FLAG_DD | LIBIE_AQ_FLAG_CMP |
+ LIBIE_AQ_FLAG_RD))) {
+ hw_dbg(hw, "Buffer:\n");
+ ixgbe_hex_debug_dump(hw, buf, min(buf_len, datalen));
+ }
+}
+
/**
* ixgbe_should_retry_aci_send_cmd_execute - decide if ACI command should
* be resent
@@ -69,26 +141,33 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
/* It's necessary to check if mechanism is enabled */
hicr = IXGBE_READ_REG(hw, IXGBE_PF_HICR);

- if (!(hicr & IXGBE_PF_HICR_EN))
+ if (!(hicr & IXGBE_PF_HICR_EN)) {
+ hw_dbg(hw, "CSR mechanism is not enabled\n");
return -EIO;
+ }

if (hicr & IXGBE_PF_HICR_C) {
hw->aci.last_status = LIBIE_AQ_RC_EBUSY;
+ hw_dbg(hw, "CSR mechanism is busy\n");
return -EBUSY;
}

opcode = le16_to_cpu(desc->opcode);

- if (buf_size > IXGBE_ACI_MAX_BUFFER_SIZE)
+ if (buf_size > IXGBE_ACI_MAX_BUFFER_SIZE) {
+ hw_dbg(hw, "buf_size is too big\n");
return -EINVAL;
+ }

if (buf)
desc->flags |= cpu_to_le16(LIBIE_AQ_FLAG_BUF);

if (desc->flags & cpu_to_le16(LIBIE_AQ_FLAG_BUF)) {
if ((buf && !buf_size) ||
- (!buf && buf_size))
+ (!buf && buf_size)) {
+ hw_dbg(hw, "error: invalid argument buf or buf_size\n");
return -EINVAL;
+ }
if (buf && buf_size)
valid_buf = true;
}
@@ -106,8 +185,12 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
if (desc->flags & cpu_to_le16(LIBIE_AQ_FLAG_RD)) {
for (i = 0; i < buf_size / 4; i++)
IXGBE_WRITE_REG(hw, IXGBE_PF_HIBA(i), ((u32 *)buf)[i]);
- if (buf_tail_size)
+ ixgbe_aci_debug(hw, desc, buf, buf_size);
+ if (buf_tail_size) {
IXGBE_WRITE_REG(hw, IXGBE_PF_HIBA(i), buf_tail);
+ ixgbe_aci_debug(hw, desc, &buf_tail,
+ buf_tail_size);
+ }
}
}

@@ -147,6 +230,7 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
raw_desc[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIDA(i));
raw_desc[i] = raw_desc[i];
}
+ ixgbe_aci_debug(hw, raw_desc, NULL, 0);
}

/* Read async Admin Command response */
@@ -155,14 +239,21 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
raw_desc[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIDA_2(i));
raw_desc[i] = raw_desc[i];
}
+ ixgbe_aci_debug(hw, raw_desc, NULL, 0);
}

/* Handle timeout and invalid state of HICR register */
- if (hicr & IXGBE_PF_HICR_C)
+ if (hicr & IXGBE_PF_HICR_C) {
+ hw_dbg(hw, "error: Admin Command 0x%X command timeout\n",
+ le16_to_cpu(desc->opcode));
return -ETIME;
+ }

- if (!(hicr & IXGBE_PF_HICR_SV) && !(hicr & IXGBE_PF_HICR_EV))
+ if (!(hicr & IXGBE_PF_HICR_SV) && !(hicr & IXGBE_PF_HICR_EV)) {
+ hw_dbg(hw, "error: Admin Command 0x%X invalid state of HICR register\n",
+ le16_to_cpu(desc->opcode));
return -EIO;
+ }

/* For every command other than 0x0014 treat opcode mismatch
* as an error. Response to 0x0014 command read from HIDA_2
@@ -170,12 +261,16 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
* different opcode than the command.
*/
if (desc->opcode != cpu_to_le16(opcode) &&
- opcode != ixgbe_aci_opc_get_fw_event)
+ opcode != ixgbe_aci_opc_get_fw_event) {
+ hw_dbg(hw, "error: Admin Command failed, bad opcode returned\n");
return -EIO;
+ }

if (desc->retval) {
hw->aci.last_status = (enum libie_aq_err)
le16_to_cpu(desc->retval);
+ hw_dbg(hw, "error: Admin Command failed with error %x\n",
+ le16_to_cpu(desc->retval));
return -EIO;
}

@@ -183,10 +278,13 @@ static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
if (valid_buf) {
for (i = 0; i < buf_size / 4; i++)
((u32 *)buf)[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIBA(i));
+ ixgbe_aci_debug(hw, raw_desc, buf, buf_size);
if (buf_tail_size) {
buf_tail = IXGBE_READ_REG(hw, IXGBE_PF_HIBA(i));
memcpy(buf + buf_size - buf_tail_size, &buf_tail,
buf_tail_size);
+ ixgbe_aci_debug(hw, raw_desc, &buf_tail,
+ buf_tail_size);
}
}

--
2.54.0.rc2.531.gaf818d63126a