xref: /linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-dump.c (revision c441bfb5f2866de71e092c1b9d866a65978dfe1a)
1*e0ab3dd5SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0
2*e0ab3dd5SMarc Kleine-Budde //
3*e0ab3dd5SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
4*e0ab3dd5SMarc Kleine-Budde //
5*e0ab3dd5SMarc Kleine-Budde // Copyright (c) 2020, 2021 Pengutronix,
6*e0ab3dd5SMarc Kleine-Budde //               Marc Kleine-Budde <kernel@pengutronix.de>
7*e0ab3dd5SMarc Kleine-Budde // Copyright (C) 2015-2018 Etnaviv Project
8*e0ab3dd5SMarc Kleine-Budde //
9*e0ab3dd5SMarc Kleine-Budde 
10*e0ab3dd5SMarc Kleine-Budde #include <linux/devcoredump.h>
11*e0ab3dd5SMarc Kleine-Budde 
12*e0ab3dd5SMarc Kleine-Budde #include "mcp251xfd.h"
13*e0ab3dd5SMarc Kleine-Budde #include "mcp251xfd-dump.h"
14*e0ab3dd5SMarc Kleine-Budde 
15*e0ab3dd5SMarc Kleine-Budde struct mcp251xfd_dump_iter {
16*e0ab3dd5SMarc Kleine-Budde 	void *start;
17*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_object_header *hdr;
18*e0ab3dd5SMarc Kleine-Budde 	void *data;
19*e0ab3dd5SMarc Kleine-Budde };
20*e0ab3dd5SMarc Kleine-Budde 
21*e0ab3dd5SMarc Kleine-Budde struct mcp251xfd_dump_reg_space {
22*e0ab3dd5SMarc Kleine-Budde 	u16 base;
23*e0ab3dd5SMarc Kleine-Budde 	u16 size;
24*e0ab3dd5SMarc Kleine-Budde };
25*e0ab3dd5SMarc Kleine-Budde 
26*e0ab3dd5SMarc Kleine-Budde struct mcp251xfd_dump_ring {
27*e0ab3dd5SMarc Kleine-Budde 	enum mcp251xfd_dump_object_ring_key key;
28*e0ab3dd5SMarc Kleine-Budde 	u32 val;
29*e0ab3dd5SMarc Kleine-Budde };
30*e0ab3dd5SMarc Kleine-Budde 
31*e0ab3dd5SMarc Kleine-Budde static const struct mcp251xfd_dump_reg_space mcp251xfd_dump_reg_space[] = {
32*e0ab3dd5SMarc Kleine-Budde 	{
33*e0ab3dd5SMarc Kleine-Budde 		.base = MCP251XFD_REG_CON,
34*e0ab3dd5SMarc Kleine-Budde 		.size = MCP251XFD_REG_FLTOBJ(32) - MCP251XFD_REG_CON,
35*e0ab3dd5SMarc Kleine-Budde 	}, {
36*e0ab3dd5SMarc Kleine-Budde 		.base = MCP251XFD_RAM_START,
37*e0ab3dd5SMarc Kleine-Budde 		.size = MCP251XFD_RAM_SIZE,
38*e0ab3dd5SMarc Kleine-Budde 	}, {
39*e0ab3dd5SMarc Kleine-Budde 		.base = MCP251XFD_REG_OSC,
40*e0ab3dd5SMarc Kleine-Budde 		.size = MCP251XFD_REG_DEVID - MCP251XFD_REG_OSC,
41*e0ab3dd5SMarc Kleine-Budde 	},
42*e0ab3dd5SMarc Kleine-Budde };
43*e0ab3dd5SMarc Kleine-Budde 
44*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_header(struct mcp251xfd_dump_iter *iter,
45*e0ab3dd5SMarc Kleine-Budde 				  enum mcp251xfd_dump_object_type object_type,
46*e0ab3dd5SMarc Kleine-Budde 				  const void *data_end)
47*e0ab3dd5SMarc Kleine-Budde {
48*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_object_header *hdr = iter->hdr;
49*e0ab3dd5SMarc Kleine-Budde 	unsigned int len;
50*e0ab3dd5SMarc Kleine-Budde 
51*e0ab3dd5SMarc Kleine-Budde 	len = data_end - iter->data;
52*e0ab3dd5SMarc Kleine-Budde 	if (!len)
53*e0ab3dd5SMarc Kleine-Budde 		return;
54*e0ab3dd5SMarc Kleine-Budde 
55*e0ab3dd5SMarc Kleine-Budde 	hdr->magic = cpu_to_le32(MCP251XFD_DUMP_MAGIC);
56*e0ab3dd5SMarc Kleine-Budde 	hdr->type = cpu_to_le32(object_type);
57*e0ab3dd5SMarc Kleine-Budde 	hdr->offset = cpu_to_le32(iter->data - iter->start);
58*e0ab3dd5SMarc Kleine-Budde 	hdr->len = cpu_to_le32(len);
59*e0ab3dd5SMarc Kleine-Budde 
60*e0ab3dd5SMarc Kleine-Budde 	iter->hdr++;
61*e0ab3dd5SMarc Kleine-Budde 	iter->data += len;
62*e0ab3dd5SMarc Kleine-Budde }
63*e0ab3dd5SMarc Kleine-Budde 
64*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_registers(const struct mcp251xfd_priv *priv,
65*e0ab3dd5SMarc Kleine-Budde 				     struct mcp251xfd_dump_iter *iter)
66*e0ab3dd5SMarc Kleine-Budde {
67*e0ab3dd5SMarc Kleine-Budde 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
68*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_object_reg *reg = iter->data;
69*e0ab3dd5SMarc Kleine-Budde 	unsigned int i, j;
70*e0ab3dd5SMarc Kleine-Budde 	int err;
71*e0ab3dd5SMarc Kleine-Budde 
72*e0ab3dd5SMarc Kleine-Budde 	for (i = 0; i < ARRAY_SIZE(mcp251xfd_dump_reg_space); i++) {
73*e0ab3dd5SMarc Kleine-Budde 		const struct mcp251xfd_dump_reg_space *reg_space;
74*e0ab3dd5SMarc Kleine-Budde 		void *buf;
75*e0ab3dd5SMarc Kleine-Budde 
76*e0ab3dd5SMarc Kleine-Budde 		reg_space = &mcp251xfd_dump_reg_space[i];
77*e0ab3dd5SMarc Kleine-Budde 
78*e0ab3dd5SMarc Kleine-Budde 		buf = kmalloc(reg_space->size, GFP_KERNEL);
79*e0ab3dd5SMarc Kleine-Budde 		if (!buf)
80*e0ab3dd5SMarc Kleine-Budde 			goto out;
81*e0ab3dd5SMarc Kleine-Budde 
82*e0ab3dd5SMarc Kleine-Budde 		err = regmap_bulk_read(priv->map_reg, reg_space->base,
83*e0ab3dd5SMarc Kleine-Budde 				       buf, reg_space->size / val_bytes);
84*e0ab3dd5SMarc Kleine-Budde 		if (err) {
85*e0ab3dd5SMarc Kleine-Budde 			kfree(buf);
86*e0ab3dd5SMarc Kleine-Budde 			continue;
87*e0ab3dd5SMarc Kleine-Budde 		}
88*e0ab3dd5SMarc Kleine-Budde 
89*e0ab3dd5SMarc Kleine-Budde 		for (j = 0; j < reg_space->size; j += sizeof(u32), reg++) {
90*e0ab3dd5SMarc Kleine-Budde 			reg->reg = cpu_to_le32(reg_space->base + j);
91*e0ab3dd5SMarc Kleine-Budde 			reg->val = cpu_to_le32p(buf + j);
92*e0ab3dd5SMarc Kleine-Budde 		}
93*e0ab3dd5SMarc Kleine-Budde 
94*e0ab3dd5SMarc Kleine-Budde 		kfree(buf);
95*e0ab3dd5SMarc Kleine-Budde 	}
96*e0ab3dd5SMarc Kleine-Budde 
97*e0ab3dd5SMarc Kleine-Budde  out:
98*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_header(iter, MCP251XFD_DUMP_OBJECT_TYPE_REG, reg);
99*e0ab3dd5SMarc Kleine-Budde }
100*e0ab3dd5SMarc Kleine-Budde 
101*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_ring(struct mcp251xfd_dump_iter *iter,
102*e0ab3dd5SMarc Kleine-Budde 				enum mcp251xfd_dump_object_type object_type,
103*e0ab3dd5SMarc Kleine-Budde 				const struct mcp251xfd_dump_ring *dump_ring,
104*e0ab3dd5SMarc Kleine-Budde 				unsigned int len)
105*e0ab3dd5SMarc Kleine-Budde {
106*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_object_reg *reg = iter->data;
107*e0ab3dd5SMarc Kleine-Budde 	unsigned int i;
108*e0ab3dd5SMarc Kleine-Budde 
109*e0ab3dd5SMarc Kleine-Budde 	for (i = 0; i < len; i++, reg++) {
110*e0ab3dd5SMarc Kleine-Budde 		reg->reg = cpu_to_le32(dump_ring[i].key);
111*e0ab3dd5SMarc Kleine-Budde 		reg->val = cpu_to_le32(dump_ring[i].val);
112*e0ab3dd5SMarc Kleine-Budde 	}
113*e0ab3dd5SMarc Kleine-Budde 
114*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_header(iter, object_type, reg);
115*e0ab3dd5SMarc Kleine-Budde }
116*e0ab3dd5SMarc Kleine-Budde 
117*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_tef_ring(const struct mcp251xfd_priv *priv,
118*e0ab3dd5SMarc Kleine-Budde 				    struct mcp251xfd_dump_iter *iter)
119*e0ab3dd5SMarc Kleine-Budde {
120*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_tef_ring *tef = priv->tef;
121*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx = priv->tx;
122*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_dump_ring dump_ring[] = {
123*e0ab3dd5SMarc Kleine-Budde 		{
124*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
125*e0ab3dd5SMarc Kleine-Budde 			.val = tef->head,
126*e0ab3dd5SMarc Kleine-Budde 		}, {
127*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
128*e0ab3dd5SMarc Kleine-Budde 			.val = tef->tail,
129*e0ab3dd5SMarc Kleine-Budde 		}, {
130*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
131*e0ab3dd5SMarc Kleine-Budde 			.val = 0,
132*e0ab3dd5SMarc Kleine-Budde 		}, {
133*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
134*e0ab3dd5SMarc Kleine-Budde 			.val = 0,
135*e0ab3dd5SMarc Kleine-Budde 		}, {
136*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
137*e0ab3dd5SMarc Kleine-Budde 			.val = 0,
138*e0ab3dd5SMarc Kleine-Budde 		}, {
139*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
140*e0ab3dd5SMarc Kleine-Budde 			.val = tx->obj_num,
141*e0ab3dd5SMarc Kleine-Budde 		}, {
142*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
143*e0ab3dd5SMarc Kleine-Budde 			.val = sizeof(struct mcp251xfd_hw_tef_obj),
144*e0ab3dd5SMarc Kleine-Budde 		},
145*e0ab3dd5SMarc Kleine-Budde 	};
146*e0ab3dd5SMarc Kleine-Budde 
147*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_TEF,
148*e0ab3dd5SMarc Kleine-Budde 			    dump_ring, ARRAY_SIZE(dump_ring));
149*e0ab3dd5SMarc Kleine-Budde }
150*e0ab3dd5SMarc Kleine-Budde 
151*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_rx_ring_one(const struct mcp251xfd_priv *priv,
152*e0ab3dd5SMarc Kleine-Budde 				       struct mcp251xfd_dump_iter *iter,
153*e0ab3dd5SMarc Kleine-Budde 				       const struct mcp251xfd_rx_ring *rx)
154*e0ab3dd5SMarc Kleine-Budde {
155*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_dump_ring dump_ring[] = {
156*e0ab3dd5SMarc Kleine-Budde 		{
157*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
158*e0ab3dd5SMarc Kleine-Budde 			.val = rx->head,
159*e0ab3dd5SMarc Kleine-Budde 		}, {
160*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
161*e0ab3dd5SMarc Kleine-Budde 			.val = rx->tail,
162*e0ab3dd5SMarc Kleine-Budde 		}, {
163*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
164*e0ab3dd5SMarc Kleine-Budde 			.val = rx->base,
165*e0ab3dd5SMarc Kleine-Budde 		}, {
166*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
167*e0ab3dd5SMarc Kleine-Budde 			.val = rx->nr,
168*e0ab3dd5SMarc Kleine-Budde 		}, {
169*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
170*e0ab3dd5SMarc Kleine-Budde 			.val = rx->fifo_nr,
171*e0ab3dd5SMarc Kleine-Budde 		}, {
172*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
173*e0ab3dd5SMarc Kleine-Budde 			.val = rx->obj_num,
174*e0ab3dd5SMarc Kleine-Budde 		}, {
175*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
176*e0ab3dd5SMarc Kleine-Budde 			.val = rx->obj_size,
177*e0ab3dd5SMarc Kleine-Budde 		},
178*e0ab3dd5SMarc Kleine-Budde 	};
179*e0ab3dd5SMarc Kleine-Budde 
180*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_RX,
181*e0ab3dd5SMarc Kleine-Budde 			    dump_ring, ARRAY_SIZE(dump_ring));
182*e0ab3dd5SMarc Kleine-Budde }
183*e0ab3dd5SMarc Kleine-Budde 
184*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_rx_ring(const struct mcp251xfd_priv *priv,
185*e0ab3dd5SMarc Kleine-Budde 				   struct mcp251xfd_dump_iter *iter)
186*e0ab3dd5SMarc Kleine-Budde {
187*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *rx_ring;
188*e0ab3dd5SMarc Kleine-Budde 	unsigned int i;
189*e0ab3dd5SMarc Kleine-Budde 
190*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i)
191*e0ab3dd5SMarc Kleine-Budde 		mcp251xfd_dump_rx_ring_one(priv, iter, rx_ring);
192*e0ab3dd5SMarc Kleine-Budde }
193*e0ab3dd5SMarc Kleine-Budde 
194*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_tx_ring(const struct mcp251xfd_priv *priv,
195*e0ab3dd5SMarc Kleine-Budde 				   struct mcp251xfd_dump_iter *iter)
196*e0ab3dd5SMarc Kleine-Budde {
197*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx = priv->tx;
198*e0ab3dd5SMarc Kleine-Budde 	const struct mcp251xfd_dump_ring dump_ring[] = {
199*e0ab3dd5SMarc Kleine-Budde 		{
200*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_HEAD,
201*e0ab3dd5SMarc Kleine-Budde 			.val = tx->head,
202*e0ab3dd5SMarc Kleine-Budde 		}, {
203*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_TAIL,
204*e0ab3dd5SMarc Kleine-Budde 			.val = tx->tail,
205*e0ab3dd5SMarc Kleine-Budde 		}, {
206*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_BASE,
207*e0ab3dd5SMarc Kleine-Budde 			.val = tx->base,
208*e0ab3dd5SMarc Kleine-Budde 		}, {
209*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_NR,
210*e0ab3dd5SMarc Kleine-Budde 			.val = 0,
211*e0ab3dd5SMarc Kleine-Budde 		}, {
212*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_FIFO_NR,
213*e0ab3dd5SMarc Kleine-Budde 			.val = MCP251XFD_TX_FIFO,
214*e0ab3dd5SMarc Kleine-Budde 		}, {
215*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_NUM,
216*e0ab3dd5SMarc Kleine-Budde 			.val = tx->obj_num,
217*e0ab3dd5SMarc Kleine-Budde 		}, {
218*e0ab3dd5SMarc Kleine-Budde 			.key = MCP251XFD_DUMP_OBJECT_RING_KEY_OBJ_SIZE,
219*e0ab3dd5SMarc Kleine-Budde 			.val = tx->obj_size,
220*e0ab3dd5SMarc Kleine-Budde 		},
221*e0ab3dd5SMarc Kleine-Budde 	};
222*e0ab3dd5SMarc Kleine-Budde 
223*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_ring(iter, MCP251XFD_DUMP_OBJECT_TYPE_TX,
224*e0ab3dd5SMarc Kleine-Budde 			    dump_ring, ARRAY_SIZE(dump_ring));
225*e0ab3dd5SMarc Kleine-Budde }
226*e0ab3dd5SMarc Kleine-Budde 
227*e0ab3dd5SMarc Kleine-Budde static void mcp251xfd_dump_end(const struct mcp251xfd_priv *priv,
228*e0ab3dd5SMarc Kleine-Budde 			       struct mcp251xfd_dump_iter *iter)
229*e0ab3dd5SMarc Kleine-Budde {
230*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_object_header *hdr = iter->hdr;
231*e0ab3dd5SMarc Kleine-Budde 
232*e0ab3dd5SMarc Kleine-Budde 	hdr->magic = cpu_to_le32(MCP251XFD_DUMP_MAGIC);
233*e0ab3dd5SMarc Kleine-Budde 	hdr->type = cpu_to_le32(MCP251XFD_DUMP_OBJECT_TYPE_END);
234*e0ab3dd5SMarc Kleine-Budde 	hdr->offset = cpu_to_le32(0);
235*e0ab3dd5SMarc Kleine-Budde 	hdr->len = cpu_to_le32(0);
236*e0ab3dd5SMarc Kleine-Budde 
237*e0ab3dd5SMarc Kleine-Budde 	/* provoke NULL pointer access, if used after END object */
238*e0ab3dd5SMarc Kleine-Budde 	iter->hdr = NULL;
239*e0ab3dd5SMarc Kleine-Budde }
240*e0ab3dd5SMarc Kleine-Budde 
241*e0ab3dd5SMarc Kleine-Budde void mcp251xfd_dump(const struct mcp251xfd_priv *priv)
242*e0ab3dd5SMarc Kleine-Budde {
243*e0ab3dd5SMarc Kleine-Budde 	struct mcp251xfd_dump_iter iter;
244*e0ab3dd5SMarc Kleine-Budde 	unsigned int rings_num, obj_num;
245*e0ab3dd5SMarc Kleine-Budde 	unsigned int file_size = 0;
246*e0ab3dd5SMarc Kleine-Budde 	unsigned int i;
247*e0ab3dd5SMarc Kleine-Budde 
248*e0ab3dd5SMarc Kleine-Budde 	/* register space + end marker */
249*e0ab3dd5SMarc Kleine-Budde 	obj_num = 2;
250*e0ab3dd5SMarc Kleine-Budde 
251*e0ab3dd5SMarc Kleine-Budde 	/* register space */
252*e0ab3dd5SMarc Kleine-Budde 	for (i = 0; i < ARRAY_SIZE(mcp251xfd_dump_reg_space); i++)
253*e0ab3dd5SMarc Kleine-Budde 		file_size += mcp251xfd_dump_reg_space[i].size / sizeof(u32) *
254*e0ab3dd5SMarc Kleine-Budde 			sizeof(struct mcp251xfd_dump_object_reg);
255*e0ab3dd5SMarc Kleine-Budde 
256*e0ab3dd5SMarc Kleine-Budde 	/* TEF ring, RX ring, TX rings */
257*e0ab3dd5SMarc Kleine-Budde 	rings_num = 1 + priv->rx_ring_num + 1;
258*e0ab3dd5SMarc Kleine-Budde 	obj_num += rings_num;
259*e0ab3dd5SMarc Kleine-Budde 	file_size += rings_num * __MCP251XFD_DUMP_OBJECT_RING_KEY_MAX  *
260*e0ab3dd5SMarc Kleine-Budde 		sizeof(struct mcp251xfd_dump_object_reg);
261*e0ab3dd5SMarc Kleine-Budde 
262*e0ab3dd5SMarc Kleine-Budde 	/* size of the headers */
263*e0ab3dd5SMarc Kleine-Budde 	file_size += sizeof(*iter.hdr) * obj_num;
264*e0ab3dd5SMarc Kleine-Budde 
265*e0ab3dd5SMarc Kleine-Budde 	/* allocate the file in vmalloc memory, it's likely to be big */
266*e0ab3dd5SMarc Kleine-Budde 	iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
267*e0ab3dd5SMarc Kleine-Budde 			       __GFP_ZERO | __GFP_NORETRY);
268*e0ab3dd5SMarc Kleine-Budde 	if (!iter.start) {
269*e0ab3dd5SMarc Kleine-Budde 		netdev_warn(priv->ndev, "Failed to allocate devcoredump file.\n");
270*e0ab3dd5SMarc Kleine-Budde 		return;
271*e0ab3dd5SMarc Kleine-Budde 	}
272*e0ab3dd5SMarc Kleine-Budde 
273*e0ab3dd5SMarc Kleine-Budde 	/* point the data member after the headers */
274*e0ab3dd5SMarc Kleine-Budde 	iter.hdr = iter.start;
275*e0ab3dd5SMarc Kleine-Budde 	iter.data = &iter.hdr[obj_num];
276*e0ab3dd5SMarc Kleine-Budde 
277*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_registers(priv, &iter);
278*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_tef_ring(priv, &iter);
279*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_rx_ring(priv, &iter);
280*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_tx_ring(priv, &iter);
281*e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump_end(priv, &iter);
282*e0ab3dd5SMarc Kleine-Budde 
283*e0ab3dd5SMarc Kleine-Budde 	dev_coredumpv(&priv->spi->dev, iter.start,
284*e0ab3dd5SMarc Kleine-Budde 		      iter.data - iter.start, GFP_KERNEL);
285*e0ab3dd5SMarc Kleine-Budde }
286