Linux Audio

Check our new training course

Loading...
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
 
 
 
 
 
 
  3 *
  4 * Authors:
  5 * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
  6 * Copyright (c)  2015 Nordic Semiconductor. All Rights Reserved.
  7 */
  8
  9#include <net/6lowpan.h>
 10
 11#include "6lowpan_i.h"
 12
 13#define LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS	8
 14
 15static struct dentry *lowpan_debugfs;
 16
 17static int lowpan_ctx_flag_active_set(void *data, u64 val)
 18{
 19	struct lowpan_iphc_ctx *ctx = data;
 20
 21	if (val != 0 && val != 1)
 22		return -EINVAL;
 23
 24	if (val)
 25		set_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
 26	else
 27		clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
 28
 29	return 0;
 30}
 31
 32static int lowpan_ctx_flag_active_get(void *data, u64 *val)
 33{
 34	*val = lowpan_iphc_ctx_is_active(data);
 35	return 0;
 36}
 37
 38DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_active_fops,
 39			 lowpan_ctx_flag_active_get,
 40			 lowpan_ctx_flag_active_set, "%llu\n");
 41
 42static int lowpan_ctx_flag_c_set(void *data, u64 val)
 43{
 44	struct lowpan_iphc_ctx *ctx = data;
 45
 46	if (val != 0 && val != 1)
 47		return -EINVAL;
 48
 49	if (val)
 50		set_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
 51	else
 52		clear_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
 53
 54	return 0;
 55}
 56
 57static int lowpan_ctx_flag_c_get(void *data, u64 *val)
 58{
 59	*val = lowpan_iphc_ctx_is_compression(data);
 60	return 0;
 61}
 62
 63DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_flag_c_fops, lowpan_ctx_flag_c_get,
 64			 lowpan_ctx_flag_c_set, "%llu\n");
 65
 66static int lowpan_ctx_plen_set(void *data, u64 val)
 67{
 68	struct lowpan_iphc_ctx *ctx = data;
 69	struct lowpan_iphc_ctx_table *t =
 70		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
 71
 72	if (val > 128)
 73		return -EINVAL;
 74
 75	spin_lock_bh(&t->lock);
 76	ctx->plen = val;
 77	spin_unlock_bh(&t->lock);
 78
 79	return 0;
 80}
 81
 82static int lowpan_ctx_plen_get(void *data, u64 *val)
 83{
 84	struct lowpan_iphc_ctx *ctx = data;
 85	struct lowpan_iphc_ctx_table *t =
 86		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
 87
 88	spin_lock_bh(&t->lock);
 89	*val = ctx->plen;
 90	spin_unlock_bh(&t->lock);
 91	return 0;
 92}
 93
 94DEFINE_DEBUGFS_ATTRIBUTE(lowpan_ctx_plen_fops, lowpan_ctx_plen_get,
 95			 lowpan_ctx_plen_set, "%llu\n");
 96
 97static int lowpan_ctx_pfx_show(struct seq_file *file, void *offset)
 98{
 99	struct lowpan_iphc_ctx *ctx = file->private;
100	struct lowpan_iphc_ctx_table *t =
101		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
102
103	spin_lock_bh(&t->lock);
104	seq_printf(file, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
105		   be16_to_cpu(ctx->pfx.s6_addr16[0]),
106		   be16_to_cpu(ctx->pfx.s6_addr16[1]),
107		   be16_to_cpu(ctx->pfx.s6_addr16[2]),
108		   be16_to_cpu(ctx->pfx.s6_addr16[3]),
109		   be16_to_cpu(ctx->pfx.s6_addr16[4]),
110		   be16_to_cpu(ctx->pfx.s6_addr16[5]),
111		   be16_to_cpu(ctx->pfx.s6_addr16[6]),
112		   be16_to_cpu(ctx->pfx.s6_addr16[7]));
113	spin_unlock_bh(&t->lock);
114
115	return 0;
116}
117
118static int lowpan_ctx_pfx_open(struct inode *inode, struct file *file)
119{
120	return single_open(file, lowpan_ctx_pfx_show, inode->i_private);
121}
122
123static ssize_t lowpan_ctx_pfx_write(struct file *fp,
124				    const char __user *user_buf, size_t count,
125				    loff_t *ppos)
126{
127	char buf[128] = {};
128	struct seq_file *file = fp->private_data;
129	struct lowpan_iphc_ctx *ctx = file->private;
130	struct lowpan_iphc_ctx_table *t =
131		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
132	int status = count, n, i;
133	unsigned int addr[8];
134
135	if (copy_from_user(&buf, user_buf, min_t(size_t, sizeof(buf) - 1,
136						 count))) {
137		status = -EFAULT;
138		goto out;
139	}
140
141	n = sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
142		   &addr[0], &addr[1], &addr[2], &addr[3], &addr[4],
143		   &addr[5], &addr[6], &addr[7]);
144	if (n != LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS) {
145		status = -EINVAL;
146		goto out;
147	}
148
149	spin_lock_bh(&t->lock);
150	for (i = 0; i < 8; i++)
151		ctx->pfx.s6_addr16[i] = cpu_to_be16(addr[i] & 0xffff);
152	spin_unlock_bh(&t->lock);
153
154out:
155	return status;
156}
157
158static const struct file_operations lowpan_ctx_pfx_fops = {
159	.open		= lowpan_ctx_pfx_open,
160	.read		= seq_read,
161	.write		= lowpan_ctx_pfx_write,
162	.llseek		= seq_lseek,
163	.release	= single_release,
164};
165
166static void lowpan_dev_debugfs_ctx_init(struct net_device *dev,
167					struct dentry *ctx, u8 id)
168{
169	struct lowpan_dev *ldev = lowpan_dev(dev);
170	struct dentry *root;
171	char buf[32];
172
173	if (WARN_ON_ONCE(id >= LOWPAN_IPHC_CTX_TABLE_SIZE))
174		return;
175
176	sprintf(buf, "%d", id);
177
178	root = debugfs_create_dir(buf, ctx);
 
 
 
 
 
 
 
 
179
180	debugfs_create_file("active", 0644, root, &ldev->ctx.table[id],
181			    &lowpan_ctx_flag_active_fops);
 
 
 
182
183	debugfs_create_file("compression", 0644, root, &ldev->ctx.table[id],
184			    &lowpan_ctx_flag_c_fops);
 
 
 
185
186	debugfs_create_file("prefix", 0644, root, &ldev->ctx.table[id],
187			    &lowpan_ctx_pfx_fops);
 
 
 
188
189	debugfs_create_file("prefix_len", 0644, root, &ldev->ctx.table[id],
190			    &lowpan_ctx_plen_fops);
191}
192
193static int lowpan_context_show(struct seq_file *file, void *offset)
194{
195	struct lowpan_iphc_ctx_table *t = file->private;
196	int i;
197
198	seq_printf(file, "%3s|%-43s|%c\n", "cid", "prefix", 'C');
199	seq_puts(file, "-------------------------------------------------\n");
200
201	spin_lock_bh(&t->lock);
202	for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
203		if (!lowpan_iphc_ctx_is_active(&t->table[i]))
204			continue;
205
206		seq_printf(file, "%3d|%39pI6c/%-3d|%d\n", t->table[i].id,
207			   &t->table[i].pfx, t->table[i].plen,
208			   lowpan_iphc_ctx_is_compression(&t->table[i]));
209	}
210	spin_unlock_bh(&t->lock);
211
212	return 0;
213}
214DEFINE_SHOW_ATTRIBUTE(lowpan_context);
 
 
 
 
 
 
 
 
 
 
 
