File Index
Files and directories
Sign in
FILE

xgbe-debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c C
  1// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
  2/*
  3 * Copyright (c) 2014-2025, Advanced Micro Devices, Inc.
  4 * Copyright (c) 2014, Synopsys, Inc.
  5 * All rights reserved
  6 */
  7
  8#include <linux/debugfs.h>
  9#include <linux/module.h>
 10#include <linux/slab.h>
 11
 12#include "xgbe.h"
 13#include "xgbe-common.h"
 14
 15static ssize_t xgbe_common_read(char __user *buffer, size_t count,
 16				loff_t *ppos, unsigned int value)
 17{
 18	char *buf;
 19	ssize_t len;
 20
 21	if (*ppos != 0)
 22		return 0;
 23
 24	buf = kasprintf(GFP_KERNEL, "0x%08x\n", value);
 25	if (!buf)
 26		return -ENOMEM;
 27
 28	if (count < strlen(buf)) {
 29		kfree(buf);
 30		return -ENOSPC;
 31	}
 32
 33	len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
 34	kfree(buf);
 35
 36	return len;
 37}
 38
 39static ssize_t xgbe_common_write(const char __user *buffer, size_t count,
 40				 loff_t *ppos, unsigned int *value)
 41{
 42	char workarea[32];
 43	ssize_t len;
 44	int ret;
 45
 46	if (*ppos != 0)
 47		return -EINVAL;
 48
 49	if (count >= sizeof(workarea))
 50		return -ENOSPC;
 51
 52	len = simple_write_to_buffer(workarea, sizeof(workarea) - 1, ppos,
 53				     buffer, count);
 54	if (len < 0)
 55		return len;
 56
 57	workarea[len] = '\0';
 58	ret = kstrtouint(workarea, 16, value);
 59	if (ret)
 60		return -EIO;
 61
 62	return len;
 63}
 64
 65static ssize_t xgmac_reg_addr_read(struct file *filp, char __user *buffer,
 66				   size_t count, loff_t *ppos)
 67{
 68	struct xgbe_prv_data *pdata = filp->private_data;
 69
 70	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xgmac_reg);
 71}
 72
 73static ssize_t xgmac_reg_addr_write(struct file *filp,
 74				    const char __user *buffer,
 75				    size_t count, loff_t *ppos)
 76{
 77	struct xgbe_prv_data *pdata = filp->private_data;
 78
 79	return xgbe_common_write(buffer, count, ppos,
 80				 &pdata->debugfs_xgmac_reg);
 81}
 82
 83static ssize_t xgmac_reg_value_read(struct file *filp, char __user *buffer,
 84				    size_t count, loff_t *ppos)
 85{
 86	struct xgbe_prv_data *pdata = filp->private_data;
 87	unsigned int value;
 88
 89	value = XGMAC_IOREAD(pdata, pdata->debugfs_xgmac_reg);
 90
 91	return xgbe_common_read(buffer, count, ppos, value);
 92}
 93
 94static ssize_t xgmac_reg_value_write(struct file *filp,
 95				     const char __user *buffer,
 96				     size_t count, loff_t *ppos)
 97{
 98	struct xgbe_prv_data *pdata = filp->private_data;
 99	unsigned int value;
100	ssize_t len;
101
102	len = xgbe_common_write(buffer, count, ppos, &value);
103	if (len < 0)
104		return len;
105
106	XGMAC_IOWRITE(pdata, pdata->debugfs_xgmac_reg, value);
107
108	return len;
109}
110
111static const struct file_operations xgmac_reg_addr_fops = {
112	.owner = THIS_MODULE,
113	.open = simple_open,
114	.read =  xgmac_reg_addr_read,
115	.write = xgmac_reg_addr_write,
116};
117
118static const struct file_operations xgmac_reg_value_fops = {
119	.owner = THIS_MODULE,
120	.open = simple_open,
121	.read =  xgmac_reg_value_read,
122	.write = xgmac_reg_value_write,
123};
124
125static ssize_t xpcs_mmd_read(struct file *filp, char __user *buffer,
126			     size_t count, loff_t *ppos)
127{
128	struct xgbe_prv_data *pdata = filp->private_data;
129
130	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_mmd);
131}
132
133static ssize_t xpcs_mmd_write(struct file *filp, const char __user *buffer,
134			      size_t count, loff_t *ppos)
135{
136	struct xgbe_prv_data *pdata = filp->private_data;
137
138	return xgbe_common_write(buffer, count, ppos,
139				 &pdata->debugfs_xpcs_mmd);
140}
141
142static ssize_t xpcs_reg_addr_read(struct file *filp, char __user *buffer,
143				  size_t count, loff_t *ppos)
144{
145	struct xgbe_prv_data *pdata = filp->private_data;
146
147	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xpcs_reg);
148}
149
150static ssize_t xpcs_reg_addr_write(struct file *filp, const char __user *buffer,
151				   size_t count, loff_t *ppos)
152{
153	struct xgbe_prv_data *pdata = filp->private_data;
154
155	return xgbe_common_write(buffer, count, ppos,
156				 &pdata->debugfs_xpcs_reg);
157}
158
159static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer,
160				   size_t count, loff_t *ppos)
161{
162	struct xgbe_prv_data *pdata = filp->private_data;
163	unsigned int value;
164
165	value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd,
166			   pdata->debugfs_xpcs_reg);
167
168	return xgbe_common_read(buffer, count, ppos, value);
169}
170
171static ssize_t xpcs_reg_value_write(struct file *filp,
172				    const char __user *buffer,
173				    size_t count, loff_t *ppos)
174{
175	struct xgbe_prv_data *pdata = filp->private_data;
176	unsigned int value;
177	ssize_t len;
178
179	len = xgbe_common_write(buffer, count, ppos, &value);
180	if (len < 0)
181		return len;
182
183	XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg,
184		    value);
185
186	return len;
187}
188
189static const struct file_operations xpcs_mmd_fops = {
190	.owner = THIS_MODULE,
191	.open = simple_open,
192	.read =  xpcs_mmd_read,
193	.write = xpcs_mmd_write,
194};
195
196static const struct file_operations xpcs_reg_addr_fops = {
197	.owner = THIS_MODULE,
198	.open = simple_open,
199	.read =  xpcs_reg_addr_read,
200	.write = xpcs_reg_addr_write,
201};
202
203static const struct file_operations xpcs_reg_value_fops = {
204	.owner = THIS_MODULE,
205	.open = simple_open,
206	.read =  xpcs_reg_value_read,
207	.write = xpcs_reg_value_write,
208};
209
210static ssize_t xprop_reg_addr_read(struct file *filp, char __user *buffer,
211				   size_t count, loff_t *ppos)
212{
213	struct xgbe_prv_data *pdata = filp->private_data;
214
215	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xprop_reg);
216}
217
218static ssize_t xprop_reg_addr_write(struct file *filp,
219				    const char __user *buffer,
220				    size_t count, loff_t *ppos)
221{
222	struct xgbe_prv_data *pdata = filp->private_data;
223
224	return xgbe_common_write(buffer, count, ppos,
225				 &pdata->debugfs_xprop_reg);
226}
227
228static ssize_t xprop_reg_value_read(struct file *filp, char __user *buffer,
229				    size_t count, loff_t *ppos)
230{
231	struct xgbe_prv_data *pdata = filp->private_data;
232	unsigned int value;
233
234	value = XP_IOREAD(pdata, pdata->debugfs_xprop_reg);
235
236	return xgbe_common_read(buffer, count, ppos, value);
237}
238
239static ssize_t xprop_reg_value_write(struct file *filp,
240				     const char __user *buffer,
241				     size_t count, loff_t *ppos)
242{
243	struct xgbe_prv_data *pdata = filp->private_data;
244	unsigned int value;
245	ssize_t len;
246
247	len = xgbe_common_write(buffer, count, ppos, &value);
248	if (len < 0)
249		return len;
250
251	XP_IOWRITE(pdata, pdata->debugfs_xprop_reg, value);
252
253	return len;
254}
255
256static const struct file_operations xprop_reg_addr_fops = {
257	.owner = THIS_MODULE,
258	.open = simple_open,
259	.read =  xprop_reg_addr_read,
260	.write = xprop_reg_addr_write,
261};
262
263static const struct file_operations xprop_reg_value_fops = {
264	.owner = THIS_MODULE,
265	.open = simple_open,
266	.read =  xprop_reg_value_read,
267	.write = xprop_reg_value_write,
268};
269
270static ssize_t xi2c_reg_addr_read(struct file *filp, char __user *buffer,
271				  size_t count, loff_t *ppos)
272{
273	struct xgbe_prv_data *pdata = filp->private_data;
274
275	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xi2c_reg);
276}
277
278static ssize_t xi2c_reg_addr_write(struct file *filp,
279				   const char __user *buffer,
280				   size_t count, loff_t *ppos)
281{
282	struct xgbe_prv_data *pdata = filp->private_data;
283
284	return xgbe_common_write(buffer, count, ppos,
285				 &pdata->debugfs_xi2c_reg);
286}
287
288static ssize_t xi2c_reg_value_read(struct file *filp, char __user *buffer,
289				   size_t count, loff_t *ppos)
290{
291	struct xgbe_prv_data *pdata = filp->private_data;
292	unsigned int value;
293
294	value = XI2C_IOREAD(pdata, pdata->debugfs_xi2c_reg);
295
296	return xgbe_common_read(buffer, count, ppos, value);
297}
298
299static ssize_t xi2c_reg_value_write(struct file *filp,
300				    const char __user *buffer,
301				    size_t count, loff_t *ppos)
302{
303	struct xgbe_prv_data *pdata = filp->private_data;
304	unsigned int value;
305	ssize_t len;
306
307	len = xgbe_common_write(buffer, count, ppos, &value);
308	if (len < 0)
309		return len;
310
311	XI2C_IOWRITE(pdata, pdata->debugfs_xi2c_reg, value);
312
313	return len;
314}
315
316static const struct file_operations xi2c_reg_addr_fops = {
317	.owner = THIS_MODULE,
318	.open = simple_open,
319	.read =  xi2c_reg_addr_read,
320	.write = xi2c_reg_addr_write,
321};
322
323static const struct file_operations xi2c_reg_value_fops = {
324	.owner = THIS_MODULE,
325	.open = simple_open,
326	.read =  xi2c_reg_value_read,
327	.write = xi2c_reg_value_write,
328};
329
330void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
331{
332	char *buf;
333
334	/* Set defaults */
335	pdata->debugfs_xgmac_reg = 0;
336	pdata->debugfs_xpcs_mmd = 1;
337	pdata->debugfs_xpcs_reg = 0;
338
339	buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
340	if (!buf)
341		return;
342
343	pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
344
345	debugfs_create_file("xgmac_register", 0600, pdata->xgbe_debugfs, pdata,
346			    &xgmac_reg_addr_fops);
347
348	debugfs_create_file("xgmac_register_value", 0600, pdata->xgbe_debugfs,
349			    pdata, &xgmac_reg_value_fops);
350
351	debugfs_create_file("xpcs_mmd", 0600, pdata->xgbe_debugfs, pdata,
352			    &xpcs_mmd_fops);
353
354	debugfs_create_file("xpcs_register", 0600, pdata->xgbe_debugfs, pdata,
355			    &xpcs_reg_addr_fops);
356
357	debugfs_create_file("xpcs_register_value", 0600, pdata->xgbe_debugfs,
358			    pdata, &xpcs_reg_value_fops);
359
360	if (pdata->xprop_regs) {
361		debugfs_create_file("xprop_register", 0600, pdata->xgbe_debugfs,
362				    pdata, &xprop_reg_addr_fops);
363
364		debugfs_create_file("xprop_register_value", 0600,
365				    pdata->xgbe_debugfs, pdata,
366				    &xprop_reg_value_fops);
367	}
368
369	if (pdata->xi2c_regs) {
370		debugfs_create_file("xi2c_register", 0600, pdata->xgbe_debugfs,
371				    pdata, &xi2c_reg_addr_fops);
372
373		debugfs_create_file("xi2c_register_value", 0600,
374				    pdata->xgbe_debugfs, pdata,
375				    &xi2c_reg_value_fops);
376	}
377
378	if (pdata->vdata->an_cdr_workaround) {
379		debugfs_create_bool("an_cdr_workaround", 0600,
380				    pdata->xgbe_debugfs,
381				    &pdata->debugfs_an_cdr_workaround);
382
383		debugfs_create_bool("an_cdr_track_early", 0600,
384				    pdata->xgbe_debugfs,
385				    &pdata->debugfs_an_cdr_track_early);
386	}
387
388	kfree(buf);
389}
390
391void xgbe_debugfs_exit(struct xgbe_prv_data *pdata)
392{
393	debugfs_remove_recursive(pdata->xgbe_debugfs);
394	pdata->xgbe_debugfs = NULL;
395}
396
397void xgbe_debugfs_rename(struct xgbe_prv_data *pdata)
398{
399	debugfs_change_name(pdata->xgbe_debugfs,
400			    "amd-xgbe-%s", pdata->netdev->name);
401}
~/ Read-only file preview.