1599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/* 2599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Ultra Wide Band 3599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Debug support 4599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 5599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Copyright (C) 2005-2006 Intel Corporation 6599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 7e43ace891229607c43d35597cbba77c2e40f48d4David Vrabel * Copyright (C) 2008 Cambridge Silicon Radio Ltd. 8599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 9599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * This program is free software; you can redistribute it and/or 10599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * modify it under the terms of the GNU General Public License version 11599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 2 as published by the Free Software Foundation. 12599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 13599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * This program is distributed in the hope that it will be useful, 14599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * but WITHOUT ANY WARRANTY; without even the implied warranty of 15599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * GNU General Public License for more details. 17599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 18599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * You should have received a copy of the GNU General Public License 19599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * along with this program; if not, write to the Free Software 20599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 02110-1301, USA. 22599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 23599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 24599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * FIXME: doc 25599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 26599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 27599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/spinlock.h> 28599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/module.h> 29599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/slab.h> 30599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/notifier.h> 31599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/device.h> 32599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/debugfs.h> 33599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/uaccess.h> 34599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/seq_file.h> 35599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 36599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include <linux/uwb/debug-cmd.h> 37599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 38599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel#include "uwb-internal.h" 39599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 40599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/* 41599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Debug interface 42599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 43599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * Per radio controller debugfs files (in uwb/uwbN/): 44599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 45599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * command: Flexible command interface (see <linux/uwb/debug-cmd.h>). 46599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 47599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * reservations: information on reservations. 48599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 49599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * accept: Set to true (Y or 1) to accept reservation requests from 50599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * peers. 51599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * 52599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * drp_avail: DRP availability information. 53599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 54599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 55599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstruct uwb_dbg { 56599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_pal pal; 57599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 58599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel u32 accept; 59599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct list_head rsvs; 60599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 61599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct dentry *root_d; 62599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct dentry *command_f; 63599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct dentry *reservations_f; 64599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct dentry *accept_f; 65599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct dentry *drp_avail_f; 665b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spinlock_t list_lock; 67599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel}; 68599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 69599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic struct dentry *root_dir; 70599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 71599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic void uwb_dbg_rsv_cb(struct uwb_rsv *rsv) 72599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 735b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella struct uwb_dbg *dbg = rsv->pal_priv; 74599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 755b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella uwb_rsv_dump("debug", rsv); 76cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel 77cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel if (rsv->state == UWB_RSV_STATE_NONE) { 785b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_lock(&dbg->list_lock); 79cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel list_del(&rsv->pal_node); 805b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_unlock(&dbg->list_lock); 81cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel uwb_rsv_destroy(rsv); 82cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel } 83599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 84599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 85599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int cmd_rsv_establish(struct uwb_rc *rc, 86599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_dbg_cmd_rsv_establish *cmd) 87599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 88599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_mac_addr macaddr; 89599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rsv *rsv; 90599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_dev *target; 91599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel int ret; 92599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 93599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel memcpy(&macaddr, cmd->target, sizeof(macaddr)); 94599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel target = uwb_dev_get_by_macaddr(rc, &macaddr); 95599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (target == NULL) 96599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -ENODEV; 97599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 98e4b49580f70380a4216ff8220c8f48a95e21c238David Vrabel rsv = uwb_rsv_create(rc, uwb_dbg_rsv_cb, rc->dbg); 99599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (rsv == NULL) { 100599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_dev_put(target); 101599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -ENOMEM; 102599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 103599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 1045b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->target.type = UWB_RSV_TARGET_DEV; 1055b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->target.dev = target; 1065b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->type = cmd->type; 1075b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->max_mas = cmd->max_mas; 1085b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->min_mas = cmd->min_mas; 1095b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella rsv->max_interval = cmd->max_interval; 110599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 111599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel ret = uwb_rsv_establish(rsv); 112599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (ret) 113599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_rsv_destroy(rsv); 1145b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella else { 1155b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_lock(&(rc->dbg)->list_lock); 116599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel list_add_tail(&rsv->pal_node, &rc->dbg->rsvs); 1175b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_unlock(&(rc->dbg)->list_lock); 1185b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella } 119599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return ret; 120599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 121599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 122599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int cmd_rsv_terminate(struct uwb_rc *rc, 123599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_dbg_cmd_rsv_terminate *cmd) 124599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 125599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rsv *rsv, *found = NULL; 126599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel int i = 0; 127599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 1285b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_lock(&(rc->dbg)->list_lock); 1295b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella 130599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel list_for_each_entry(rsv, &rc->dbg->rsvs, pal_node) { 131599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (i == cmd->index) { 132599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel found = rsv; 1335b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella uwb_rsv_get(found); 134599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel break; 135599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 136cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel i++; 137599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 1385b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella 1395b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_unlock(&(rc->dbg)->list_lock); 1405b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella 141599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (!found) 142599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -EINVAL; 143599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 144599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_rsv_terminate(found); 1455b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella uwb_rsv_put(found); 146599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 147599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return 0; 148599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 149599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 1506d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panellastatic int cmd_ie_add(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_add) 1516d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella{ 1526d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella return uwb_rc_ie_add(rc, 1536d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella (const struct uwb_ie_hdr *) ie_to_add->data, 1546d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella ie_to_add->len); 1556d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella} 1566d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella 1576d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panellastatic int cmd_ie_rm(struct uwb_rc *rc, struct uwb_dbg_cmd_ie *ie_to_rm) 1586d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella{ 1596d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella return uwb_rc_ie_rm(rc, ie_to_rm->data[0]); 1606d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella} 1616d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella 162599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic ssize_t command_write(struct file *file, const char __user *buf, 163599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel size_t len, loff_t *off) 164599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 165599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rc *rc = file->private_data; 166599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_dbg_cmd cmd; 1676fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel int ret = 0; 1685b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella 169599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (len != sizeof(struct uwb_dbg_cmd)) 170599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -EINVAL; 171599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 172599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (copy_from_user(&cmd, buf, len) != 0) 173599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -EFAULT; 174599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 175599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel switch (cmd.type) { 176599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel case UWB_DBG_CMD_RSV_ESTABLISH: 177599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel ret = cmd_rsv_establish(rc, &cmd.rsv_establish); 178599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel break; 179599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel case UWB_DBG_CMD_RSV_TERMINATE: 180599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel ret = cmd_rsv_terminate(rc, &cmd.rsv_terminate); 181599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel break; 1826d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella case UWB_DBG_CMD_IE_ADD: 1836d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella ret = cmd_ie_add(rc, &cmd.ie_add); 1846d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella break; 1856d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella case UWB_DBG_CMD_IE_RM: 1866d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella ret = cmd_ie_rm(rc, &cmd.ie_rm); 1876d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella break; 1886fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel case UWB_DBG_CMD_RADIO_START: 1896fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel ret = uwb_radio_start(&rc->dbg->pal); 1906fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel break; 1916fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel case UWB_DBG_CMD_RADIO_STOP: 1926fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel uwb_radio_stop(&rc->dbg->pal); 1936fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel break; 194599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel default: 195599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return -EINVAL; 196599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 197599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 198599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return ret < 0 ? ret : len; 199599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 200599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 201828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations command_fops = { 202234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd .open = simple_open, 203599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .write = command_write, 204599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .read = NULL, 205599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .llseek = no_llseek, 206599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .owner = THIS_MODULE, 207599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel}; 208599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 209599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int reservations_print(struct seq_file *s, void *p) 210599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 211599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rc *rc = s->private; 212599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rsv *rsv; 213599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 214599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel mutex_lock(&rc->rsvs_mutex); 215599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 216599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel list_for_each_entry(rsv, &rc->reservations, rc_node) { 217599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_dev_addr devaddr; 218599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel char owner[UWB_ADDR_STRSIZE], target[UWB_ADDR_STRSIZE]; 219599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel bool is_owner; 220599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel char buf[72]; 221599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 222599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_dev_addr_print(owner, sizeof(owner), &rsv->owner->dev_addr); 223599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (rsv->target.type == UWB_RSV_TARGET_DEV) { 224599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel devaddr = rsv->target.dev->dev_addr; 225599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel is_owner = &rc->uwb_dev == rsv->owner; 226599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } else { 227599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel devaddr = rsv->target.devaddr; 228599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel is_owner = true; 229599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 230599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_dev_addr_print(target, sizeof(target), &devaddr); 231599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 232599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, "%c %s -> %s: %s\n", 233599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel is_owner ? 'O' : 'T', 234599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel owner, target, uwb_rsv_state_str(rsv->state)); 235599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, " stream: %d type: %s\n", 236599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rsv->stream, uwb_rsv_type_str(rsv->type)); 237599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel bitmap_scnprintf(buf, sizeof(buf), rsv->mas.bm, UWB_NUM_MAS); 238599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, " %s\n", buf); 239599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 240599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 241599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel mutex_unlock(&rc->rsvs_mutex); 242599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 243599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return 0; 244599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 245599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 246599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int reservations_open(struct inode *inode, struct file *file) 247599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 248599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return single_open(file, reservations_print, inode->i_private); 249599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 250599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 251828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations reservations_fops = { 252599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .open = reservations_open, 253599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .read = seq_read, 254599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .llseek = seq_lseek, 255599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .release = single_release, 256599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .owner = THIS_MODULE, 257599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel}; 258599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 259599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int drp_avail_print(struct seq_file *s, void *p) 260599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 261599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rc *rc = s->private; 262599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel char buf[72]; 263599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 264599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.global, UWB_NUM_MAS); 265599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, "global: %s\n", buf); 266599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.local, UWB_NUM_MAS); 267599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, "local: %s\n", buf); 268599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel bitmap_scnprintf(buf, sizeof(buf), rc->drp_avail.pending, UWB_NUM_MAS); 269599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel seq_printf(s, "pending: %s\n", buf); 270599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 271599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return 0; 272599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 273599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 274599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelstatic int drp_avail_open(struct inode *inode, struct file *file) 275599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 276599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return single_open(file, drp_avail_print, inode->i_private); 277599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 278599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 279828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations drp_avail_fops = { 280599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .open = drp_avail_open, 281599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .read = seq_read, 282599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .llseek = seq_lseek, 283599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .release = single_release, 284599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel .owner = THIS_MODULE, 285599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel}; 286599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 2876fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabelstatic void uwb_dbg_channel_changed(struct uwb_pal *pal, int channel) 2886fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel{ 2896fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel struct device *dev = &pal->rc->uwb_dev.dev; 2906fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel 2916fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel if (channel > 0) 2926fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel dev_info(dev, "debug: channel %d started\n", channel); 2936fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel else 2946fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel dev_info(dev, "debug: channel stopped\n"); 2956fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel} 2966fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel 297e17be2b2a95b43fe0d5878adf330701bb7a77115David Vrabelstatic void uwb_dbg_new_rsv(struct uwb_pal *pal, struct uwb_rsv *rsv) 298599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 299e17be2b2a95b43fe0d5878adf330701bb7a77115David Vrabel struct uwb_dbg *dbg = container_of(pal, struct uwb_dbg, pal); 300599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 301e17be2b2a95b43fe0d5878adf330701bb7a77115David Vrabel if (dbg->accept) { 3025b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_lock(&dbg->list_lock); 303e17be2b2a95b43fe0d5878adf330701bb7a77115David Vrabel list_add_tail(&rsv->pal_node, &dbg->rsvs); 3045b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_unlock(&dbg->list_lock); 305e17be2b2a95b43fe0d5878adf330701bb7a77115David Vrabel uwb_rsv_accept(rsv, uwb_dbg_rsv_cb, dbg); 306cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel } 307599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 308599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 309599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/** 310599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * uwb_dbg_add_rc - add a debug interface for a radio controller 311599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * @rc: the radio controller 312599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 313599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelvoid uwb_dbg_add_rc(struct uwb_rc *rc) 314599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 315599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg = kzalloc(sizeof(struct uwb_dbg), GFP_KERNEL); 316599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (rc->dbg == NULL) 317599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return; 318599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 319599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel INIT_LIST_HEAD(&rc->dbg->rsvs); 3205b37717a23b8e40f6cf7ad85a26ddcf41c171e2cStefano Panella spin_lock_init(&(rc->dbg)->list_lock); 321599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 322599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel uwb_pal_init(&rc->dbg->pal); 3236fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel rc->dbg->pal.rc = rc; 3246fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel rc->dbg->pal.channel_changed = uwb_dbg_channel_changed; 325599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->pal.new_rsv = uwb_dbg_new_rsv; 3266fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel uwb_pal_register(&rc->dbg->pal); 3276fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel 328599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (root_dir) { 329599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->root_d = debugfs_create_dir(dev_name(&rc->uwb_dev.dev), 330599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel root_dir); 331599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->command_f = debugfs_create_file("command", 0200, 332599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->root_d, rc, 333599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel &command_fops); 334599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->reservations_f = debugfs_create_file("reservations", 0444, 335599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->root_d, rc, 336599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel &reservations_fops); 337599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->accept_f = debugfs_create_bool("accept", 0644, 338599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->root_d, 339599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel &rc->dbg->accept); 340599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->drp_avail_f = debugfs_create_file("drp_avail", 0444, 341599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel rc->dbg->root_d, rc, 342599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel &drp_avail_fops); 343599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 344599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 345599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 346599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/** 3476d5a681dfb583b2f1eefe7cd5505419ca2d4d6c8Stefano Panella * uwb_dbg_del_rc - remove a radio controller's debug interface 348599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * @rc: the radio controller 349599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 350599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelvoid uwb_dbg_del_rc(struct uwb_rc *rc) 351599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 352599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel struct uwb_rsv *rsv, *t; 353599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 354599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (rc->dbg == NULL) 355599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel return; 356599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 357599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel list_for_each_entry_safe(rsv, t, &rc->dbg->rsvs, pal_node) { 358cae1c11414912bf77a62aebd65ced321f0b9da51David Vrabel uwb_rsv_terminate(rsv); 359599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 360599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 3616fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel uwb_pal_unregister(&rc->dbg->pal); 362599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 363599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel if (root_dir) { 364599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(rc->dbg->drp_avail_f); 365599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(rc->dbg->accept_f); 366599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(rc->dbg->reservations_f); 367599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(rc->dbg->command_f); 368599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(rc->dbg->root_d); 369599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel } 370599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 371599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 372599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/** 373599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * uwb_dbg_exit - initialize the debug interface sub-module 374599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 375599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelvoid uwb_dbg_init(void) 376599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 377599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel root_dir = debugfs_create_dir("uwb", NULL); 378599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 379599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel 380599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel/** 381599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel * uwb_dbg_exit - clean-up the debug interface sub-module 382599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel */ 383599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabelvoid uwb_dbg_exit(void) 384599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel{ 385599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel debugfs_remove(root_dir); 386599e8d80a2cdf4f65fc49b31b27a49235c78acfeDavid Vrabel} 387dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel 388dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel/** 389dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel * uwb_dbg_create_pal_dir - create a debugfs directory for a PAL 390dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel * @pal: The PAL. 391dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel */ 392dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabelstruct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal) 393dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel{ 394dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel struct uwb_rc *rc = pal->rc; 395dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel 396dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel if (root_dir && rc->dbg && rc->dbg->root_d && pal->name) 397dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel return debugfs_create_dir(pal->name, rc->dbg->root_d); 398dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel return NULL; 399dcc7461eef7341e84e2f7274f904ce01a43b2506David Vrabel} 400