be2net: add register dump feature for Lancer
authorPadmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Wed, 16 Nov 2011 02:02:43 +0000 (02:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Nov 2011 23:07:09 +0000 (18:07 -0500)
Implement register dump using ethtool for Lancer.

Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c

index d35a214a276680a7d190bc3359cd022f54720d2c..1522065926b8a5f1314155f7a42f2f3c48b30ae4 100644 (file)
@@ -1828,6 +1828,53 @@ err_unlock:
        return status;
 }
 
+int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
+               u32 data_size, u32 data_offset, const char *obj_name,
+               u32 *data_read, u32 *eof, u8 *addn_status)
+{
+       struct be_mcc_wrb *wrb;
+       struct lancer_cmd_req_read_object *req;
+       struct lancer_cmd_resp_read_object *resp;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err_unlock;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                       OPCODE_COMMON_READ_OBJECT,
+                       sizeof(struct lancer_cmd_req_read_object), wrb,
+                       NULL);
+
+       req->desired_read_len = cpu_to_le32(data_size);
+       req->read_offset = cpu_to_le32(data_offset);
+       strcpy(req->object_name, obj_name);
+       req->descriptor_count = cpu_to_le32(1);
+       req->buf_len = cpu_to_le32(data_size);
+       req->addr_low = cpu_to_le32((cmd->dma & 0xFFFFFFFF));
+       req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma));
+
+       status = be_mcc_notify_wait(adapter);
+
+       resp = embedded_payload(wrb);
+       if (!status) {
+               *data_read = le32_to_cpu(resp->actual_read_len);
+               *eof = le32_to_cpu(resp->eof);
+       } else {
+               *addn_status = resp->additional_status;
+       }
+
+err_unlock:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
                        u32 flash_type, u32 flash_opcode, u32 buf_size)
 {
index 08180396891cab80d0ddc7917a7c5f6cb1a78312..2d3fe6a8b04f442e92af86b214344ec21db5d7c3 100644 (file)
@@ -189,6 +189,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_PHY_DETAILS                  102
 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP          103
 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES   121
+#define OPCODE_COMMON_READ_OBJECT                      171
 #define OPCODE_COMMON_WRITE_OBJECT                     172
 
 #define OPCODE_ETH_RSS_CONFIG                          1
@@ -1161,6 +1162,36 @@ struct lancer_cmd_resp_write_object {
        u32 actual_write_len;
 };
 
+/************************ Lancer Read FW info **************/
+#define LANCER_READ_FILE_CHUNK                 (32*1024)
+#define LANCER_READ_FILE_EOF_MASK              0x80000000
+
+#define LANCER_FW_DUMP_FILE                    "/dbg/dump.bin"
+
+struct lancer_cmd_req_read_object {
+       struct be_cmd_req_hdr hdr;
+       u32 desired_read_len;
+       u32 read_offset;
+       u8 object_name[104];
+       u32 descriptor_count;
+       u32 buf_len;
+       u32 addr_low;
+       u32 addr_high;
+};
+
+struct lancer_cmd_resp_read_object {
+       u8 opcode;
+       u8 subsystem;
+       u8 rsvd1[2];
+       u8 status;
+       u8 additional_status;
+       u8 rsvd2[2];
+       u32 resp_len;
+       u32 actual_resp_len;
+       u32 actual_read_len;
+       u32 eof;
+};
+
 /************************ WOL *******************************/
 struct be_cmd_req_acpi_wol_magic_config{
        struct be_cmd_req_hdr hdr;
@@ -1480,6 +1511,9 @@ extern int lancer_cmd_write_object(struct be_adapter *adapter,
                                u32 data_size, u32 data_offset,
                                const char *obj_name,
                                u32 *data_written, u8 *addn_status);
+int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
+               u32 data_size, u32 data_offset, const char *obj_name,
+               u32 *data_read, u32 *eof, u8 *addn_status);
 int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
                                int offset);
 extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
index 1ad7a28fae6ad2935198bbb19593238c82e2babe..1e7252e4cdec83e6089567d271db92a10f50adc5 100644 (file)
@@ -143,15 +143,77 @@ static void be_get_drvinfo(struct net_device *netdev,
        drvinfo->eedump_len = 0;
 }
 
+static u32
+lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name)
+{
+       u32 data_read = 0, eof;
+       u8 addn_status;
+       struct be_dma_mem data_len_cmd;
+       int status;
+
+       memset(&data_len_cmd, 0, sizeof(data_len_cmd));
+       /* data_offset and data_size should be 0 to get reg len */
+       status = lancer_cmd_read_object(adapter, &data_len_cmd, 0, 0,
+                               file_name, &data_read, &eof, &addn_status);
+
+       return data_read;
+}
+
+static int
+lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,
+               u32 buf_len, void *buf)
+{
+       struct be_dma_mem read_cmd;
+       u32 read_len = 0, total_read_len = 0, chunk_size;
+       u32 eof = 0;
+       u8 addn_status;
+       int status = 0;
+
+       read_cmd.size = LANCER_READ_FILE_CHUNK;
+       read_cmd.va = pci_alloc_consistent(adapter->pdev, read_cmd.size,
+                       &read_cmd.dma);
+
+       if (!read_cmd.va) {
+               dev_err(&adapter->pdev->dev,
+                               "Memory allocation failure while reading dump\n");
+               return -ENOMEM;
+       }
+
+       while ((total_read_len < buf_len) && !eof) {
+               chunk_size = min_t(u32, (buf_len - total_read_len),
+                               LANCER_READ_FILE_CHUNK);
+               chunk_size = ALIGN(chunk_size, 4);
+               status = lancer_cmd_read_object(adapter, &read_cmd, chunk_size,
+                               total_read_len, file_name, &read_len,
+                               &eof, &addn_status);
+               if (!status) {
+                       memcpy(buf + total_read_len, read_cmd.va, read_len);
+                       total_read_len += read_len;
+                       eof &= LANCER_READ_FILE_EOF_MASK;
+               } else {
+                       status = -EIO;
+                       break;
+               }
+       }
+       pci_free_consistent(adapter->pdev, read_cmd.size, read_cmd.va,
+                       read_cmd.dma);
+
+       return status;
+}
+
 static int
 be_get_reg_len(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
        u32 log_size = 0;
 
-       if (be_physfn(adapter))
-               be_cmd_get_reg_len(adapter, &log_size);
-
+       if (be_physfn(adapter)) {
+               if (lancer_chip(adapter))
+                       log_size = lancer_cmd_get_file_len(adapter,
+                                       LANCER_FW_DUMP_FILE);
+               else
+                       be_cmd_get_reg_len(adapter, &log_size);
+       }
        return log_size;
 }
 
@@ -162,7 +224,11 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
 
        if (be_physfn(adapter)) {
                memset(buf, 0, regs->len);
-               be_cmd_get_regs(adapter, regs->len, buf);
+               if (lancer_chip(adapter))
+                       lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE,
+                                       regs->len, buf);
+               else
+                       be_cmd_get_regs(adapter, regs->len, buf);
        }
 }