From patchwork Thu Oct 12 08:24:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rahul Lakkireddy X-Patchwork-Id: 824723 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yCP7k1CJVz9t2d for ; Thu, 12 Oct 2017 19:26:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754531AbdJLI0I (ORCPT ); Thu, 12 Oct 2017 04:26:08 -0400 Received: from stargate.chelsio.com ([12.32.117.8]:7060 "EHLO stargate.chelsio.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753384AbdJLI0G (ORCPT ); Thu, 12 Oct 2017 04:26:06 -0400 Received: from localhost (scalar.blr.asicdesigners.com [10.193.185.94]) by stargate.chelsio.com (8.13.8/8.13.8) with ESMTP id v9C8Q2AX022653; Thu, 12 Oct 2017 01:26:03 -0700 From: Rahul Lakkireddy To: netdev@vger.kernel.org Cc: davem@davemloft.net, ganeshgr@chelsio.com, nirranjan@chelsio.com, indranil@chelsio.com, Rahul Lakkireddy Subject: [PATCH net-next 3/8] cxgb4: collect on-chip memory dump Date: Thu, 12 Oct 2017 13:54:40 +0530 Message-Id: X-Mailer: git-send-email 2.5.3 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Collect EDC0 and EDC1 memory dump. Signed-off-by: Rahul Lakkireddy Signed-off-by: Ganesh Goudar --- drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h | 29 +++++ drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h | 8 ++ drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c | 132 +++++++++++++++++++++ drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h | 6 + .../net/ethernet/chelsio/cxgb4/cudbg_lib_common.h | 3 + drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c | 38 +++++- drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h | 1 + 7 files changed, 216 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h b/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h new file mode 100644 index 000000000000..71a426dd22f5 --- /dev/null +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_entity.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 Chelsio Communications. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + */ + +#ifndef __CUDBG_ENTITY_H__ +#define __CUDBG_ENTITY_H__ + +#define EDC0_FLAG 3 +#define EDC1_FLAG 4 + +struct card_mem { + u16 size_edc0; + u16 size_edc1; + u16 mem_flag; +}; +#endif /* __CUDBG_ENTITY_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h b/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h index 73725a8666df..e45690fd0932 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_if.h @@ -20,6 +20,7 @@ /* Error codes */ #define CUDBG_STATUS_NO_MEM -19 +#define CUDBG_STATUS_ENTITY_NOT_FOUND -24 #define CUDBG_SYSTEM_ERROR -29 #define CUDBG_MAJOR_VERSION 1 @@ -27,6 +28,8 @@ enum cudbg_dbg_entity_type { CUDBG_REG_DUMP = 1, + CUDBG_EDC0 = 18, + CUDBG_EDC1 = 19, CUDBG_MAX_ENTITY = 70, }; @@ -35,4 +38,9 @@ struct cudbg_init { void *outbuf; /* Output buffer */ u32 outbuf_size; /* Output buffer size */ }; + +static inline unsigned int mbytes_to_bytes(unsigned int size) +{ + return size * 1024 * 1024; +} #endif /* __CUDBG_IF_H__ */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c index 4605481706ec..b0a747a6fbb2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c @@ -15,10 +15,12 @@ * */ +#include "t4_regs.h" #include "cxgb4.h" #include "cudbg_if.h" #include "cudbg_lib_common.h" #include "cudbg_lib.h" +#include "cudbg_entity.h" static void write_and_release_buff(struct cudbg_buffer *pin_buff, struct cudbg_buffer *dbg_buff) @@ -27,6 +29,16 @@ static void write_and_release_buff(struct cudbg_buffer *pin_buff, put_cudbg_buff(pin_buff, dbg_buff); } +static int is_fw_attached(struct cudbg_init *pdbg_init) +{ + struct adapter *padap = pdbg_init->adap; + + if (!(padap->flags & FW_OK) || padap->use_bd) + return 0; + + return 1; +} + /* This function will add additional padding bytes into debug_buffer to make it * 4 byte aligned. */ @@ -77,3 +89,123 @@ int collect_reg_dump(struct cudbg_init *pdbg_init, write_and_release_buff(&temp_buff, dbg_buff); return rc; } + +static int read_fw_mem(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, u8 mem_type, + unsigned long tot_len, struct cudbg_error *cudbg_err) +{ + unsigned long bytes, bytes_left, bytes_read = 0; + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer temp_buff = { 0 }; + int rc = 0; + + bytes_left = tot_len; + while (bytes_left > 0) { + bytes = min_t(unsigned long, bytes_left, + (unsigned long)CUDBG_CHUNK_SIZE); + rc = get_cudbg_buff(dbg_buff, bytes, &temp_buff); + if (rc) + return rc; + spin_lock(&padap->win0_lock); + rc = t4_memory_rw(padap, MEMWIN_NIC, mem_type, + bytes_read, bytes, + (__be32 *)temp_buff.data, + 1); + spin_unlock(&padap->win0_lock); + if (rc) { + cudbg_err->sys_err = rc; + put_cudbg_buff(&temp_buff, dbg_buff); + return rc; + } + bytes_left -= bytes; + bytes_read += bytes; + write_and_release_buff(&temp_buff, dbg_buff); + } + return rc; +} + +void collect_mem_info(struct cudbg_init *pdbg_init, struct card_mem *mem_info) +{ + struct adapter *padap = pdbg_init->adap; + u32 value; + + value = t4_read_reg(padap, MA_EDRAM0_BAR_A); + value = EDRAM0_SIZE_G(value); + mem_info->size_edc0 = (u16)value; + + value = t4_read_reg(padap, MA_EDRAM1_BAR_A); + value = EDRAM1_SIZE_G(value); + mem_info->size_edc1 = (u16)value; + + value = t4_read_reg(padap, MA_TARGET_MEM_ENABLE_A); + if (value & EDRAM0_ENABLE_F) + mem_info->mem_flag |= (1 << EDC0_FLAG); + if (value & EDRAM1_ENABLE_F) + mem_info->mem_flag |= (1 << EDC1_FLAG); +} + +static void cudbg_t4_fwcache(struct cudbg_init *pdbg_init, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + int rc; + + if (is_fw_attached(pdbg_init)) { + /* Flush uP dcache before reading edcX/mcX */ + rc = t4_fwcache(padap, FW_PARAM_DEV_FWCACHE_FLUSH); + if (rc) + cudbg_err->sys_warn = rc; + } +} + +static int collect_mem_region(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err, + u8 mem_type) +{ + struct card_mem mem_info = {0}; + unsigned long flag, size; + int rc; + + cudbg_t4_fwcache(pdbg_init, cudbg_err); + collect_mem_info(pdbg_init, &mem_info); + switch (mem_type) { + case MEM_EDC0: + flag = (1 << EDC0_FLAG); + size = mbytes_to_bytes(mem_info.size_edc0); + break; + case MEM_EDC1: + flag = (1 << EDC1_FLAG); + size = mbytes_to_bytes(mem_info.size_edc1); + break; + default: + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + goto err; + } + + if (mem_info.mem_flag & flag) { + rc = read_fw_mem(pdbg_init, dbg_buff, mem_type, + size, cudbg_err); + if (rc) + goto err; + } else { + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + goto err; + } +err: + return rc; +} + +int collect_edc0_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + return collect_mem_region(pdbg_init, dbg_buff, cudbg_err, MEM_EDC0); +} + +int collect_edc1_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + return collect_mem_region(pdbg_init, dbg_buff, cudbg_err, MEM_EDC1); +} diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h index c6baeb533c44..04d66807c153 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.h @@ -21,6 +21,12 @@ int collect_reg_dump(struct cudbg_init *pdbg_init, struct cudbg_buffer *dbg_buff, struct cudbg_error *cudbg_err); +int collect_edc0_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err); +int collect_edc1_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err); struct cudbg_entity_hdr *get_entity_hdr(void *outbuf, int i); void align_debug_buffer(struct cudbg_buffer *dbg_buff, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib_common.h b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib_common.h index 851284db0812..a5b92ae8fc85 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib_common.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib_common.h @@ -69,6 +69,9 @@ struct cudbg_error { int app_err; }; +#define CDUMP_MAX_COMP_BUF_SIZE ((64 * 1024) - 1) +#define CUDBG_CHUNK_SIZE ((CDUMP_MAX_COMP_BUF_SIZE / 1024) * 1024) + int get_cudbg_buff(struct cudbg_buffer *pdbg_buff, u32 size, struct cudbg_buffer *pin_buff); void put_cudbg_buff(struct cudbg_buffer *pin_buff, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c index 5c351ee8ab58..cd8599083a69 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.c @@ -15,16 +15,22 @@ * */ +#include "t4_regs.h" #include "cxgb4.h" #include "cxgb4_cudbg.h" +static const struct cudbg_collect_entity collect_mem_dump[] = { + { CUDBG_EDC0, collect_edc0_meminfo }, + { CUDBG_EDC1, collect_edc1_meminfo }, +}; + static const struct cudbg_collect_entity collect_hw_dump[] = { { CUDBG_REG_DUMP, collect_reg_dump }, }; static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity) { - u32 len = 0; + u32 value, len = 0; switch (entity) { case CUDBG_REG_DUMP: @@ -40,6 +46,22 @@ static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity) break; } break; + case CUDBG_EDC0: + value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); + if (value & EDRAM0_ENABLE_F) { + value = t4_read_reg(adap, MA_EDRAM0_BAR_A); + len = EDRAM0_SIZE_G(value); + } + len = mbytes_to_bytes(len); + break; + case CUDBG_EDC1: + value = t4_read_reg(adap, MA_TARGET_MEM_ENABLE_A); + if (value & EDRAM1_ENABLE_F) { + value = t4_read_reg(adap, MA_EDRAM1_BAR_A); + len = EDRAM1_SIZE_G(value); + } + len = mbytes_to_bytes(len); + break; default: break; } @@ -59,6 +81,13 @@ u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag) } } + if (flag & CXGB4_ETH_DUMP_MEM) { + for (i = 0; i < ARRAY_SIZE(collect_mem_dump); i++) { + entity = collect_mem_dump[i].entity; + len += cxgb4_get_entity_length(adap, entity); + } + } + return len; } @@ -152,6 +181,13 @@ int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size, buf, &total_size); + if (flag & CXGB4_ETH_DUMP_MEM) + cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff, + collect_mem_dump, + ARRAY_SIZE(collect_mem_dump), + buf, + &total_size); + cudbg_hdr->data_len = total_size; *buf_size = total_size; return 0; diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h index 3aeb887831c9..79fcea1ad163 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_cudbg.h @@ -33,6 +33,7 @@ struct cudbg_collect_entity { enum CXGB4_ETHTOOL_DUMP_FLAGS { CXGB4_ETH_DUMP_NONE = ETH_FW_DUMP_DISABLE, + CXGB4_ETH_DUMP_MEM = (1 << 0), /* On-Chip Memory Dumps */ CXGB4_ETH_DUMP_HW = (1 << 1), /* various FW and HW dumps */ };