5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include <linux/spinlock.h>
27 #include <linux/module.h>
28 #include <linux/slab.h>
29 #include <linux/notifier.h>
30 #include <linux/device.h>
31 #include <linux/debugfs.h>
32 #include <linux/uaccess.h>
33 #include <linux/seq_file.h>
35 #include <linux/uwb/debug-cmd.h>
37 #include <linux/uwb/debug.h>
39 #include "uwb-internal.h"
41 void dump_bytes(struct device
*dev
, const void *_buf
, size_t rsize
)
43 const char *buf
= _buf
;
47 for (cnt
= 0; cnt
< rsize
; cnt
+= 8) {
48 size_t rtop
= rsize
- cnt
< 8 ? rsize
- cnt
: 8;
49 for (offset
= cnt2
= 0; cnt2
< rtop
; cnt2
++) {
50 offset
+= scnprintf(line
+ offset
, sizeof(line
) - offset
,
51 "%02x ", buf
[cnt
+ cnt2
] & 0xff);
54 dev_info(dev
, "%s\n", line
);
56 printk(KERN_INFO
"%s\n", line
);
59 EXPORT_SYMBOL_GPL(dump_bytes
);
64 * Per radio controller debugfs files (in uwb/uwbN/):
66 * command: Flexible command interface (see <linux/uwb/debug-cmd.h>).
68 * reservations: information on reservations.
70 * accept: Set to true (Y or 1) to accept reservation requests from
73 * drp_avail: DRP availability information.
80 struct list_head rsvs
;
82 struct dentry
*root_d
;
83 struct dentry
*command_f
;
84 struct dentry
*reservations_f
;
85 struct dentry
*accept_f
;
86 struct dentry
*drp_avail_f
;
89 static struct dentry
*root_dir
;
91 static void uwb_dbg_rsv_cb(struct uwb_rsv
*rsv
)
93 struct uwb_rc
*rc
= rsv
->rc
;
94 struct device
*dev
= &rc
->uwb_dev
.dev
;
95 struct uwb_dev_addr devaddr
;
96 char owner
[UWB_ADDR_STRSIZE
], target
[UWB_ADDR_STRSIZE
];
98 uwb_dev_addr_print(owner
, sizeof(owner
), &rsv
->owner
->dev_addr
);
99 if (rsv
->target
.type
== UWB_RSV_TARGET_DEV
)
100 devaddr
= rsv
->target
.dev
->dev_addr
;
102 devaddr
= rsv
->target
.devaddr
;
103 uwb_dev_addr_print(target
, sizeof(target
), &devaddr
);
105 dev_dbg(dev
, "debug: rsv %s -> %s: %s\n",
106 owner
, target
, uwb_rsv_state_str(rsv
->state
));
109 static int cmd_rsv_establish(struct uwb_rc
*rc
,
110 struct uwb_dbg_cmd_rsv_establish
*cmd
)
112 struct uwb_mac_addr macaddr
;
114 struct uwb_dev
*target
;
117 memcpy(&macaddr
, cmd
->target
, sizeof(macaddr
));
118 target
= uwb_dev_get_by_macaddr(rc
, &macaddr
);
122 rsv
= uwb_rsv_create(rc
, uwb_dbg_rsv_cb
, NULL
);
128 rsv
->owner
= &rc
->uwb_dev
;
129 rsv
->target
.type
= UWB_RSV_TARGET_DEV
;
130 rsv
->target
.dev
= target
;
131 rsv
->type
= cmd
->type
;
132 rsv
->max_mas
= cmd
->max_mas
;
133 rsv
->min_mas
= cmd
->min_mas
;
134 rsv
->sparsity
= cmd
->sparsity
;
136 ret
= uwb_rsv_establish(rsv
);
138 uwb_rsv_destroy(rsv
);
140 list_add_tail(&rsv
->pal_node
, &rc
->dbg
->rsvs
);
145 static int cmd_rsv_terminate(struct uwb_rc
*rc
,
146 struct uwb_dbg_cmd_rsv_terminate
*cmd
)
148 struct uwb_rsv
*rsv
, *found
= NULL
;
151 list_for_each_entry(rsv
, &rc
->dbg
->rsvs
, pal_node
) {
152 if (i
== cmd
->index
) {
160 list_del(&found
->pal_node
);
161 uwb_rsv_terminate(found
);
166 static int command_open(struct inode
*inode
, struct file
*file
)
168 file
->private_data
= inode
->i_private
;
173 static ssize_t
command_write(struct file
*file
, const char __user
*buf
,
174 size_t len
, loff_t
*off
)
176 struct uwb_rc
*rc
= file
->private_data
;
177 struct uwb_dbg_cmd cmd
;
180 if (len
!= sizeof(struct uwb_dbg_cmd
))
183 if (copy_from_user(&cmd
, buf
, len
) != 0)
187 case UWB_DBG_CMD_RSV_ESTABLISH
:
188 ret
= cmd_rsv_establish(rc
, &cmd
.rsv_establish
);
190 case UWB_DBG_CMD_RSV_TERMINATE
:
191 ret
= cmd_rsv_terminate(rc
, &cmd
.rsv_terminate
);
197 return ret
< 0 ? ret
: len
;
200 static struct file_operations command_fops
= {
201 .open
= command_open
,
202 .write
= command_write
,
205 .owner
= THIS_MODULE
,
208 static int reservations_print(struct seq_file
*s
, void *p
)
210 struct uwb_rc
*rc
= s
->private;
213 mutex_lock(&rc
->rsvs_mutex
);
215 list_for_each_entry(rsv
, &rc
->reservations
, rc_node
) {
216 struct uwb_dev_addr devaddr
;
217 char owner
[UWB_ADDR_STRSIZE
], target
[UWB_ADDR_STRSIZE
];
221 uwb_dev_addr_print(owner
, sizeof(owner
), &rsv
->owner
->dev_addr
);
222 if (rsv
->target
.type
== UWB_RSV_TARGET_DEV
) {
223 devaddr
= rsv
->target
.dev
->dev_addr
;
224 is_owner
= &rc
->uwb_dev
== rsv
->owner
;
226 devaddr
= rsv
->target
.devaddr
;
229 uwb_dev_addr_print(target
, sizeof(target
), &devaddr
);
231 seq_printf(s
, "%c %s -> %s: %s\n",
232 is_owner
? 'O' : 'T',
233 owner
, target
, uwb_rsv_state_str(rsv
->state
));
234 seq_printf(s
, " stream: %d type: %s\n",
235 rsv
->stream
, uwb_rsv_type_str(rsv
->type
));
236 bitmap_scnprintf(buf
, sizeof(buf
), rsv
->mas
.bm
, UWB_NUM_MAS
);
237 seq_printf(s
, " %s\n", buf
);
240 mutex_unlock(&rc
->rsvs_mutex
);
245 static int reservations_open(struct inode
*inode
, struct file
*file
)
247 return single_open(file
, reservations_print
, inode
->i_private
);
250 static struct file_operations reservations_fops
= {
251 .open
= reservations_open
,
254 .release
= single_release
,
255 .owner
= THIS_MODULE
,
258 static int drp_avail_print(struct seq_file
*s
, void *p
)
260 struct uwb_rc
*rc
= s
->private;
263 bitmap_scnprintf(buf
, sizeof(buf
), rc
->drp_avail
.global
, UWB_NUM_MAS
);
264 seq_printf(s
, "global: %s\n", buf
);
265 bitmap_scnprintf(buf
, sizeof(buf
), rc
->drp_avail
.local
, UWB_NUM_MAS
);
266 seq_printf(s
, "local: %s\n", buf
);
267 bitmap_scnprintf(buf
, sizeof(buf
), rc
->drp_avail
.pending
, UWB_NUM_MAS
);
268 seq_printf(s
, "pending: %s\n", buf
);
273 static int drp_avail_open(struct inode
*inode
, struct file
*file
)
275 return single_open(file
, drp_avail_print
, inode
->i_private
);
278 static struct file_operations drp_avail_fops
= {
279 .open
= drp_avail_open
,
282 .release
= single_release
,
283 .owner
= THIS_MODULE
,
286 static void uwb_dbg_new_rsv(struct uwb_rsv
*rsv
)
288 struct uwb_rc
*rc
= rsv
->rc
;
291 uwb_rsv_accept(rsv
, uwb_dbg_rsv_cb
, NULL
);
295 * uwb_dbg_add_rc - add a debug interface for a radio controller
296 * @rc: the radio controller
298 void uwb_dbg_add_rc(struct uwb_rc
*rc
)
300 rc
->dbg
= kzalloc(sizeof(struct uwb_dbg
), GFP_KERNEL
);
304 INIT_LIST_HEAD(&rc
->dbg
->rsvs
);
306 uwb_pal_init(&rc
->dbg
->pal
);
307 rc
->dbg
->pal
.new_rsv
= uwb_dbg_new_rsv
;
308 uwb_pal_register(rc
, &rc
->dbg
->pal
);
310 rc
->dbg
->root_d
= debugfs_create_dir(dev_name(&rc
->uwb_dev
.dev
),
312 rc
->dbg
->command_f
= debugfs_create_file("command", 0200,
315 rc
->dbg
->reservations_f
= debugfs_create_file("reservations", 0444,
318 rc
->dbg
->accept_f
= debugfs_create_bool("accept", 0644,
321 rc
->dbg
->drp_avail_f
= debugfs_create_file("drp_avail", 0444,
328 * uwb_dbg_add_rc - remove a radio controller's debug interface
329 * @rc: the radio controller
331 void uwb_dbg_del_rc(struct uwb_rc
*rc
)
333 struct uwb_rsv
*rsv
, *t
;
338 list_for_each_entry_safe(rsv
, t
, &rc
->dbg
->rsvs
, pal_node
) {
339 uwb_rsv_destroy(rsv
);
342 uwb_pal_unregister(rc
, &rc
->dbg
->pal
);
345 debugfs_remove(rc
->dbg
->drp_avail_f
);
346 debugfs_remove(rc
->dbg
->accept_f
);
347 debugfs_remove(rc
->dbg
->reservations_f
);
348 debugfs_remove(rc
->dbg
->command_f
);
349 debugfs_remove(rc
->dbg
->root_d
);
354 * uwb_dbg_exit - initialize the debug interface sub-module
356 void uwb_dbg_init(void)
358 root_dir
= debugfs_create_dir("uwb", NULL
);
362 * uwb_dbg_exit - clean-up the debug interface sub-module
364 void uwb_dbg_exit(void)
366 debugfs_remove(root_dir
);