[PATCH v1 4/5] net/ixgbe: add ACI debug printouts

Anatoly Burakov anatoly.burakov at intel.com
Mon Jun 9 12:25:37 CEST 2025


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

Add more verbose printouts for ACI when debugging is enabled.

Signed-off-by: Piotr Kwapulinski <piotr.kwapulinski at intel.com>
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
 drivers/net/intel/ixgbe/base/ixgbe_e610.c     | 110 ++++++++++++++++++
 drivers/net/intel/ixgbe/base/ixgbe_e610.h     |   2 +
 drivers/net/intel/ixgbe/base/ixgbe_osdep.h    |   1 +
 .../net/intel/ixgbe/base/ixgbe_type_e610.h    |   1 +
 4 files changed, 114 insertions(+)

diff --git a/drivers/net/intel/ixgbe/base/ixgbe_e610.c b/drivers/net/intel/ixgbe/base/ixgbe_e610.c
index cf45db3bc4..06a69d1d62 100644
--- a/drivers/net/intel/ixgbe/base/ixgbe_e610.c
+++ b/drivers/net/intel/ixgbe/base/ixgbe_e610.c
@@ -31,6 +31,99 @@ void ixgbe_shutdown_aci(struct ixgbe_hw *hw)
 	ixgbe_destroy_lock(&hw->aci.lock);
 }
 