215
216static int lowpan_short_addr_get(void *data, u64 *val)
217{
218	struct wpan_dev *wdev = data;
219
220	rtnl_lock();
221	*val = le16_to_cpu(wdev->short_addr);
222	rtnl_unlock();
223
224	return 0;
225}
226
227DEFINE_DEBUGFS_ATTRIBUTE(lowpan_short_addr_fops, lowpan_short_addr_get, NULL,
228			 "0x%04llx\n");
229
230static void lowpan_dev_debugfs_802154_init(const struct net_device *dev,
231					  struct lowpan_dev *ldev)
232{
233	struct dentry *root;
234
235	if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
236		return;
237
238	root = debugfs_create_dir("ieee802154", ldev->iface_debugfs);
 
 
 
 
 
 
 
 
239
240	debugfs_create_file("short_addr", 0444, root,
241			    lowpan_802154_dev(dev)->wdev->ieee802154_ptr,
242			    &lowpan_short_addr_fops);
243}
244
245void lowpan_dev_debugfs_init(struct net_device *dev)
246{
247	struct lowpan_dev *ldev = lowpan_dev(dev);
248	struct dentry *contexts;
249	int i;
250
251	/* creating the root */
252	ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs);
 
 
253
254	contexts = debugfs_create_dir("contexts", ldev->iface_debugfs);
 
 
 
 
 
 
 
 
255
256	debugfs_create_file("show", 0644, contexts, &lowpan_dev(dev)->ctx,
257			    &lowpan_context_fops);
 
 
 
