i40e: enable user dump of internal hardware state
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Tue, 7 Apr 2015 23:45:37 +0000 (19:45 -0400)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 15 Apr 2015 03:14:58 +0000 (20:14 -0700)
This is a feature to enable better debugging of user reported issues by
allowing a bash script to acquire information about the internal hardware
state. The data output to the kernel log is collected by the script and can
then be sent to Intel. This is a critical debugging feature for helping us
interpret and reproduce complex customer setups.

Change-ID: Ie8b3ab09086d6870a709015f51ada05af10b41bb
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h

index 44dc4b1f418ce139788472ca09ec11266fce4602..ce522d76811d7d70e013e5e49b83e3501a5ce362 100644 (file)
@@ -3505,6 +3505,63 @@ void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status)
        }
 }
 
+/**
+ * i40e_aq_debug_dump
+ * @hw: pointer to the hardware structure
+ * @cluster_id: specific cluster to dump
+ * @table_id: table id within cluster
+ * @start_index: index of line in the block to read
+ * @buff_size: dump buffer size
+ * @buff: dump buffer
+ * @ret_buff_size: actual buffer size returned
+ * @ret_next_table: next block to read
+ * @ret_next_index: next index to read
+ *
+ * Dump internal FW/HW data for debug purposes.
+ *
+ **/
+i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
+                              u8 table_id, u32 start_index, u16 buff_size,
+                              void *buff, u16 *ret_buff_size,
+                              u8 *ret_next_table, u32 *ret_next_index,
+                              struct i40e_asq_cmd_details *cmd_details)
+{
+       struct i40e_aq_desc desc;
+       struct i40e_aqc_debug_dump_internals *cmd =
+               (struct i40e_aqc_debug_dump_internals *)&desc.params.raw;
+       struct i40e_aqc_debug_dump_internals *resp =
+               (struct i40e_aqc_debug_dump_internals *)&desc.params.raw;
+       i40e_status status;
+
+       if (buff_size == 0 || !buff)
+               return I40E_ERR_PARAM;
+
+       i40e_fill_default_direct_cmd_desc(&desc,
+                                         i40e_aqc_opc_debug_dump_internals);
+       /* Indirect Command */
+       desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF);
+       if (buff_size > I40E_AQ_LARGE_BUF)
+               desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
+
+       cmd->cluster_id = cluster_id;
+       cmd->table_id = table_id;
+       cmd->idx = cpu_to_le32(start_index);
+
+       desc.datalen = cpu_to_le16(buff_size);
+
+       status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
+       if (!status) {
+               if (ret_buff_size)
+                       *ret_buff_size = le16_to_cpu(desc.datalen);
+               if (ret_next_table)
+                       *ret_next_table = resp->table_id;
+               if (ret_next_index)
+                       *ret_next_index = le32_to_cpu(resp->idx);
+       }
+
+       return status;
+}
+
 /**
  * i40e_read_bw_from_alt_ram
  * @hw: pointer to the hardware structure
index daa88263af663eb0f88052602b9ec1cc4ce697e4..34170eabca7da939ba1c8b9b5fad14dc2f54370d 100644 (file)
@@ -1388,6 +1388,50 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                                         r_cfg->app[i].selector,
                                         r_cfg->app[i].protocolid);
                        }
+               } else if (strncmp(&cmd_buf[5], "debug fwdata", 12) == 0) {
+                       int cluster_id, table_id;
+                       int index, ret;
+                       u16 buff_len = 4096;
+                       u32 next_index;
+                       u8 next_table;
+                       u8 *buff;
+                       u16 rlen;
+
+                       cnt = sscanf(&cmd_buf[18], "%i %i %i",
+                                    &cluster_id, &table_id, &index);
+                       if (cnt != 3) {
+                               dev_info(&pf->pdev->dev,
+                                        "dump debug fwdata <cluster_id> <table_id> <index>\n");
+                               goto command_write_done;
+                       }
+
+                       dev_info(&pf->pdev->dev,
+                                "AQ debug dump fwdata params %x %x %x %x\n",
+                                cluster_id, table_id, index, buff_len);
+                       buff = kzalloc(buff_len, GFP_KERNEL);
+                       if (!buff)
+                               goto command_write_done;
+
+                       ret = i40e_aq_debug_dump(&pf->hw, cluster_id, table_id,
+                                                index, buff_len, buff, &rlen,
+                                                &next_table, &next_index,
+                                                NULL);
+                       if (ret) {
+                               dev_info(&pf->pdev->dev,
+                                        "debug dump fwdata AQ Failed %d 0x%x\n",
+                                        ret, pf->hw.aq.asq_last_status);
+                               kfree(buff);
+                               buff = NULL;
+                               goto command_write_done;
+                       }
+                       dev_info(&pf->pdev->dev,
+                                "AQ debug dump fwdata rlen=0x%x next_table=0x%x next_index=0x%x\n",
+                                rlen, next_table, next_index);
+                       print_hex_dump(KERN_INFO, "AQ buffer WB: ",
+                                      DUMP_PREFIX_OFFSET, 16, 1,
+                                      buff, rlen, true);
+                       kfree(buff);
+                       buff = NULL;
                } else {
                        dev_info(&pf->pdev->dev,
                                 "dump desc tx <vsi_seid> <ring_id> [<desc_n>], dump desc rx <vsi_seid> <ring_id> [<desc_n>],\n");
@@ -1903,6 +1947,7 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
                dev_info(&pf->pdev->dev, "  dump desc rx <vsi_seid> <ring_id> [<desc_n>]\n");
                dev_info(&pf->pdev->dev, "  dump desc aq\n");
                dev_info(&pf->pdev->dev, "  dump reset stats\n");
+               dev_info(&pf->pdev->dev, "  dump debug fwdata <cluster_id> <table_id> <index>\n");
                dev_info(&pf->pdev->dev, "  msg_enable [level]\n");
                dev_info(&pf->pdev->dev, "  read <reg>\n");
                dev_info(&pf->pdev->dev, "  write <reg> <value>\n");
index fea0d37ecc722af58d052476829c5f8ec53ef916..7b34f1e660eacf99699d411e3e498d6fdf85d37c 100644 (file)
@@ -303,4 +303,9 @@ i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
                                u16 vsi_seid, u16 queue, bool is_add,
                                struct i40e_control_filter_stats *stats,
                                struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_debug_dump(struct i40e_hw *hw, u8 cluster_id,
+                              u8 table_id, u32 start_index, u16 buff_size,
+                              void *buff, u16 *ret_buff_size,
+                              u8 *ret_next_table, u32 *ret_next_index,
+                              struct i40e_asq_cmd_details *cmd_details);
 #endif /* _I40E_PROTOTYPE_H_ */