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