+/**
+ * ixgbe_aci_debug_array - dump a buffer of data row by row
+ * @row_size: size in bytes of data dumped in a single row
+ * @buf: data to be dumped into the debug log
+ * @buf_size: size of buffer
+ *
+ * Debug function for dumping a binary blob of data row by row.
+ */
+STATIC void ixgbe_aci_debug_array(struct ixgbe_hw *hw, u16 row_size, u8 *buf,
+				  u16 buf_size)
+{
+	char debug_portion[IXGBE_ACI_MAX_DEBUG_STRING_LENGTH] = {'\0'};
+	char debug_string[IXGBE_ACI_MAX_DEBUG_STRING_LENGTH] = {'\0'};
+	u16 i = 0, j = 0;
+	s16 remaining_space = IXGBE_ACI_MAX_DEBUG_STRING_LENGTH - 1;
+	s16 nbytes = 0;
+	if (!hw)
+		return;
+	if (buf && buf_size && row_size) {
+		if (buf_size >= row_size) {
+			for (i = 0; i < (buf_size - row_size); i += row_size) {
+				nbytes = snprintf(debug_string, sizeof(debug_string), "0x%04X : ", i);
+				remaining_space = IXGBE_ACI_MAX_DEBUG_STRING_LENGTH - nbytes - 1;
+				for (j = 0; j < row_size; j++) {
+					nbytes = snprintf(debug_portion, sizeof(debug_portion), "0x%02X ", buf[i + j]);
+					strncat(debug_string, debug_portion, remaining_space);
+					remaining_space -= nbytes;
+					if (remaining_space <= 0) break;
+				}
+				strncat(debug_string, "\n", remaining_space);
+				DEBUGOUT1("%s", debug_string);
+				memset(debug_string, 0, IXGBE_ACI_MAX_DEBUG_STRING_LENGTH);
+			}
+		}
+		if (i < buf_size) {
+			nbytes = snprintf(debug_string, sizeof(debug_string), "0x%04X : ", i);
+			remaining_space = IXGBE_ACI_MAX_DEBUG_STRING_LENGTH - nbytes - 1;
+			for (j = 0; j < (buf_size - i); j++) {
+				nbytes = snprintf(debug_portion, sizeof(debug_portion), "0x%02X ", buf[i + j]);
+				strncat(debug_string, debug_portion, remaining_space);
+				remaining_space -= nbytes;
+				if (remaining_space <= 0) break;
+			}
+			strncat(debug_string, "\n", remaining_space);
+			DEBUGOUT1("%s", debug_string);
+		}
+	}
+}
+
+/**
+ * ixgbe_aci_debug - dump the ACI data with the descriptor contents.
+ * @hw: pointer to the hardware structure
+ * @desc: pointer to control queue descriptor
+ * @buf: pointer to command buffer
+ * @buf_len: max length of buf
+ *
+ * Debug function for dumping logs about ACI command with descriptor contents.
+ */
+void ixgbe_aci_debug(struct ixgbe_hw *hw, void *desc, void *buf, u16 buf_len)
+{
+	struct ixgbe_aci_desc *aci_desc = (struct ixgbe_aci_desc *)desc;
+	u16 datalen, flags;
+
+	if (!hw || !desc)
+		return;
+
+	datalen = IXGBE_LE16_TO_CPU(aci_desc->datalen);
+	flags = IXGBE_LE16_TO_CPU(aci_desc->flags);
+
+	DEBUGOUT4("CQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n",
+		  IXGBE_LE16_TO_CPU(aci_desc->opcode), flags, datalen,
+		  IXGBE_LE16_TO_CPU(aci_desc->retval));
+	DEBUGOUT2("\tcookie (h,l) 0x%08X 0x%08X\n",
+		  IXGBE_LE32_TO_CPU(aci_desc->cookie_high),
+		  IXGBE_LE32_TO_CPU(aci_desc->cookie_low));
+	DEBUGOUT2("\tparam (0,1)  0x%08X 0x%08X\n",
+		  IXGBE_LE32_TO_CPU(aci_desc->params.generic.param0),
+		  IXGBE_LE32_TO_CPU(aci_desc->params.generic.param1));
+	DEBUGOUT2("\taddr (h,l)   0x%08X 0x%08X\n",
+		  IXGBE_LE32_TO_CPU(aci_desc->params.generic.addr_high),
+		  IXGBE_LE32_TO_CPU(aci_desc->params.generic.addr_low));
+
+	/* Dump buffer if 1) one exists and 2) is either a response indicated
+	 * by the DD and/or CMP flag set or a command with the RD flag set.
+	 */
+	if (buf && aci_desc->datalen != 0 &&
+	    (flags & (IXGBE_ACI_FLAG_DD | IXGBE_ACI_FLAG_CMP) ||
+	     flags & IXGBE_ACI_FLAG_RD)) {
+		DEBUGOUT("Buffer:\n");
+		ixgbe_aci_debug_array(hw, 16, (u8 *)buf, min(buf_len, datalen));
+	}
+}
+
 /**
  * ixgbe_should_retry_aci_send_cmd_execute - decide if ACI command should
  * be resent
@@ -94,10 +187,12 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 		/* It's necessary to check if mechanism is enabled */
 		hicr = IXGBE_READ_REG(hw, PF_HICR);
 		if (!(hicr & PF_HICR_EN)) {
+			DEBUGOUT("CSR mechanism is not enabled\n");
 			status = IXGBE_ERR_ACI_DISABLED;
 			break;
 		}
 		if (hicr & PF_HICR_C) {
+			DEBUGOUT("CSR mechanism is busy\n");
 			hw->aci.last_status = IXGBE_ACI_RC_EBUSY;
 			status = IXGBE_ERR_ACI_BUSY;
 			break;
@@ -105,6 +200,7 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 		opcode = desc->opcode;
 
 		if (buf_size > IXGBE_ACI_MAX_BUFFER_SIZE) {
+			DEBUGOUT("buf_size is too big\n");
 			status = IXGBE_ERR_PARAM;
 			break;
 		}
@@ -117,6 +213,7 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 			if ((buf && buf_size == 0) ||
 			    (buf == NULL && buf_size)) {
 				status = IXGBE_ERR_PARAM;
+				DEBUGOUT("Error: Invalid argument buf or buf_size\n");
 				break;
 			}
 			if (buf && buf_size)
@@ -156,6 +253,8 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 			}
 		}
 
+		ixgbe_aci_debug(hw, (void *)desc, tmp_buf, (u16)tmp_buf_size);
+
 		/* Descriptor is written to specific registers */
 		for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++)
 			IXGBE_WRITE_REG(hw, PF_HIDA(i),
@@ -195,6 +294,7 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 				raw_desc[i] = IXGBE_READ_REG(hw, PF_HIDA(i));
 				raw_desc[i] = IXGBE_CPU_TO_LE32(raw_desc[i]);
 			}
+			ixgbe_aci_debug(hw, (void *)raw_desc, NULL, 0);
 		}
 
 		/* Read async Admin Command response */
@@ -203,13 +303,18 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 				raw_desc[i] = IXGBE_READ_REG(hw, PF_HIDA_2(i));
 				raw_desc[i] = IXGBE_CPU_TO_LE32(raw_desc[i]);
 			}
