1c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* 2c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Intel Wireless WiMAX Connection 2400m 3c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Debugfs interfaces to manipulate driver and device information 4c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 5c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 6c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com> 7c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 8c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 9c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 10c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 11c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 12c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 13c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 14c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 15c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * GNU General Public License for more details. 17c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 18c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 19c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * along with this program; if not, write to the Free Software 20c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 02110-1301, USA. 22c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez */ 23c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 24c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include <linux/debugfs.h> 25c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include <linux/netdevice.h> 26c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include <linux/etherdevice.h> 27c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include <linux/spinlock.h> 28c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include <linux/device.h> 29ee40fa0656a730491765545ff7550f3c1ceb0fbcPaul Gortmaker#include <linux/export.h> 30c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include "i2400m.h" 31c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 32c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 33c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#define D_SUBMODULE debugfs 34c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#include "debug-levels.h" 35c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 36c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 37c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezint debugfs_netdev_queue_stopped_get(void *data, u64 *val) 38c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 39c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = data; 40c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez *val = netif_queue_stopped(i2400m->wimax_dev.net_dev); 41c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return 0; 42c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 43c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-GonzalezDEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped, 44c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez debugfs_netdev_queue_stopped_get, 45c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez NULL, "%llu\n"); 46c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 47c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 48c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 49c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstruct dentry *debugfs_create_netdev_queue_stopped( 50c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez const char *name, struct dentry *parent, struct i2400m *i2400m) 51c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 52c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return debugfs_create_file(name, 0400, parent, i2400m, 53c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &fops_netdev_queue_stopped); 54c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 55c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 56c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* 57c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * We don't allow partial reads of this file, as then the reader would 58c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * get weirdly confused data as it is updated. 59c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 60c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * So or you read it all or nothing; if you try to read with an offset 61c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * != 0, we consider you are done reading. 62c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez */ 63c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 64c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezssize_t i2400m_rx_stats_read(struct file *filp, char __user *buffer, 65c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez size_t count, loff_t *ppos) 66c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 67c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = filp->private_data; 68c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez char buf[128]; 69c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez unsigned long flags; 70c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 71c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (*ppos != 0) 72c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return 0; 73c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (count < sizeof(buf)) 74c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return -ENOSPC; 75c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_lock_irqsave(&i2400m->rx_lock, flags); 76c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n", 77c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_pl_num, i2400m->rx_pl_min, 78c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_pl_max, i2400m->rx_num, 79c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_size_acc, 80c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_size_min, i2400m->rx_size_max); 81c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_unlock_irqrestore(&i2400m->rx_lock, flags); 82c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 83c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 84c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 85c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 86c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* Any write clears the stats */ 87c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 88c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer, 89c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez size_t count, loff_t *ppos) 90c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 91c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = filp->private_data; 92c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez unsigned long flags; 93c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 94c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_lock_irqsave(&i2400m->rx_lock, flags); 95c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_pl_num = 0; 96c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_pl_max = 0; 97c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_pl_min = UINT_MAX; 98c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_num = 0; 99c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_size_acc = 0; 100c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_size_min = UINT_MAX; 101c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->rx_size_max = 0; 102c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_unlock_irqrestore(&i2400m->rx_lock, flags); 103c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return count; 104c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 105c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 106c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 107c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezconst struct file_operations i2400m_rx_stats_fops = { 108c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .owner = THIS_MODULE, 109234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd .open = simple_open, 110c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .read = i2400m_rx_stats_read, 111c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .write = i2400m_rx_stats_write, 1126038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 113c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez}; 114c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 115c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 116c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* See i2400m_rx_stats_read() */ 117c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 118c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezssize_t i2400m_tx_stats_read(struct file *filp, char __user *buffer, 119c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez size_t count, loff_t *ppos) 120c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 121c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = filp->private_data; 122c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez char buf[128]; 123c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez unsigned long flags; 124c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 125c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (*ppos != 0) 126c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return 0; 127c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (count < sizeof(buf)) 128c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return -ENOSPC; 129c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_lock_irqsave(&i2400m->tx_lock, flags); 130c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n", 131c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_pl_num, i2400m->tx_pl_min, 132c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_pl_max, i2400m->tx_num, 133c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_size_acc, 134c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_size_min, i2400m->tx_size_max); 135c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_unlock_irqrestore(&i2400m->tx_lock, flags); 136c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); 137c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 138c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 139c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* Any write clears the stats */ 140c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 141c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer, 142c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez size_t count, loff_t *ppos) 143c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 144c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = filp->private_data; 145c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez unsigned long flags; 146c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 147c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_lock_irqsave(&i2400m->tx_lock, flags); 148c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_pl_num = 0; 149c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_pl_max = 0; 150c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_pl_min = UINT_MAX; 151c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_num = 0; 152c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_size_acc = 0; 153c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_size_min = UINT_MAX; 154c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->tx_size_max = 0; 155c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez spin_unlock_irqrestore(&i2400m->tx_lock, flags); 156c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return count; 157c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 158c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 159c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 160c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezconst struct file_operations i2400m_tx_stats_fops = { 161c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .owner = THIS_MODULE, 162234e340582901211f40d8c732afc49f0630ecf05Stephen Boyd .open = simple_open, 163c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .read = i2400m_tx_stats_read, 164c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez .write = i2400m_tx_stats_write, 1656038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 166c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez}; 167c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 168c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 169c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* Write 1 to ask the device to go into suspend */ 170c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 171c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezint debugfs_i2400m_suspend_set(void *data, u64 val) 172c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 173c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez int result; 174c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = data; 175c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = i2400m_cmd_enter_powersave(i2400m); 176c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (result >= 0) 177c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = 0; 178c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return result; 179c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 180c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-GonzalezDEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend, 181c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez NULL, debugfs_i2400m_suspend_set, 182c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "%llu\n"); 183c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 184c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 185c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstruct dentry *debugfs_create_i2400m_suspend( 186c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez const char *name, struct dentry *parent, struct i2400m *i2400m) 187c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 188c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return debugfs_create_file(name, 0200, parent, i2400m, 189c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &fops_i2400m_suspend); 190c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 191c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 192c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 193c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez/* 194c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Reset the device 195c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 196c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Write 0 to ask the device to soft reset, 1 to cold reset, 2 to bus 197c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * reset (as defined by enum i2400m_reset_type). 198c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez */ 199c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 200c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezint debugfs_i2400m_reset_set(void *data, u64 val) 201c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 202c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez int result; 203c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct i2400m *i2400m = data; 204c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez enum i2400m_reset_type rt = val; 205c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez switch(rt) { 206c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez case I2400M_RT_WARM: 207c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez case I2400M_RT_COLD: 208c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez case I2400M_RT_BUS: 209c931ceeb780560ff652a8f9875f88778439ee87eInaky Perez-Gonzalez result = i2400m_reset(i2400m, rt); 210c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (result >= 0) 211c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = 0; 21201872c641f8bb25b6d70328177c8fb08e0dd6d0bAlan Cox break; 213c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez default: 214c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = -EINVAL; 215c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 216c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return result; 217c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 218c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-GonzalezDEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset, 219c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez NULL, debugfs_i2400m_reset_set, 220c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "%llu\n"); 221c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 222c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstatic 223c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezstruct dentry *debugfs_create_i2400m_reset( 224c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez const char *name, struct dentry *parent, struct i2400m *i2400m) 225c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 226c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return debugfs_create_file(name, 0200, parent, i2400m, 227c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &fops_i2400m_reset); 228c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 229c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 230c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 231c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez#define __debugfs_register(prefix, name, parent) \ 232c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezdo { \ 233c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = d_level_register_debugfs(prefix, name, parent); \ 234c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (result < 0) \ 235c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; \ 236c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} while (0) 237c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 238c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 239c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezint i2400m_debugfs_add(struct i2400m *i2400m) 240c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 241c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez int result; 242c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct device *dev = i2400m_dev(i2400m); 243c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry; 244c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez struct dentry *fd; 245c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 246c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dentry = debugfs_create_dir("i2400m", dentry); 247c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(dentry); 248c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(dentry)) { 249c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (result == -ENODEV) 250c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = 0; /* No debugfs support */ 251c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 252c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 253c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez i2400m->debugfs_dentry = dentry; 254c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", control, dentry); 255c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", driver, dentry); 256c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", debugfs, dentry); 257c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", fw, dentry); 258c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", netdev, dentry); 259c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", rfkill, dentry); 260c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", rx, dentry); 261c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez __debugfs_register("dl_", tx, dentry); 262c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 263c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_size_t("tx_in", 0400, dentry, 264c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m->tx_in); 265c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 266c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 267c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 268c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "tx_in: %d\n", result); 269c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 270c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 271c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 272c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_size_t("tx_out", 0400, dentry, 273c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m->tx_out); 274c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 275c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 276c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 277c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "tx_out: %d\n", result); 278c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 279c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 280c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 281c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_u32("state", 0600, dentry, 282c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m->state); 283c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 284c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 285c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 286c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "state: %d\n", result); 287c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 288c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 289c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 290c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez /* 291c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Trace received messages from user space 292c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 293c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * In order to tap the bidirectional message stream in the 294c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 'msg' pipe, user space can read from the 'msg' pipe; 295c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * however, due to limitations in libnl, we can't know what 296c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * the different applications are sending down to the kernel. 297c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 298c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * So we have this hack where the driver will echo any message 299c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * received on the msg pipe from user space [through a call to 300c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * wimax_dev->op_msg_from_user() into 301c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * i2400m_op_msg_from_user()] into the 'trace' pipe that this 302c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * driver creates. 303c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 304c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * So then, reading from both the 'trace' and 'msg' pipes in 305c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * user space will provide a full dump of the traffic. 306c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 307c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * Write 1 to activate, 0 to clear. 308c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * 309c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * It is not really very atomic, but it is also not too 310c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez * critical. 311c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez */ 312c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry, 313c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m->trace_msg_from_user); 314c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 315c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 316c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 317c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "trace_msg_from_user: %d\n", result); 318c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 319c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 320c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 321c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped", 322c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dentry, i2400m); 323c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 324c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 325c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 326c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "netdev_queue_stopped: %d\n", result); 327c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 328c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 329c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 330c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m, 331c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m_rx_stats_fops); 332c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 333c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 334c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 335c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "rx_stats: %d\n", result); 336c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 337c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 338c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 339c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m, 340c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez &i2400m_tx_stats_fops); 341c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 342c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 343c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry " 344c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez "tx_stats: %d\n", result); 345c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 346c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 347c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 348c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m); 349c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 350c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 351c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry suspend: %d\n", 352c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result); 353c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 354c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 355c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 356c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez fd = debugfs_create_i2400m_reset("reset", dentry, i2400m); 357c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = PTR_ERR(fd); 358c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez if (IS_ERR(fd) && result != -ENODEV) { 359c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez dev_err(dev, "Can't create debugfs entry reset: %d\n", result); 360c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez goto error; 361c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez } 362c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 363c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez result = 0; 364c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezerror: 365c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez return result; 366c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 367c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez 368c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalezvoid i2400m_debugfs_rm(struct i2400m *i2400m) 369c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez{ 370c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez debugfs_remove_recursive(i2400m->debugfs_dentry); 371c71228caf91ec6320b489dec5cd0087b64da9fb5Inaky Perez-Gonzalez} 372