xref: /dpdk/drivers/net/qede/qede_regs.c (revision fac8177a3669ff63d9ecb04372539e93e1f96ebf)
1a50d7cbbSRasesh Mody /* SPDX-License-Identifier: BSD-3-Clause
2a50d7cbbSRasesh Mody  * Copyright (c) 2020 Marvell Semiconductor Inc.
3a50d7cbbSRasesh Mody  * All rights reserved.
4a50d7cbbSRasesh Mody  * www.marvell.com
5a50d7cbbSRasesh Mody  */
6a50d7cbbSRasesh Mody 
7a50d7cbbSRasesh Mody #include <stdio.h>
8a50d7cbbSRasesh Mody #include <stdlib.h>
9a50d7cbbSRasesh Mody #include <fcntl.h>
10a50d7cbbSRasesh Mody #include <time.h>
11a50d7cbbSRasesh Mody #include <rte_ethdev.h>
12a50d7cbbSRasesh Mody #include "base/bcm_osal.h"
13a50d7cbbSRasesh Mody #include "qede_ethdev.h"
14a50d7cbbSRasesh Mody 
15a50d7cbbSRasesh Mody int
qede_get_regs_len(struct qede_dev * qdev)16a50d7cbbSRasesh Mody qede_get_regs_len(struct qede_dev *qdev)
17a50d7cbbSRasesh Mody {
18a50d7cbbSRasesh Mody 	struct ecore_dev *edev = &qdev->edev;
19a50d7cbbSRasesh Mody 	int cur_engine, num_of_hwfns, regs_len = 0;
20a50d7cbbSRasesh Mody 	uint8_t org_engine;
21a50d7cbbSRasesh Mody 
22a50d7cbbSRasesh Mody 	if (IS_VF(edev))
23a50d7cbbSRasesh Mody 		return 0;
24a50d7cbbSRasesh Mody 
25a50d7cbbSRasesh Mody 	if (qdev->ops && qdev->ops->common) {
26a50d7cbbSRasesh Mody 		num_of_hwfns = qdev->dev_info.common.num_hwfns;
27a50d7cbbSRasesh Mody 		org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
28a50d7cbbSRasesh Mody 		for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
29a50d7cbbSRasesh Mody 			/* compute required buffer size for idle_chks and
30a50d7cbbSRasesh Mody 			 * grcDump for each hw function
31a50d7cbbSRasesh Mody 			 */
32a50d7cbbSRasesh Mody 			DP_NOTICE(edev, false,
33a50d7cbbSRasesh Mody 				"Calculating idle_chk and grcdump register length for current engine\n");
34a50d7cbbSRasesh Mody 			qdev->ops->common->dbg_set_debug_engine(edev,
35a50d7cbbSRasesh Mody 								cur_engine);
36a50d7cbbSRasesh Mody 			regs_len += REGDUMP_HEADER_SIZE +
37a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_idle_chk_size(edev) +
38a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
39a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_idle_chk_size(edev) +
40a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
41a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_grc_size(edev) +
42a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
43a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_reg_fifo_size(edev) +
44a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
45a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_protection_override_size(edev) +
46a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
47a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_igu_fifo_size(edev) +
48a50d7cbbSRasesh Mody 				REGDUMP_HEADER_SIZE +
49a50d7cbbSRasesh Mody 				qdev->ops->common->dbg_fw_asserts_size(edev);
50a50d7cbbSRasesh Mody 		}
51a50d7cbbSRasesh Mody 		/* compute required buffer size for mcp trace and add it to the
52a50d7cbbSRasesh Mody 		 * total required buffer size
53a50d7cbbSRasesh Mody 		 */
54a50d7cbbSRasesh Mody 		regs_len += REGDUMP_HEADER_SIZE +
55a50d7cbbSRasesh Mody 			    qdev->ops->common->dbg_mcp_trace_size(edev);
56a50d7cbbSRasesh Mody 
57a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
58a50d7cbbSRasesh Mody 	}
59a50d7cbbSRasesh Mody 	DP_NOTICE(edev, false, "Total length = %u\n", regs_len);
60a50d7cbbSRasesh Mody 
61a50d7cbbSRasesh Mody 	return regs_len;
62a50d7cbbSRasesh Mody }
63a50d7cbbSRasesh Mody 
64a50d7cbbSRasesh Mody static uint32_t
qede_calc_regdump_header(enum debug_print_features feature,int engine,uint32_t feature_size,uint8_t omit_engine)65a50d7cbbSRasesh Mody qede_calc_regdump_header(enum debug_print_features feature, int engine,
66a50d7cbbSRasesh Mody 			 uint32_t feature_size, uint8_t omit_engine)
67a50d7cbbSRasesh Mody {
68a50d7cbbSRasesh Mody 	/* insert the engine, feature and mode inside the header and
69a50d7cbbSRasesh Mody 	 * combine it with feature size
70a50d7cbbSRasesh Mody 	 */
71a50d7cbbSRasesh Mody 	return (feature_size | (feature << REGDUMP_HEADER_FEATURE_SHIFT) |
72a50d7cbbSRasesh Mody 		(omit_engine << REGDUMP_HEADER_OMIT_ENGINE_SHIFT) |
73a50d7cbbSRasesh Mody 		(engine << REGDUMP_HEADER_ENGINE_SHIFT));
74a50d7cbbSRasesh Mody }
75a50d7cbbSRasesh Mody 
qede_get_regs(struct rte_eth_dev * eth_dev,struct rte_dev_reg_info * regs)76a50d7cbbSRasesh Mody int qede_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
77a50d7cbbSRasesh Mody {
78a50d7cbbSRasesh Mody 	struct qede_dev *qdev = eth_dev->data->dev_private;
79a50d7cbbSRasesh Mody 	struct ecore_dev *edev = &qdev->edev;
80a50d7cbbSRasesh Mody 	uint32_t *buffer = regs->data;
81a50d7cbbSRasesh Mody 	int cur_engine, num_of_hwfns;
82a50d7cbbSRasesh Mody 	/* '1' tells the parser to omit the engine number in the output files */
83a50d7cbbSRasesh Mody 	uint8_t omit_engine = 0;
84a50d7cbbSRasesh Mody 	uint8_t org_engine;
85a50d7cbbSRasesh Mody 	uint32_t feature_size;
86a50d7cbbSRasesh Mody 	uint32_t offset = 0;
87a50d7cbbSRasesh Mody 
88a50d7cbbSRasesh Mody 	if (IS_VF(edev))
89a50d7cbbSRasesh Mody 		return -ENOTSUP;
90a50d7cbbSRasesh Mody 
91a50d7cbbSRasesh Mody 	if (buffer == NULL) {
92a50d7cbbSRasesh Mody 		regs->length = qede_get_regs_len(qdev);
93a50d7cbbSRasesh Mody 		regs->width =  sizeof(uint32_t);
94a50d7cbbSRasesh Mody 		DP_INFO(edev, "Length %u\n", regs->length);
95a50d7cbbSRasesh Mody 		return 0;
96a50d7cbbSRasesh Mody 	}
97a50d7cbbSRasesh Mody 
98a50d7cbbSRasesh Mody 	memset(buffer, 0, regs->length);
99a50d7cbbSRasesh Mody 	num_of_hwfns = qdev->dev_info.common.num_hwfns;
100a50d7cbbSRasesh Mody 	if (num_of_hwfns == 1)
101a50d7cbbSRasesh Mody 		omit_engine = 1;
102a50d7cbbSRasesh Mody 
103a50d7cbbSRasesh Mody 	OSAL_MUTEX_ACQUIRE(&edev->dbg_lock);
104a50d7cbbSRasesh Mody 
105a50d7cbbSRasesh Mody 	org_engine = qdev->ops->common->dbg_get_debug_engine(edev);
106a50d7cbbSRasesh Mody 	for (cur_engine = 0; cur_engine < num_of_hwfns; cur_engine++) {
107a50d7cbbSRasesh Mody 		/* collect idle_chks and grcDump for each hw function */
108a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "obtaining idle_chk and grcdump for current engine\n");
109a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_set_debug_engine(edev, cur_engine);
110a50d7cbbSRasesh Mody 
111a50d7cbbSRasesh Mody 		/* first idle_chk */
112a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
113a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
114a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
115a50d7cbbSRasesh Mody 			qede_calc_regdump_header(IDLE_CHK, cur_engine,
116a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
117a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
118a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "Idle Check1 feature_size %u\n",
119a50d7cbbSRasesh Mody 			  feature_size);
120a50d7cbbSRasesh Mody 
121a50d7cbbSRasesh Mody 		/* second idle_chk */
122a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_idle_chk(edev, (uint8_t *)buffer +
123a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
124a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
125a50d7cbbSRasesh Mody 			qede_calc_regdump_header(IDLE_CHK, cur_engine,
126a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
127a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
128a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "Idle Check2 feature_size %u\n",
129a50d7cbbSRasesh Mody 			  feature_size);
130a50d7cbbSRasesh Mody 
131a50d7cbbSRasesh Mody 		/* reg_fifo dump */
132a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_reg_fifo(edev, (uint8_t *)buffer +
133a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
134a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
135a50d7cbbSRasesh Mody 			qede_calc_regdump_header(REG_FIFO, cur_engine,
136a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
137a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
138a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "Reg fifo feature_size %u\n",
139a50d7cbbSRasesh Mody 			  feature_size);
140a50d7cbbSRasesh Mody 
141a50d7cbbSRasesh Mody 		/* igu_fifo dump */
142a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_igu_fifo(edev, (uint8_t *)buffer +
143a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
144a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
145a50d7cbbSRasesh Mody 			qede_calc_regdump_header(IGU_FIFO, cur_engine,
146a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
147a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
148a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "IGU fifo feature_size %u\n",
149a50d7cbbSRasesh Mody 			  feature_size);
150a50d7cbbSRasesh Mody 
151a50d7cbbSRasesh Mody 		/* protection_override dump */
152a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_protection_override(edev,
153a50d7cbbSRasesh Mody 							   (uint8_t *)buffer +
154a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
155a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
156a50d7cbbSRasesh Mody 		       qede_calc_regdump_header(PROTECTION_OVERRIDE, cur_engine,
157a50d7cbbSRasesh Mody 						feature_size, omit_engine);
158a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
159a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "Protection override feature_size %u\n",
160a50d7cbbSRasesh Mody 			  feature_size);
161a50d7cbbSRasesh Mody 
162a50d7cbbSRasesh Mody 		/* fw_asserts dump */
163a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_fw_asserts(edev, (uint8_t *)buffer +
164a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
165a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
166a50d7cbbSRasesh Mody 			qede_calc_regdump_header(FW_ASSERTS, cur_engine,
167a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
168a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
169a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "FW assert feature_size %u\n",
170a50d7cbbSRasesh Mody 			  feature_size);
171a50d7cbbSRasesh Mody 
172a50d7cbbSRasesh Mody 		/* grc dump */
173a50d7cbbSRasesh Mody 		qdev->ops->common->dbg_grc(edev, (uint8_t *)buffer +
174a50d7cbbSRasesh Mody 			offset + REGDUMP_HEADER_SIZE, &feature_size);
175a50d7cbbSRasesh Mody 		*(uint32_t *)((uint8_t *)buffer + offset) =
176a50d7cbbSRasesh Mody 			qede_calc_regdump_header(GRC_DUMP, cur_engine,
177a50d7cbbSRasesh Mody 						 feature_size, omit_engine);
178a50d7cbbSRasesh Mody 		offset += (feature_size + REGDUMP_HEADER_SIZE);
179a50d7cbbSRasesh Mody 		DP_NOTICE(edev, false, "GRC dump feature_size %u\n",
180a50d7cbbSRasesh Mody 			  feature_size);
181a50d7cbbSRasesh Mody 	}
182a50d7cbbSRasesh Mody 
183a50d7cbbSRasesh Mody 	/* mcp_trace */
184a50d7cbbSRasesh Mody 	qdev->ops->common->dbg_mcp_trace(edev, (uint8_t *)buffer +
185a50d7cbbSRasesh Mody 		offset + REGDUMP_HEADER_SIZE, &feature_size);
186a50d7cbbSRasesh Mody 	*(uint32_t *)((uint8_t *)buffer + offset) =
187a50d7cbbSRasesh Mody 		qede_calc_regdump_header(MCP_TRACE, cur_engine, feature_size,
188a50d7cbbSRasesh Mody 					 omit_engine);
189a50d7cbbSRasesh Mody 	offset += (feature_size + REGDUMP_HEADER_SIZE);
190a50d7cbbSRasesh Mody 	DP_NOTICE(edev, false, "MCP trace feature_size %u\n", feature_size);
191a50d7cbbSRasesh Mody 
192a50d7cbbSRasesh Mody 	qdev->ops->common->dbg_set_debug_engine(edev, org_engine);
193a50d7cbbSRasesh Mody 
194a50d7cbbSRasesh Mody 	OSAL_MUTEX_RELEASE(&edev->dbg_lock);
195a50d7cbbSRasesh Mody 
196a50d7cbbSRasesh Mody 	return 0;
197a50d7cbbSRasesh Mody }
198a50d7cbbSRasesh Mody 
199a50d7cbbSRasesh Mody static void
qede_set_fw_dump_file_name(struct qede_dev * qdev)200a50d7cbbSRasesh Mody qede_set_fw_dump_file_name(struct qede_dev *qdev)
201a50d7cbbSRasesh Mody {
202a50d7cbbSRasesh Mody 	time_t ltime;
203a50d7cbbSRasesh Mody 	struct tm *tm;
204a50d7cbbSRasesh Mody 
205a50d7cbbSRasesh Mody 	ltime = time(NULL);
206a50d7cbbSRasesh Mody 	tm = localtime(&ltime);
207a50d7cbbSRasesh Mody 	snprintf(qdev->dump_file, QEDE_FW_DUMP_FILE_SIZE,
208a50d7cbbSRasesh Mody 		 "qede_pmd_dump_%02d-%02d-%02d_%02d-%02d-%02d.bin",
209a50d7cbbSRasesh Mody 		 tm->tm_mon + 1, (int)tm->tm_mday, 1900 + tm->tm_year,
210a50d7cbbSRasesh Mody 		 tm->tm_hour, tm->tm_min, tm->tm_sec);
211a50d7cbbSRasesh Mody }
212a50d7cbbSRasesh Mody 
213a50d7cbbSRasesh Mody static int
qede_write_fwdump(const char * dump_file,void * dump,size_t len)214a50d7cbbSRasesh Mody qede_write_fwdump(const char *dump_file, void *dump, size_t len)
215a50d7cbbSRasesh Mody {
216a50d7cbbSRasesh Mody 	int err = 0;
217a50d7cbbSRasesh Mody 	FILE *f;
218a50d7cbbSRasesh Mody 	size_t bytes;
219a50d7cbbSRasesh Mody 
220a50d7cbbSRasesh Mody 	f = fopen(dump_file, "wb+");
221a50d7cbbSRasesh Mody 
222a50d7cbbSRasesh Mody 	if (!f) {
223a50d7cbbSRasesh Mody 		fprintf(stderr, "Can't open file %s: %s\n",
224a50d7cbbSRasesh Mody 			dump_file, strerror(errno));
225a50d7cbbSRasesh Mody 		return 1;
226a50d7cbbSRasesh Mody 	}
227a50d7cbbSRasesh Mody 	bytes = fwrite(dump, 1, len, f);
228a50d7cbbSRasesh Mody 	if (bytes != len) {
229a50d7cbbSRasesh Mody 		fprintf(stderr,
230a50d7cbbSRasesh Mody 			"Can not write all of dump data bytes=%zd len=%zd\n",
231a50d7cbbSRasesh Mody 			bytes, len);
232a50d7cbbSRasesh Mody 		err = 1;
233a50d7cbbSRasesh Mody 	}
234a50d7cbbSRasesh Mody 
235a50d7cbbSRasesh Mody 	if (fclose(f)) {
236a50d7cbbSRasesh Mody 		fprintf(stderr, "Can't close file %s: %s\n",
237a50d7cbbSRasesh Mody 			dump_file, strerror(errno));
238a50d7cbbSRasesh Mody 		err = 1;
239a50d7cbbSRasesh Mody 	}
240a50d7cbbSRasesh Mody 
241a50d7cbbSRasesh Mody 	return err;
242a50d7cbbSRasesh Mody }
243a50d7cbbSRasesh Mody 
244a50d7cbbSRasesh Mody int
qede_save_fw_dump(uint16_t port_id)245*fac8177aSChenbo Xia qede_save_fw_dump(uint16_t port_id)
246a50d7cbbSRasesh Mody {
247a50d7cbbSRasesh Mody 	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
248a50d7cbbSRasesh Mody 	struct rte_dev_reg_info regs;
249a50d7cbbSRasesh Mody 	struct qede_dev *qdev = eth_dev->data->dev_private;
250a50d7cbbSRasesh Mody 	struct ecore_dev *edev = &qdev->edev;
251a50d7cbbSRasesh Mody 	int rc = 0;
252a50d7cbbSRasesh Mody 
253a50d7cbbSRasesh Mody 	if (!rte_eth_dev_is_valid_port(port_id)) {
254a50d7cbbSRasesh Mody 		DP_ERR(edev, "port %u invalid port ID", port_id);
255a50d7cbbSRasesh Mody 		return -ENODEV;
256a50d7cbbSRasesh Mody 	}
257a50d7cbbSRasesh Mody 
258a50d7cbbSRasesh Mody 	memset(&regs, 0, sizeof(regs));
259a50d7cbbSRasesh Mody 	regs.length = qede_get_regs_len(qdev);
260a50d7cbbSRasesh Mody 	regs.data = OSAL_ZALLOC(eth_dev, GFP_KERNEL, regs.length);
261a50d7cbbSRasesh Mody 	if (regs.data) {
262a50d7cbbSRasesh Mody 		qede_get_regs(eth_dev, &regs);
263a50d7cbbSRasesh Mody 		qede_set_fw_dump_file_name(qdev);
264a50d7cbbSRasesh Mody 		rc = qede_write_fwdump(qdev->dump_file, regs.data, regs.length);
265a50d7cbbSRasesh Mody 		if (!rc)
266a50d7cbbSRasesh Mody 			DP_NOTICE(edev, false, "FW dump written to %s file\n",
267a50d7cbbSRasesh Mody 				  qdev->dump_file);
268a50d7cbbSRasesh Mody 		OSAL_FREE(edev, regs.data);
269a50d7cbbSRasesh Mody 	}
270a50d7cbbSRasesh Mody 
271a50d7cbbSRasesh Mody 	return rc;
272a50d7cbbSRasesh Mody }
273