+			ixgbe_aci_debug(hw, (void *)raw_desc, NULL, 0);
 		}
 
 		/* Handle timeout and invalid state of HICR register */
 		if (hicr & PF_HICR_C) {
+			DEBUGOUT1("Error: Admin Command 0x%X command timeout\n",
+				  desc->opcode);
 			status = IXGBE_ERR_ACI_TIMEOUT;
 			break;
 		} else if (!(hicr & PF_HICR_SV) && !(hicr & PF_HICR_EV)) {
+			DEBUGOUT1("Error: Admin Command 0x%X invalid state of HICR register\n",
+				  desc->opcode);
 			status = IXGBE_ERR_ACI_ERROR;
 			break;
 		}
@@ -221,11 +326,14 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 		 */
 		if (desc->opcode != opcode &&
 		    opcode != IXGBE_CPU_TO_LE16(ixgbe_aci_opc_get_fw_event)) {
+			DEBUGOUT("Error: Admin Command failed because of bad opcode was returned\n");
 			status = IXGBE_ERR_ACI_ERROR;
 			break;
 		}
 
 		if (desc->retval != IXGBE_ACI_RC_OK) {
+			DEBUGOUT1("Error: Admin Command failed with error %x\n",
+				  desc->retval);
 			hw->aci.last_status = (enum ixgbe_aci_err)desc->retval;
 			status = IXGBE_ERR_ACI_ERROR;
 			break;
@@ -239,6 +347,8 @@ ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 				tmp_buf[i] = IXGBE_CPU_TO_LE32(tmp_buf[i]);
 			}
 			memcpy(buf, tmp_buf, buf_size);
+			ixgbe_aci_debug(hw, (void *)raw_desc, tmp_buf,
+					(u16)tmp_buf_size);
 		}
 	} while (0);
 
diff --git a/drivers/net/intel/ixgbe/base/ixgbe_e610.h b/drivers/net/intel/ixgbe/base/ixgbe_e610.h
index f60268cf91..e950f89e80 100644
--- a/drivers/net/intel/ixgbe/base/ixgbe_e610.h
+++ b/drivers/net/intel/ixgbe/base/ixgbe_e610.h
@@ -10,6 +10,8 @@
 void ixgbe_init_aci(struct ixgbe_hw *hw);
 void ixgbe_shutdown_aci(struct ixgbe_hw *hw);
 
+void ixgbe_aci_debug(struct ixgbe_hw *hw, void *desc, void *buf, u16 buf_len);
+
 s32 ixgbe_aci_send_cmd(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
 		       void *buf, u16 buf_size);
 bool ixgbe_aci_check_event_pending(struct ixgbe_hw *hw);
diff --git a/drivers/net/intel/ixgbe/base/ixgbe_osdep.h b/drivers/net/intel/ixgbe/base/ixgbe_osdep.h
index 53d0422193..4dfed02137 100644
--- a/drivers/net/intel/ixgbe/base/ixgbe_osdep.h
+++ b/drivers/net/intel/ixgbe/base/ixgbe_osdep.h
@@ -39,6 +39,7 @@
 #define DEBUGOUT1(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
 #define DEBUGOUT2(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
 #define DEBUGOUT3(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
+#define DEBUGOUT4(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
 #define DEBUGOUT6(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
 #define DEBUGOUT7(S, ...)       DEBUGOUT(S, ##__VA_ARGS__)
 
diff --git a/drivers/net/intel/ixgbe/base/ixgbe_type_e610.h b/drivers/net/intel/ixgbe/base/ixgbe_type_e610.h
index e804172252..9348294735 100644
--- a/drivers/net/intel/ixgbe/base/ixgbe_type_e610.h
+++ b/drivers/net/intel/ixgbe/base/ixgbe_type_e610.h
@@ -361,6 +361,7 @@
 #define IXGBE_ACI_DESC_COOKIE_L_DWORD_OFFSET	3
 #define IXGBE_ACI_SEND_DELAY_TIME_MS		10
 #define IXGBE_ACI_SEND_MAX_EXECUTE		3
+#define IXGBE_ACI_MAX_DEBUG_STRING_LENGTH	128
 /* [ms] timeout of waiting for sync response */
 #define IXGBE_ACI_SYNC_RESPONSE_TIMEOUT		100000
 /* [ms] timeout of waiting for async response */
-- 
2.47.1



More information about the dev mailing list