258
259	for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
260		lowpan_dev_debugfs_ctx_init(dev, contexts, i);
 
 
 
261
262	lowpan_dev_debugfs_802154_init(dev, ldev);
 
 
 
263}
264
265void lowpan_dev_debugfs_exit(struct net_device *dev)
266{
267	debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs);
268}
269
270void __init lowpan_debugfs_init(void)
271{
272	lowpan_debugfs = debugfs_create_dir("6lowpan", NULL);
 
 
 
 
273}
274
275void lowpan_debugfs_exit(void)
276{
277	debugfs_remove_recursive(lowpan_debugfs);
278}
v4.10.11
  1/* This program is free software; you can redistribute it and/or modify
  2 * it under the terms of the GNU General Public License version 2
  3 * as published by the Free Software Foundation.
  4 *
  5 * This program is distributed in the hope that it will be useful,
  6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8 * GNU General Public License for more details.
  9 *
 10 * Authors:
 11 * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
 12 * Copyright (c)  2015 Nordic Semiconductor. All Rights Reserved.
 13 */
 14
 15#include <net/6lowpan.h>
 16
 17#include "6lowpan_i.h"
 18
 19#define LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS	8
 20
 21static struct dentry *lowpan_debugfs;
 22
 23static int lowpan_ctx_flag_active_set(void *data, u64 val)
 24{
 25	struct lowpan_iphc_ctx *ctx = data;
 26
 27	if (val != 0 && val != 1)
 28		return -EINVAL;
 29
 30	if (val)
 31		set_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
 32	else
 33		clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE, &ctx->flags);
 34
 35	return 0;
 36}
 37
 38static int lowpan_ctx_flag_active_get(void *data, u64 *val)
 39{
 40	*val = lowpan_iphc_ctx_is_active(data);
 41	return 0;
 42}
 43
 44DEFINE_SIMPLE_ATTRIBUTE(lowpan_ctx_flag_active_fops,
 45			lowpan_ctx_flag_active_get,
 46			lowpan_ctx_flag_active_set, "%llu\n");
 47
 48static int lowpan_ctx_flag_c_set(void *data, u64 val)
 49{
 50	struct lowpan_iphc_ctx *ctx = data;
 51
 52	if (val != 0 && val != 1)
 53		return -EINVAL;
 54
 55	if (val)
 56		set_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
 57	else
 58		clear_bit(LOWPAN_IPHC_CTX_FLAG_COMPRESSION, &ctx->flags);
 59
 60	return 0;
 61}
 62
 63static int lowpan_ctx_flag_c_get(void *data, u64 *val)
 64{
 65	*val = lowpan_iphc_ctx_is_compression(data);
 66	return 0;
 67}
 68
 69DEFINE_SIMPLE_ATTRIBUTE(lowpan_ctx_flag_c_fops, lowpan_ctx_flag_c_get,
 70			lowpan_ctx_flag_c_set, "%llu\n");
 71
 72static int lowpan_ctx_plen_set(void *data, u64 val)
 73{
 74	struct lowpan_iphc_ctx *ctx = data;
 75	struct lowpan_iphc_ctx_table *t =
 76		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
 77
 78	if (val > 128)
 79		return -EINVAL;
 80
 81	spin_lock_bh(&t->lock);
 82	ctx->plen = val;
 83	spin_unlock_bh(&t->lock);
 84
 85	return 0;
 86}
 87
 88static int lowpan_ctx_plen_get(void *data, u64 *val)
 89{
 90	struct lowpan_iphc_ctx *ctx = data;
 91	struct lowpan_iphc_ctx_table *t =
 92		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
 93
 94	spin_lock_bh(&t->lock);
 95	*val = ctx->plen;
 96	spin_unlock_bh(&t->lock);
 97	return 0;
 98}
 99
