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 <[email protected]>
Signed-off-by: Stefan Wegrzyn <[email protected]>
Reviewed-by: Aleksandr Loktionov <[email protected]>
Signed-off-by: Piotr Kwapulinski <[email protected]>
---
 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 f494e90..bccd51e 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);
+                       }
                }
        }
 
@@ -148,6 +231,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] = cpu_to_le32(raw_desc[i]);
                }
+               ixgbe_aci_debug(hw, raw_desc, NULL, 0);
        }
 
        /* Read async Admin Command response */
@@ -156,14 +240,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] = cpu_to_le32(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
@@ -171,12 +262,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;
        }
 
@@ -184,10 +279,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.47.1

Reply via email to