be2net: Support for FAT dump retrieval using ethtool --register-dump option
authorSomnath Kotur <somnath.kotur@emulex.com>
Wed, 16 Mar 2011 21:22:43 +0000 (21:22 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 31 Mar 2011 04:39:19 +0000 (21:39 -0700)
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_ethtool.c
drivers/net/benet/be_hw.h

index 5a4a87e7c5eadb8a83e72289d61e42ea5fdf42c9..2aadf88eaa0acc205d471e31e0fd6266a2f41804 100644 (file)
@@ -1186,6 +1186,113 @@ err:
        return status;
 }
 
+/* Uses synchronous mcc */
+int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fat *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+       req = embedded_payload(wrb);
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+                       OPCODE_COMMON_MANAGE_FAT);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+               OPCODE_COMMON_MANAGE_FAT, sizeof(*req));
+       req->fat_operation = cpu_to_le32(QUERY_FAT);
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_fat *resp = embedded_payload(wrb);
+               if (log_size && resp->log_size)
+                       *log_size = le32_to_cpu(resp->log_size -
+                                       sizeof(u32));
+       }
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
+void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf)
+{
+       struct be_dma_mem get_fat_cmd;
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fat *req;
+       struct be_sge *sge;
+       u32 offset = 0, total_size, buf_size, log_offset = sizeof(u32);
+       int status;
+
+       if (buf_len == 0)
+               return;
+
+       total_size = buf_len;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+       while (total_size) {
+               buf_size = min(total_size, (u32)60*1024);
+               total_size -= buf_size;
+
+               get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + buf_size;
+               get_fat_cmd.va = pci_alloc_consistent(adapter->pdev,
+                                       get_fat_cmd.size,
+                                       &get_fat_cmd.dma);
+               if (!get_fat_cmd.va) {
+                       status = -ENOMEM;
+                       dev_err(&adapter->pdev->dev,
+                                       "Memory allocation failure while retrieving FAT data\n");
+                       goto err;
+               }
+               req = get_fat_cmd.va;
+               sge = nonembedded_sgl(wrb);
+
+               be_wrb_hdr_prepare(wrb, get_fat_cmd.size, false, 1,
+                               OPCODE_COMMON_MANAGE_FAT);
+
+               be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                               OPCODE_COMMON_MANAGE_FAT, get_fat_cmd.size);
+
+               sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.size));
+               sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF);
+               sge->len = cpu_to_le32(get_fat_cmd.size);
+
+               req->fat_operation = cpu_to_le32(RETRIEVE_FAT);
+               req->read_log_offset = cpu_to_le32(log_offset);
+               req->read_log_length = cpu_to_le32(buf_size);
+               req->data_buffer_size = cpu_to_le32(buf_size);
+
+               status = be_mcc_notify_wait(adapter);
+               if (!status) {
+                       struct be_cmd_resp_get_fat *resp = get_fat_cmd.va;
+                       memcpy(buf + offset,
+                               resp->data_buffer,
+                               resp->read_log_length);
+               }
+               pci_free_consistent(adapter->pdev, get_fat_cmd.size,
+                               get_fat_cmd.va,
+                               get_fat_cmd.dma);
+               if (status)
+                       dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n");
+
+               offset += buf_size;
+               log_offset += buf_size;
+       }
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+}
+
 /* Uses Mbox */
 int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
index 4f254cfaabe2c616dc1958650119cce795e57558..3fb6e0a3ad7a594479e5fd74ede1e71ab414d240 100644 (file)
@@ -186,6 +186,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_NTWK_PMAC_ADD                    59
 #define OPCODE_COMMON_NTWK_PMAC_DEL                    60
 #define OPCODE_COMMON_FUNCTION_RESET                   61
+#define OPCODE_COMMON_MANAGE_FAT                       68
 #define OPCODE_COMMON_ENABLE_DISABLE_BEACON            69
 #define OPCODE_COMMON_GET_BEACON_STATE                 70
 #define OPCODE_COMMON_READ_TRANSRECV_DATA              73
@@ -380,6 +381,24 @@ struct be_cmd_resp_cq_create {
        u16 rsvd0;
 } __packed;
 
+struct be_cmd_req_get_fat {
+       struct be_cmd_req_hdr hdr;
+       u32 fat_operation;
+       u32 read_log_offset;
+       u32 read_log_length;
+       u32 data_buffer_size;
+       u32 data_buffer[1];
+} __packed;
+
+struct be_cmd_resp_get_fat {
+       struct be_cmd_resp_hdr hdr;
+       u32 log_size;
+       u32 read_log_length;
+       u32 rsvd[2];
+       u32 data_buffer[1];
+} __packed;
+
+
 /******************** Create MCCQ ***************************/
 /* Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field */
@@ -1148,4 +1167,6 @@ extern void be_detect_dump_ue(struct be_adapter *adapter);
 extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
 extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
 extern int be_cmd_check_native_mode(struct be_adapter *adapter);
+extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
+extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
 
index aac248fbd18b6ebe06c8686e94c2d39670ca94be..575ac659ceb40d7342572dad5e58fdd37fc760a6 100644 (file)
@@ -155,6 +155,25 @@ be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
        drvinfo->eedump_len = 0;
 }
 
+static int
+be_get_reg_len(struct net_device *netdev)
+{
+       struct be_adapter *adapter = netdev_priv(netdev);
+       u32 log_size = 0;
+
+       be_cmd_get_reg_len(adapter, &log_size);
+       return log_size;
+}
+
+static void
+be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
+{
+       struct be_adapter *adapter = netdev_priv(netdev);
+
+       memset(buf, 0, regs->len);
+       be_cmd_get_regs(adapter, regs->len, buf);
+}
+
 static int
 be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
 {
@@ -737,6 +756,8 @@ const struct ethtool_ops be_ethtool_ops = {
        .phys_id = be_phys_id,
        .get_sset_count = be_get_sset_count,
        .get_ethtool_stats = be_get_ethtool_stats,
+       .get_regs_len = be_get_reg_len,
+       .get_regs = be_get_regs,
        .flash_device = be_do_flash,
        .self_test = be_self_test,
 };
index d4344a06090ba42351ec4e73083d125251720759..53d658afea2af48a958c0357f6ad51e0a5c7dbde 100644 (file)
 /********** SRIOV VF PCICFG OFFSET ********/
 #define SRIOV_VF_PCICFG_OFFSET         (4096)
 
+/********** FAT TABLE  ********/
+#define RETRIEVE_FAT   0
+#define QUERY_FAT      1
+
 /* Flashrom related descriptors */
 #define IMAGE_TYPE_FIRMWARE            160
 #define IMAGE_TYPE_BOOTCODE            224