100DEFINE_SIMPLE_ATTRIBUTE(lowpan_ctx_plen_fops, lowpan_ctx_plen_get,
101			lowpan_ctx_plen_set, "%llu\n");
102
103static int lowpan_ctx_pfx_show(struct seq_file *file, void *offset)
104{
105	struct lowpan_iphc_ctx *ctx = file->private;
106	struct lowpan_iphc_ctx_table *t =
107		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
108
109	spin_lock_bh(&t->lock);
110	seq_printf(file, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
111		   be16_to_cpu(ctx->pfx.s6_addr16[0]),
112		   be16_to_cpu(ctx->pfx.s6_addr16[1]),
113		   be16_to_cpu(ctx->pfx.s6_addr16[2]),
114		   be16_to_cpu(ctx->pfx.s6_addr16[3]),
115		   be16_to_cpu(ctx->pfx.s6_addr16[4]),
116		   be16_to_cpu(ctx->pfx.s6_addr16[5]),
117		   be16_to_cpu(ctx->pfx.s6_addr16[6]),
118		   be16_to_cpu(ctx->pfx.s6_addr16[7]));
119	spin_unlock_bh(&t->lock);
120
121	return 0;
122}
123
124static int lowpan_ctx_pfx_open(struct inode *inode, struct file *file)
125{
126	return single_open(file, lowpan_ctx_pfx_show, inode->i_private);
127}
128
129static ssize_t lowpan_ctx_pfx_write(struct file *fp,
130				    const char __user *user_buf, size_t count,
131				    loff_t *ppos)
132{
133	char buf[128] = {};
134	struct seq_file *file = fp->private_data;
135	struct lowpan_iphc_ctx *ctx = file->private;
136	struct lowpan_iphc_ctx_table *t =
137		container_of(ctx, struct lowpan_iphc_ctx_table, table[ctx->id]);
138	int status = count, n, i;
139	unsigned int addr[8];
140
141	if (copy_from_user(&buf, user_buf, min_t(size_t, sizeof(buf) - 1,
142						 count))) {
143		status = -EFAULT;
144		goto out;
145	}
146
147	n = sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
148		   &addr[0], &addr[1], &addr[2], &addr[3], &addr[4],
149		   &addr[5], &addr[6], &addr[7]);
150	if (n != LOWPAN_DEBUGFS_CTX_PFX_NUM_ARGS) {
151		status = -EINVAL;
152		goto out;
153	}
154
155	spin_lock_bh(&t->lock);
156	for (i = 0; i < 8; i++)
157		ctx->pfx.s6_addr16[i] = cpu_to_be16(addr[i] & 0xffff);
158	spin_unlock_bh(&t->lock);
159
160out:
161	return status;
162}
163
164static const struct file_operations lowpan_ctx_pfx_fops = {
165	.open		= lowpan_ctx_pfx_open,
166	.read		= seq_read,
167	.write		= lowpan_ctx_pfx_write,
168	.llseek		= seq_lseek,
169	.release	= single_release,
170};
171
172static int lowpan_dev_debugfs_ctx_init(struct net_device *dev,
173				       struct dentry *ctx, u8 id)
174{
175	struct lowpan_dev *ldev = lowpan_dev(dev);
176	struct dentry *dentry, *root;
177	char buf[32];
178
179	WARN_ON_ONCE(id > LOWPAN_IPHC_CTX_TABLE_SIZE);
 
180
181	sprintf(buf, "%d", id);
182
183	root = debugfs_create_dir(buf, ctx);
184	if (!root)
185		return -EINVAL;
186
187	dentry = debugfs_create_file("active", 0644, root,
188				     &ldev->ctx.table[id],
189				     &lowpan_ctx_flag_active_fops);
190	if (!dentry)
191		return -EINVAL;
192
193	dentry = debugfs_create_file("compression", 0644, root,
194				     &ldev->ctx.table[id],
195				     &lowpan_ctx_flag_c_fops);
196	if (!dentry)
197		return -EINVAL;
198
199	dentry = debugfs_create_file("prefix", 0644, root,
200				     &ldev->ctx.table[id],
201				     &lowpan_ctx_pfx_fops);
202	if (!dentry)
203		return -EINVAL;
204
205	dentry = debugfs_create_file("prefix_len", 0644, root,
206				     &ldev->ctx.table[id],
207				     &lowpan_ctx_plen_fops);
208	if (!dentry)
209		return -EINVAL;
210
211	return 0;
 
212}
213
214static int lowpan_context_show(struct seq_file *file, void *offset)
215{
216	struct lowpan_iphc_ctx_table *t = file->private;
217	int i;
218
219	seq_printf(file, "%3s|%-43s|%c\n", "cid", "prefix", 'C');
220	seq_puts(file, "-------------------------------------------------\n");
221
222	spin_lock_bh(&t->lock);
223	for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
224		if (!lowpan_iphc_ctx_is_active(&t->table[i]))
225			continue;
226
227		seq_printf(file, "%3d|%39pI6c/%-3d|%d\n", t->table[i].id,
228			   &t->table[i].pfx, t->table[i].plen,
229			   lowpan_iphc_ctx_is_compression(&t->table[i]));
230	}
231	spin_unlock_bh(&t->lock);
232
233	return 0;
234}
235
236static int lowpan_context_open(struct inode *inode, struct file *file)
237{
238	return single_open(file, lowpan_context_show, inode->i_private);
239}
240
241static const struct file_operations lowpan_context_fops = {
242	.open		= lowpan_context_open,
243	.read		= seq_read,
244	.llseek		= seq_lseek,
245	.release	= single_release,
246};
247
248static int lowpan_short_addr_get(void *data, u64 *val)
249{
250	struct wpan_dev *wdev = data;
251
252	rtnl_lock();
253	*val = le16_to_cpu(wdev->short_addr);
254	rtnl_unlock();
255
256	return 0;
257}
258
259DEFINE_SIMPLE_ATTRIBUTE(lowpan_short_addr_fops, lowpan_short_addr_get,
260			NULL, "0x%04llx\n");
261
262static int lowpan_dev_debugfs_802154_init(const struct net_device *dev,
263					  struct lowpan_dev *ldev)
264{
265	struct dentry *dentry, *root;
266
267	if (!lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154))
268		return 0;
269
270	root = debugfs_create_dir("ieee802154", ldev->iface_debugfs);
271	if (!root)
272		return -EINVAL;
273
274	dentry = debugfs_create_file("short_addr", 0444, root,
275				     lowpan_802154_dev(dev)->wdev->ieee802154_ptr,
276				     &lowpan_short_addr_fops);
277	if (!dentry)
278		return -EINVAL;
279
280	return 0;
 
 
281}
282
283int lowpan_dev_debugfs_init(struct net_device *dev)
284{
285	struct lowpan_dev *ldev = lowpan_dev(dev);
286	struct dentry *contexts, *dentry;
287	int ret, i;
288
289	/* creating the root */
290	ldev->iface_debugfs = debugfs_create_dir(dev->name, lowpan_debugfs);
291	if (!ldev->iface_debugfs)
292		goto fail;
293
294	contexts = debugfs_create_dir("contexts", ldev->iface_debugfs);
295	if (!contexts)
296		goto remove_root;
297
298	dentry = debugfs_create_file("show", 0644, contexts,
299				     &lowpan_dev(dev)->ctx,
300				     &lowpan_context_fops);
301	if (!dentry)
302		goto remove_root;
303
304	for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++) {
305		ret = lowpan_dev_debugfs_ctx_init(dev, contexts, i);
306		if (ret < 0)
307			goto remove_root;
308	}
309
310	ret = lowpan_dev_debugfs_802154_init(dev, ldev);
311	if (ret < 0)
312		goto remove_root;
313
314	return 0;
315
316remove_root:
317	lowpan_dev_debugfs_exit(dev);
318fail:
319	return -EINVAL;
320}
321
322void lowpan_dev_debugfs_exit(struct net_device *dev)
323{
324	debugfs_remove_recursive(lowpan_dev(dev)->iface_debugfs);
325}
326
327int __init lowpan_debugfs_init(void)
328{
329	lowpan_debugfs = debugfs_create_dir("6lowpan", NULL);
330	if (!lowpan_debugfs)
331		return -EINVAL;
332
333	return 0;
334}
335
336void lowpan_debugfs_exit(void)
337{
338	debugfs_remove_recursive(lowpan_debugfs);
339}