cxgb4_cudbg.c 6.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 *  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".
 *
 */

18
#include "t4_regs.h"
19 20
#include "cxgb4.h"
#include "cxgb4_cudbg.h"
21
#include "cudbg_entity.h"
22

23 24 25 26 27
static const struct cxgb4_collect_entity cxgb4_collect_mem_dump[] = {
	{ CUDBG_EDC0, cudbg_collect_edc0_meminfo },
	{ CUDBG_EDC1, cudbg_collect_edc1_meminfo },
};

R
Rahul Lakkireddy 已提交
28
static const struct cxgb4_collect_entity cxgb4_collect_hw_dump[] = {
29 30
	{ CUDBG_MBOX_LOG, cudbg_collect_mbox_log },
	{ CUDBG_DEV_LOG, cudbg_collect_fw_devlog },
R
Rahul Lakkireddy 已提交
31
	{ CUDBG_REG_DUMP, cudbg_collect_reg_dump },
R
Rahul Lakkireddy 已提交
32
	{ CUDBG_TP_INDIRECT, cudbg_collect_tp_indirect },
R
Rahul Lakkireddy 已提交
33 34 35 36
};

static u32 cxgb4_get_entity_length(struct adapter *adap, u32 entity)
{
R
Rahul Lakkireddy 已提交
37
	u32 value, n = 0, len = 0;
R
Rahul Lakkireddy 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

	switch (entity) {
	case CUDBG_REG_DUMP:
		switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
		case CHELSIO_T4:
			len = T4_REGMAP_SIZE;
			break;
		case CHELSIO_T5:
		case CHELSIO_T6:
			len = T5_REGMAP_SIZE;
			break;
		default:
			break;
		}
		break;
53 54 55
	case CUDBG_DEV_LOG:
		len = adap->params.devlog.size;
		break;
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
	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 = cudbg_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 = cudbg_mbytes_to_bytes(len);
		break;
R
Rahul Lakkireddy 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
	case CUDBG_TP_INDIRECT:
		switch (CHELSIO_CHIP_VERSION(adap->params.chip)) {
		case CHELSIO_T5:
			n = sizeof(t5_tp_pio_array) +
			    sizeof(t5_tp_tm_pio_array) +
			    sizeof(t5_tp_mib_index_array);
			break;
		case CHELSIO_T6:
			n = sizeof(t6_tp_pio_array) +
			    sizeof(t6_tp_tm_pio_array) +
			    sizeof(t6_tp_mib_index_array);
			break;
		default:
			break;
		}
		n = n / (IREG_NUM_ELEM * sizeof(u32));
		len = sizeof(struct ireg_buf) * n;
		break;
90 91 92
	case CUDBG_MBOX_LOG:
		len = sizeof(struct cudbg_mbox_log) * adap->mbox_log->size;
		break;
R
Rahul Lakkireddy 已提交
93 94 95 96 97 98 99
	default:
		break;
	}

	return len;
}

100 101
u32 cxgb4_get_dump_length(struct adapter *adap, u32 flag)
{
R
Rahul Lakkireddy 已提交
102 103 104 105 106 107 108 109 110 111
	u32 i, entity;
	u32 len = 0;

	if (flag & CXGB4_ETH_DUMP_HW) {
		for (i = 0; i < ARRAY_SIZE(cxgb4_collect_hw_dump); i++) {
			entity = cxgb4_collect_hw_dump[i].entity;
			len += cxgb4_get_entity_length(adap, entity);
		}
	}

112 113 114 115 116 117 118
	if (flag & CXGB4_ETH_DUMP_MEM) {
		for (i = 0; i < ARRAY_SIZE(cxgb4_collect_mem_dump); i++) {
			entity = cxgb4_collect_mem_dump[i].entity;
			len += cxgb4_get_entity_length(adap, entity);
		}
	}

R
Rahul Lakkireddy 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	return len;
}

