5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
7 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version
11 * 2 as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include <linux/spinlock.h>
28 #include <linux/module.h>
29 #include <linux/slab.h>
30 #include <linux/notifier.h>
31 #include <linux/device.h>
32 #include <linux/debugfs.h>
33 #include <linux/uaccess.h>
34 #include <linux/seq_file.h>
36 #include <linux/uwb/debug-cmd.h>
38 #include "uwb-internal.h"
43 * Per radio controller debugfs files (in uwb/uwbN/):
45 * command: Flexible command interface (see <linux/uwb/debug-cmd.h>).
47 * reservations: information on reservations.
49 * accept: Set to true (Y or 1) to accept reservation requests from
52 * drp_avail: DRP availability information.
59 struct list_head rsvs
;
61 struct dentry
*root_d
;
62 struct dentry
*command_f
;
63 struct dentry
*reservations_f
;
64 struct dentry
*accept_f
;
65 struct dentry
*drp_avail_f
;
69 static struct dentry
*root_dir
;
71 static void uwb_dbg_rsv_cb(struct uwb_rsv
*rsv
)
73 struct uwb_dbg
*dbg
= rsv
->pal_priv
;
75 uwb_rsv_dump("debug", rsv
);
77 if (rsv
->state
== UWB_RSV_STATE_NONE
) {
78 spin_lock(&dbg
->list_lock
);
79 list_del(&rsv
->pal_node
);
80 spin_unlock(&dbg
->list_lock
);
85 static int cmd_rsv_establish(struct uwb_rc
*rc
,
86 struct uwb_dbg_cmd_rsv_establish
*cmd
)
88 struct uwb_mac_addr macaddr
;
90 struct uwb_dev
*target
;
93 memcpy(&macaddr
, cmd
->target
, sizeof(macaddr
));
94 target
= uwb_dev_get_by_macaddr(rc
, &macaddr
);
98 rsv
= uwb_rsv_create(rc
, uwb_dbg_rsv_cb
, rc
->dbg
);
104 rsv
->target
.type
= UWB_RSV_TARGET_DEV
;
105 rsv
->target
.dev
= target
;
106 rsv
->type
= cmd
->type
;
107 rsv
->max_mas
= cmd
->max_mas
;
108 rsv
->min_mas
= cmd
->min_mas
;
109 rsv
->max_interval
= cmd
->max_interval
;
111 ret
= uwb_rsv_establish(rsv
);
113 uwb_rsv_destroy(rsv
);
115 spin_lock(&(rc
->dbg
)->list_lock
);
116 list_add_tail(&rsv
->pal_node
, &rc
->dbg
->rsvs
);
117 spin_unlock(&(rc
->dbg
)->list_lock
);
122 static int cmd_rsv_terminate(struct uwb_rc
*rc
,
123 struct uwb_dbg_cmd_rsv_terminate
*cmd
)
125 struct uwb_rsv
*rsv
, *found
= NULL
;
128 spin_lock(&(rc
->dbg
)->list_lock
);
130 list_for_each_entry(rsv
, &rc
->dbg
->rsvs
, pal_node
) {
131 if (i
== cmd
->index
) {
139 spin_unlock(&(rc
->dbg
)->list_lock
);
144 uwb_rsv_terminate(found
);
150 static int cmd_ie_add(struct uwb_rc
*rc
, struct uwb_dbg_cmd_ie
*ie_to_add
)
152 return uwb_rc_ie_add(rc
,
153 (const struct uwb_ie_hdr
*) ie_to_add
->data
,
157 static int cmd_ie_rm(struct uwb_rc
*rc
, struct uwb_dbg_cmd_ie
*ie_to_rm
)
159 return uwb_rc_ie_rm(rc
, ie_to_rm
->data
[0]);
162 static ssize_t
command_write(struct file
*file
, const char __user
*buf
,
163 size_t len
, loff_t
*off
)
165 struct uwb_rc
*rc
= file
->private_data
;
166 struct uwb_dbg_cmd cmd
;
169 if (len
!= sizeof(struct uwb_dbg_cmd
))
172 if (copy_from_user(&cmd
, buf
, len
) != 0)
176 case UWB_DBG_CMD_RSV_ESTABLISH
:
177 ret
= cmd_rsv_establish(rc
, &cmd
.rsv_establish
);
179 case UWB_DBG_CMD_RSV_TERMINATE
:
180 ret
= cmd_rsv_terminate(rc
, &cmd
.rsv_terminate
);
182 case UWB_DBG_CMD_IE_ADD
:
183 ret
= cmd_ie_add(rc
, &cmd
.ie_add
);
185 case UWB_DBG_CMD_IE_RM
:
186 ret
= cmd_ie_rm(rc
, &cmd
.ie_rm
);
188 case UWB_DBG_CMD_RADIO_START
:
189 ret
= uwb_radio_start(&rc
->dbg
->pal
);
191 case UWB_DBG_CMD_RADIO_STOP
:
192 uwb_radio_stop(&rc
->dbg
->pal
);
198 return ret
< 0 ? ret
: len
;
201 static const struct file_operations command_fops
= {
203 .write
= command_write
,
206 .owner
= THIS_MODULE
,
209 static int reservations_show(struct seq_file
*s
, void *p
)
211 struct uwb_rc
*rc
= s
->private;
214 mutex_lock(&rc
->rsvs_mutex
);
216 list_for_each_entry(rsv
, &rc
->reservations
, rc_node
) {
217 struct uwb_dev_addr devaddr
;
218 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 seq_printf(s
, " %*pb\n", UWB_NUM_MAS
, rsv
->mas
.bm
);
239 mutex_unlock(&rc
->rsvs_mutex
);
243 DEFINE_SHOW_ATTRIBUTE(reservations
);
245 static int drp_avail_show(struct seq_file
*s
, void *p
)
247 struct uwb_rc
*rc
= s
->private;
249 seq_printf(s
, "global: %*pb\n", UWB_NUM_MAS
, rc
->drp_avail
.global
);
250 seq_printf(s
, "local: %*pb\n", UWB_NUM_MAS
, rc
->drp_avail
.local
);
251 seq_printf(s
, "pending: %*pb\n", UWB_NUM_MAS
, rc
->drp_avail
.pending
);
255 DEFINE_SHOW_ATTRIBUTE(drp_avail
);
257 static void uwb_dbg_channel_changed(struct uwb_pal
*pal
, int channel
)
259 struct device
*dev
= &pal
->rc
->uwb_dev
.dev
;
262 dev_info(dev
, "debug: channel %d started\n", channel
);
264 dev_info(dev
, "debug: channel stopped\n");
267 static void uwb_dbg_new_rsv(struct uwb_pal
*pal
, struct uwb_rsv
*rsv
)
269 struct uwb_dbg
*dbg
= container_of(pal
, struct uwb_dbg
, pal
);
272 spin_lock(&dbg
->list_lock
);
273 list_add_tail(&rsv
->pal_node
, &dbg
->rsvs
);
274 spin_unlock(&dbg
->list_lock
);
275 uwb_rsv_accept(rsv
, uwb_dbg_rsv_cb
, dbg
);
280 * uwb_dbg_add_rc - add a debug interface for a radio controller
281 * @rc: the radio controller
283 void uwb_dbg_add_rc(struct uwb_rc
*rc
)
285 rc
->dbg
= kzalloc(sizeof(struct uwb_dbg
), GFP_KERNEL
);
289 INIT_LIST_HEAD(&rc
->dbg
->rsvs
);
290 spin_lock_init(&(rc
->dbg
)->list_lock
);
292 uwb_pal_init(&rc
->dbg
->pal
);
293 rc
->dbg
->pal
.rc
= rc
;
294 rc
->dbg
->pal
.channel_changed
= uwb_dbg_channel_changed
;
295 rc
->dbg
->pal
.new_rsv
= uwb_dbg_new_rsv
;
296 uwb_pal_register(&rc
->dbg
->pal
);
299 rc
->dbg
->root_d
= debugfs_create_dir(dev_name(&rc
->uwb_dev
.dev
),
301 rc
->dbg
->command_f
= debugfs_create_file("command", 0200,
304 rc
->dbg
->reservations_f
= debugfs_create_file("reservations", 0444,
307 rc
->dbg
->accept_f
= debugfs_create_bool("accept", 0644,
310 rc
->dbg
->drp_avail_f
= debugfs_create_file("drp_avail", 0444,
317 * uwb_dbg_del_rc - remove a radio controller's debug interface
318 * @rc: the radio controller
320 void uwb_dbg_del_rc(struct uwb_rc
*rc
)
322 struct uwb_rsv
*rsv
, *t
;
327 list_for_each_entry_safe(rsv
, t
, &rc
->dbg
->rsvs
, pal_node
) {
328 uwb_rsv_terminate(rsv
);
331 uwb_pal_unregister(&rc
->dbg
->pal
);
334 debugfs_remove(rc
->dbg
->drp_avail_f
);
335 debugfs_remove(rc
->dbg
->accept_f
);
336 debugfs_remove(rc
->dbg
->reservations_f
);
337 debugfs_remove(rc
->dbg
->command_f
);
338 debugfs_remove(rc
->dbg
->root_d
);
343 * uwb_dbg_exit - initialize the debug interface sub-module
345 void uwb_dbg_init(void)
347 root_dir
= debugfs_create_dir("uwb", NULL
);
351 * uwb_dbg_exit - clean-up the debug interface sub-module
353 void uwb_dbg_exit(void)
355 debugfs_remove(root_dir
);
359 * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL
362 struct dentry
*uwb_dbg_create_pal_dir(struct uwb_pal
*pal
)
364 struct uwb_rc
*rc
= pal
->rc
;
366 if (root_dir
&& rc
->dbg
&& rc
->dbg
->root_d
&& pal
->name
)
367 return debugfs_create_dir(pal
->name
, rc
->dbg
->root_d
);