static void cxgb4_cudbg_collect_entity(struct cudbg_init *pdbg_init,
				       struct cudbg_buffer *dbg_buff,
				       const struct cxgb4_collect_entity *e_arr,
				       u32 arr_size, void *buf, u32 *tot_size)
{
	struct adapter *adap = pdbg_init->adap;
	struct cudbg_error cudbg_err = { 0 };
	struct cudbg_entity_hdr *entity_hdr;
	u32 entity_size, i;
	u32 total_size = 0;
	int ret;

	for (i = 0; i < arr_size; i++) {
		const struct cxgb4_collect_entity *e = &e_arr[i];

		/* Skip entities that won't fit in output buffer */
		entity_size = cxgb4_get_entity_length(adap, e->entity);
		if (entity_size >
		    pdbg_init->outbuf_size - *tot_size - total_size)
			continue;

		entity_hdr = cudbg_get_entity_hdr(buf, e->entity);
		entity_hdr->entity_type = e->entity;
		entity_hdr->start_offset = dbg_buff->offset;
		memset(&cudbg_err, 0, sizeof(struct cudbg_error));
		ret = e->collect_cb(pdbg_init, dbg_buff, &cudbg_err);
		if (ret) {
			entity_hdr->size = 0;
			dbg_buff->offset = entity_hdr->start_offset;
		} else {
			cudbg_align_debug_buffer(dbg_buff, entity_hdr);
		}

		/* Log error and continue with next entity */
		if (cudbg_err.sys_err)
			ret = CUDBG_SYSTEM_ERROR;

		entity_hdr->hdr_flags = ret;
		entity_hdr->sys_err = cudbg_err.sys_err;
		entity_hdr->sys_warn = cudbg_err.sys_warn;
		total_size += entity_hdr->size;
	}

	*tot_size += total_size;
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
}

int cxgb4_cudbg_collect(struct adapter *adap, void *buf, u32 *buf_size,
			u32 flag)
{
	struct cudbg_init cudbg_init = { 0 };
	struct cudbg_buffer dbg_buff = { 0 };
	u32 size, min_size, total_size = 0;
	struct cudbg_hdr *cudbg_hdr;

	size = *buf_size;

	cudbg_init.adap = adap;
	cudbg_init.outbuf = buf;
	cudbg_init.outbuf_size = size;

	dbg_buff.data = buf;
	dbg_buff.size = size;
	dbg_buff.offset = 0;

	cudbg_hdr = (struct cudbg_hdr *)buf;
	cudbg_hdr->signature = CUDBG_SIGNATURE;
	cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr);
	cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION;
	cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION;
	cudbg_hdr->max_entities = CUDBG_MAX_ENTITY;
	cudbg_hdr->chip_ver = adap->params.chip;
	cudbg_hdr->dump_type = CUDBG_DUMP_TYPE_MINI;
	cudbg_hdr->compress_type = CUDBG_COMPRESSION_NONE;

	min_size = sizeof(struct cudbg_hdr) +
		   sizeof(struct cudbg_entity_hdr) *
		   cudbg_hdr->max_entities;
	if (size < min_size)
		return -ENOMEM;

	dbg_buff.offset += min_size;
	total_size = dbg_buff.offset;

R
Rahul Lakkireddy 已提交
205 206 207 208 209 210 211
	if (flag & CXGB4_ETH_DUMP_HW)
		cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff,
					   cxgb4_collect_hw_dump,
					   ARRAY_SIZE(cxgb4_collect_hw_dump),
					   buf,
					   &total_size);

212 213 214 215 216 217 218
	if (flag & CXGB4_ETH_DUMP_MEM)
		cxgb4_cudbg_collect_entity(&cudbg_init, &dbg_buff,
					   cxgb4_collect_mem_dump,
					   ARRAY_SIZE(cxgb4_collect_mem_dump),
					   buf,
					   &total_size);

219 220 221 222 223 224 225 226 227 228 229
	cudbg_hdr->data_len = total_size;
	*buf_size = total_size;
	return 0;
}

void cxgb4_init_ethtool_dump(struct adapter *adapter)
{
	adapter->eth_dump.flag = CXGB4_ETH_DUMP_NONE;
	adapter->eth_dump.version = adapter->params.fw_vers;
	adapter->eth_dump.len = 0;
}