1876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/dcache.h> 2876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/debugfs.h> 3876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/delay.h> 4a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/hardirq.h> 5876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include <linux/mm.h> 6d8b0fb51ef1563c631d26cb649a5479b5cc4899cGeert Uytterhoeven#include <linux/string.h> 75a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 8ee40fa0656a730491765545ff7550f3c1ceb0fbcPaul Gortmaker#include <linux/export.h> 946868202b2dd22156460a220553a223f406f4f22Holger Schurig 10876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#include "decl.h" 113fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse#include "cmd.h" 12e86dc1ca4676445d9f0dfe35104efe0eb8a2f566Kiran Divekar#include "debugfs.h" 13876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 141007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic struct dentry *lbs_dir; 15876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic char *szStates[] = { 16876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti "Connected", 17876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti "Disconnected" 18876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 19876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2046868202b2dd22156460a220553a223f406f4f22Holger Schurig#ifdef PROC_DEBUG 21e98a88dd33b7188ce84533e128101dd9630ae592Holger Schurigstatic void lbs_debug_init(struct lbs_private *priv); 2246868202b2dd22156460a220553a223f406f4f22Holger Schurig#endif 23876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 24876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic int open_file_generic(struct inode *inode, struct file *file) 25876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 26876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti file->private_data = inode->i_private; 27876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 0; 28876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 29876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 30876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic ssize_t write_file_dummy(struct file *file, const char __user *buf, 31876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 32876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 33876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return -EINVAL; 34876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 35876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 36876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic const size_t len = PAGE_SIZE; 37876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 381007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_dev_info(struct file *file, char __user *userbuf, 39876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 40876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 4169f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 42876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t pos = 0; 43876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 44876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 45876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res; 46ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 47ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 48876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 49876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti pos += snprintf(buf+pos, len-pos, "state = %s\n", 50aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse szStates[priv->connect_status]); 51876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti pos += snprintf(buf+pos, len-pos, "region_code = %02x\n", 52aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse (u32) priv->regioncode); 53876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 54876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 55876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 56876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 57876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 58876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 59876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 601007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_sleepparams_write(struct file *file, 61876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *user_buf, size_t count, 62876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti loff_t *ppos) 63876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 6469f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 653fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ssize_t buf_size, ret; 663fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse struct sleep_params sp; 67876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int p1, p2, p3, p4, p5, p6; 68876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 69876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 70ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 71ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 72876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 73876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 74876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, user_buf, buf_size)) { 753fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = -EFAULT; 76876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 77876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 783fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6); 793fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse if (ret != 6) { 803fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = -EINVAL; 81876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 82876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 833fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_error = p1; 843fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_offset = p2; 853fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_stabletime = p3; 863fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_calcontrol = p4; 873fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_extsleepclk = p5; 883fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_reserved = p6; 893fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse 903fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp); 913fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse if (!ret) 923fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = count; 933fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse else if (ret > 0) 943fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = -EINVAL; 95876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 96876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 97876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 983fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse return ret; 99876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 100876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1011007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, 102876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 103876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 10469f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 1053fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ssize_t ret; 106876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t pos = 0; 1073fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse struct sleep_params sp; 108876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 109876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 110ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 111ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 112876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1133fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp); 1143fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse if (ret) 115876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 116876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1173fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error, 1183fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_offset, sp.sp_stabletime, 1193fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_calcontrol, sp.sp_extsleepclk, 1203fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse sp.sp_reserved); 121876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1223fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 123876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 124876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 125876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 1263fbe104cecdb8c812976fdb0cc41be65491b85eeDavid Woodhouse return ret; 127876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 128876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 1291311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwarstatic ssize_t lbs_host_sleep_write(struct file *file, 1301311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar const char __user *user_buf, size_t count, 1311311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar loff_t *ppos) 1321311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar{ 1331311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar struct lbs_private *priv = file->private_data; 1341311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ssize_t buf_size, ret; 1351311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar int host_sleep; 1361311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar unsigned long addr = get_zeroed_page(GFP_KERNEL); 1371311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar char *buf = (char *)addr; 1381311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (!buf) 1391311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar return -ENOMEM; 1401311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1411311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar buf_size = min(count, len - 1); 1421311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (copy_from_user(buf, user_buf, buf_size)) { 1431311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = -EFAULT; 1441311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar goto out_unlock; 1451311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar } 1461311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = sscanf(buf, "%d", &host_sleep); 1471311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (ret != 1) { 1481311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = -EINVAL; 1491311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar goto out_unlock; 1501311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar } 1511311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1521311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (host_sleep == 0) 1531311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = lbs_set_host_sleep(priv, 0); 1541311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar else if (host_sleep == 1) { 1551311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { 156f3a57fd148a4afd3c38f558c5b44972cb29ea8baJoe Perches netdev_info(priv->dev, 157f3a57fd148a4afd3c38f558c5b44972cb29ea8baJoe Perches "wake parameters not configured\n"); 1581311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = -EINVAL; 1591311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar goto out_unlock; 1601311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar } 1611311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = lbs_set_host_sleep(priv, 1); 1621311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar } else { 163f3a57fd148a4afd3c38f558c5b44972cb29ea8baJoe Perches netdev_err(priv->dev, "invalid option\n"); 1641311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = -EINVAL; 1651311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar } 1661311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1671311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (!ret) 1681311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = count; 1691311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1701311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwarout_unlock: 1711311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar free_page(addr); 1721311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar return ret; 1731311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar} 1741311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1751311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwarstatic ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf, 1761311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar size_t count, loff_t *ppos) 1771311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar{ 1781311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar struct lbs_private *priv = file->private_data; 1791311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ssize_t ret; 1801311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar size_t pos = 0; 1811311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar unsigned long addr = get_zeroed_page(GFP_KERNEL); 1821311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar char *buf = (char *)addr; 1831311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar if (!buf) 1841311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar return -ENOMEM; 1851311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1861311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated); 1871311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1881311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 1891311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1901311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar free_page(addr); 1911311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar return ret; 1921311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar} 1931311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar 1943a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig/* 1953a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might 1963a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the 1973a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * firmware. Here's an example: 1983a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00 1993a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03 2003a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2013a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 2023a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length, 2033a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 00 00 are the data bytes of this TLV. For this TLV, their meaning is 2043a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * defined in mrvlietypes_thresholds 2053a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * 2063a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * This function searches in this TLV data chunk for a given TLV type 2073a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * and returns a pointer to the first data byte of the TLV, or to NULL 2083a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig * if the TLV hasn't been found. 2093a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig */ 2105844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size) 211876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 21275b6a61a47353fd404277ae3f2dda03af96a8c1aDan Williams struct mrvl_ie_header *tlv_h; 2135844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse uint16_t length; 2145844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ssize_t pos = 0; 2155844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 2163a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig while (pos < size) { 21775b6a61a47353fd404277ae3f2dda03af96a8c1aDan Williams tlv_h = (struct mrvl_ie_header *) tlv; 2185844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!tlv_h->len) 2193a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return NULL; 2205844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (tlv_h->type == cpu_to_le16(tlv_type)) 2215844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse return tlv_h; 2225844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h); 2233a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig pos += length; 2243a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig tlv += length; 2253a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig } 2263a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return NULL; 227876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 228876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2293a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig 2305844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, 2315844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse struct file *file, char __user *userbuf, 2325844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 233876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 2345844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse struct cmd_ds_802_11_subscribe_event *subscribed; 23575b6a61a47353fd404277ae3f2dda03af96a8c1aDan Williams struct mrvl_ie_thresholds *got; 23669f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 2375844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ssize_t ret = 0; 2383a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig size_t pos = 0; 2395844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse char *buf; 2403a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig u8 value; 2413a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig u8 freq; 242b6b8abe4ddec2cfb3471ea60f965a137cd4d529dHolger Schurig int events = 0; 243876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2445844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse buf = (char *)get_zeroed_page(GFP_KERNEL); 2455844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!buf) 2465844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse return -ENOMEM; 247876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2485844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL); 2495844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!subscribed) { 2505844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = -ENOMEM; 2515844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_page; 252876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 253876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2545844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed)); 2555844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse subscribed->action = cpu_to_le16(CMD_ACT_GET); 2565844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 2575844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed); 2585844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (ret) 2595844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_cmd; 2605844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 261b6b8abe4ddec2cfb3471ea60f965a137cd4d529dHolger Schurig got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv)); 2623a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig if (got) { 2633a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig value = got->value; 2643a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig freq = got->freq; 265b6b8abe4ddec2cfb3471ea60f965a137cd4d529dHolger Schurig events = le16_to_cpu(subscribed->events); 266876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2673a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig pos += snprintf(buf, len, "%d %d %d\n", value, freq, 2685844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse !!(events & event_mask)); 2695844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse } 270876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2715844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 272876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2735844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse out_cmd: 2745844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse kfree(subscribed); 2755844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 2765844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse out_page: 2775844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse free_page((unsigned long)buf); 2785844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse return ret; 279876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 280876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 281876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 2825844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, 2835844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse struct file *file, 2845844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse const char __user *userbuf, size_t count, 2855844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse loff_t *ppos) 286876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 2873a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig struct cmd_ds_802_11_subscribe_event *events; 28875b6a61a47353fd404277ae3f2dda03af96a8c1aDan Williams struct mrvl_ie_thresholds *tlv; 2895844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse struct lbs_private *priv = file->private_data; 2905844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ssize_t buf_size; 2915844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse int value, freq, new_mask; 2925844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse uint16_t curr_mask; 2935844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse char *buf; 2945844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse int ret; 2955844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 2965844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse buf = (char *)get_zeroed_page(GFP_KERNEL); 2975844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!buf) 2985844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse return -ENOMEM; 299876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 300876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 301876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 3025844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = -EFAULT; 3035844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_page; 304876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 3055844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask); 3065844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (ret != 3) { 3075844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = -EINVAL; 3085844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_page; 3095844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse } 3105844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse events = kzalloc(sizeof(*events), GFP_KERNEL); 3115844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!events) { 3125844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = -ENOMEM; 3135844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_page; 314876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 3155844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3165844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse events->hdr.size = cpu_to_le16(sizeof(*events)); 3175844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse events->action = cpu_to_le16(CMD_ACT_GET); 3185844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3195844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); 3205844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (ret) 3215844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse goto out_events; 3225844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3235844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse curr_mask = le16_to_cpu(events->events); 324876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3253a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig if (new_mask) 3263a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig new_mask = curr_mask | event_mask; 3273a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig else 3283a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig new_mask = curr_mask & ~event_mask; 3293a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig 3303a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig /* Now everything is set and we can send stuff down to the firmware */ 331876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3325844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse tlv = (void *)events->tlv; 3335844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3345844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse events->action = cpu_to_le16(CMD_ACT_SET); 3355844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse events->events = cpu_to_le16(new_mask); 3365844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse tlv->header.type = cpu_to_le16(tlv_type); 3375844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header)); 3385844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse tlv->value = value; 3395844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (tlv_type != TLV_TYPE_BCNMISS) 3405844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse tlv->freq = freq; 3415844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 342a75eda43dc4a64d0bd0502da546871c01f70e899Holger Schurig /* The command header, the action, the event mask, and one TLV */ 343a75eda43dc4a64d0bd0502da546871c01f70e899Holger Schurig events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv)); 3445844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3455844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); 3465844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse 3475844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse if (!ret) 3485844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse ret = count; 3495844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse out_events: 3505844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse kfree(events); 3515844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse out_page: 3525844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse free_page((unsigned long)buf); 3535844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse return ret; 354876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 355876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 356876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3575844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf, 3585844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 359876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 3603a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW, 3615844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 362876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 363876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 364876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3655844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf, 3665844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 3673a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 3683a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW, 3695844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 3703a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 371876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 372876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3735844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf, 3745844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 3753a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 3763a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW, 3775844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 3783a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 379876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 380876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3815844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf, 3825844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 3833a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 3843a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW, 3855844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 3863a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 387876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 388876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3895844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_failcount_read(struct file *file, char __user *userbuf, 3905844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 3913a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 3923a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT, 3935844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 3943a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 395876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 396876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 3975844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf, 3985844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 3993a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 4003a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT, 4015844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 402876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 403876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4043a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig 4055844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf, 4065844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 407876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 4083a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH, 4095844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 4103a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 411876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 412876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4135844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf, 4145844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 4153a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 4163a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH, 4175844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 4183a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 419876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 420876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4215844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf, 4225844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 4233a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 4243a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH, 4255844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 4263a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 427876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 428876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4295844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf, 4305844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 4313a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 4323a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH, 4335844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 434876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 435876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4365844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf, 4375844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 438876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 4393a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS, 4405844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 4413a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig} 442876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 443876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4445844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhousestatic ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf, 4455844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse size_t count, loff_t *ppos) 4463a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig{ 4473a1886491710c196656a005fcc693172f5bb4c8aHolger Schurig return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS, 4485844d12ea30bacae9224db6561a16e86ad31c6e5David Woodhouse file, userbuf, count, ppos); 449876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 450876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 451876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4521007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, 453876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 454876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 45569f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 456876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t pos = 0; 457876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int ret; 458876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 459876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 4604c7c6e00f17365633638848197c44552dd353d49Dan Williams u32 val = 0; 4614c7c6e00f17365633638848197c44552dd353d49Dan Williams 462ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 463ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 464876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4654c7c6e00f17365633638848197c44552dd353d49Dan Williams ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val); 466876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 467c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!ret) { 4684c7c6e00f17365633638848197c44552dd353d49Dan Williams pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n", 4694c7c6e00f17365633638848197c44552dd353d49Dan Williams priv->mac_offset, val); 470c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 471c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar } 472876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 473876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 474876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 475876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4761007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdmac_write(struct file *file, 477876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 478876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 479876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 48069f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 481876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 482876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 483876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 484ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 485ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 486876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 487876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 488876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 489876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 490876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 491876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 492876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->mac_offset = simple_strtoul((char *)buf, NULL, 16); 493876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = count; 494876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 495876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 496876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 497876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 498876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 4991007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_wrmac_write(struct file *file, 500876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 501876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 502876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 503876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 50469f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 505876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 506876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 offset, value; 507876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 508876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 509ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 510ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 511876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 512876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 513876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 514876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 515876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 516876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 517876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = sscanf(buf, "%x %x", &offset, &value); 518876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (res != 2) { 519876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 520876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 521876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 522876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 5234c7c6e00f17365633638848197c44552dd353d49Dan Williams res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value); 524876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 525876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 526c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!res) 527c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar res = count; 528876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 529876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 530876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 531876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 532876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 5331007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, 534876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 535876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 53669f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 537876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t pos = 0; 538876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int ret; 539876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 540876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 5414c7c6e00f17365633638848197c44552dd353d49Dan Williams u32 val; 5424c7c6e00f17365633638848197c44552dd353d49Dan Williams 543ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 544ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 545876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 5464c7c6e00f17365633638848197c44552dd353d49Dan Williams ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val); 547876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 548c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!ret) { 5494c7c6e00f17365633638848197c44552dd353d49Dan Williams pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n", 5504c7c6e00f17365633638848197c44552dd353d49Dan Williams priv->bbp_offset, val); 551c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 552c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar } 553876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 554876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 555876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 556876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 557876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 5581007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdbbp_write(struct file *file, 559876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 560876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 561876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 56269f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 563876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 564876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 565876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 566ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 567ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 568876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 569876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 570876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 571876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 572876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 573876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 574876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16); 575876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = count; 576876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 577876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 578876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 579876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 580876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 5811007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_wrbbp_write(struct file *file, 582876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 583876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 584876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 585876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 58669f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 587876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 588876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 offset, value; 589876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 590876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 591ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 592ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 593876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 594876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 595876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 596876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 597876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 598876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 599876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = sscanf(buf, "%x %x", &offset, &value); 600876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (res != 2) { 601876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 602876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 603876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 604876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6054c7c6e00f17365633638848197c44552dd353d49Dan Williams res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value); 606876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 607876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 608c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!res) 609c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar res = count; 610876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 611876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 612876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 613876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 614876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6151007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, 616876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 617876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 61869f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 619876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t pos = 0; 620876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int ret; 621876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 622876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 6234c7c6e00f17365633638848197c44552dd353d49Dan Williams u32 val; 6244c7c6e00f17365633638848197c44552dd353d49Dan Williams 625ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 626ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 627876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6284c7c6e00f17365633638848197c44552dd353d49Dan Williams ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val); 629876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 630c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!ret) { 6314c7c6e00f17365633638848197c44552dd353d49Dan Williams pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n", 6324c7c6e00f17365633638848197c44552dd353d49Dan Williams priv->rf_offset, val); 633c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 634c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar } 635876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 636876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 637876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return ret; 638876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 639876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6401007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_rdrf_write(struct file *file, 641876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 642876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 643876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 64469f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 645876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 646876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 647876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 648ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 649ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 650876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 651876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 652876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 653876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 654876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 655876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 6564101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardt priv->rf_offset = simple_strtoul(buf, NULL, 16); 657876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = count; 658876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 659876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 660876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 661876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 662876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6631007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_wrrf_write(struct file *file, 664876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti const char __user *userbuf, 665876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 666876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 667876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 66869f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurig struct lbs_private *priv = file->private_data; 669876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res, buf_size; 670876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 offset, value; 671876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 672876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 673ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 674ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 675876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 676876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti buf_size = min(count, len - 1); 677876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(buf, userbuf, buf_size)) { 678876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 679876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 680876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 681876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = sscanf(buf, "%x %x", &offset, &value); 682876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (res != 2) { 683876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = -EFAULT; 684876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto out_unlock; 685876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 686876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 6874c7c6e00f17365633638848197c44552dd353d49Dan Williams res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value); 688876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti mdelay(10); 689876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 690c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar if (!res) 691c0bbd57679efc2350703a1c0f3fc624cbcaba55fAmitkumar Karwar res = count; 692876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiout_unlock: 693876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 694876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 695876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 696876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 697876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#define FOPS(fread, fwrite) { \ 698876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .owner = THIS_MODULE, \ 699876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .open = open_file_generic, \ 700876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .read = (fread), \ 701876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .write = (fwrite), \ 7022b18ab36cf7e956fb5b5ee12847e94fc66d496f4Arnd Bergmann .llseek = generic_file_llseek, \ 703876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 704876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7051007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstruct lbs_debugfs_files { 7064101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardt const char *name; 707f4ae40a6a50a98ac23d4b285f739455e926a473eAl Viro umode_t perm; 708876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct file_operations fops; 709876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 710876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7114101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardtstatic const struct lbs_debugfs_files debugfs_files[] = { 7121007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, 7131007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig { "sleepparams", 0644, FOPS(lbs_sleepparams_read, 7141007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_sleepparams_write), }, 7151311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar { "hostsleep", 0644, FOPS(lbs_host_sleep_read, 7161311843c58ca606bab8bfe4cf6c0fe50deb9986dAmitkumar Karwar lbs_host_sleep_write), }, 717876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 718876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7194101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardtstatic const struct lbs_debugfs_files debugfs_events_files[] = { 7201007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"low_rssi", 0644, FOPS(lbs_lowrssi_read, 7211007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_lowrssi_write), }, 7221007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"low_snr", 0644, FOPS(lbs_lowsnr_read, 7231007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_lowsnr_write), }, 7241007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"failure_count", 0644, FOPS(lbs_failcount_read, 7251007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_failcount_write), }, 7261007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read, 7271007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_bcnmiss_write), }, 7281007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"high_rssi", 0644, FOPS(lbs_highrssi_read, 7291007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_highrssi_write), }, 7301007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"high_snr", 0644, FOPS(lbs_highsnr_read, 7311007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_highsnr_write), }, 732876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 733876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7344101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardtstatic const struct lbs_debugfs_files debugfs_regs_files[] = { 7351007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), }, 7361007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), }, 7371007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), }, 7381007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), }, 7391007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), }, 7401007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), }, 741876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 742876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7431007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_debugfs_init(void) 744876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 7451007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (!lbs_dir) 7461007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig lbs_dir = debugfs_create_dir("lbs_wireless", NULL); 747876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 748876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7491007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigvoid lbs_debugfs_remove(void) 750876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 7511007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (lbs_dir) 7521007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig debugfs_remove(lbs_dir); 753876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 754876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 75569f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurigvoid lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) 756876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 757876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int i; 7584101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardt const struct lbs_debugfs_files *files; 7591007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig if (!lbs_dir) 760876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto exit; 761876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 7621007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir); 763876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!priv->debugfs_dir) 764876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto exit; 765876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 766876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i=0; i<ARRAY_SIZE(debugfs_files); i++) { 767876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files = &debugfs_files[i]; 768876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_files[i] = debugfs_create_file(files->name, 769876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files->perm, 770876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_dir, 771876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv, 772876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti &files->fops); 773876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 774876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 775876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir); 776876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!priv->events_dir) 777876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto exit; 778876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 779876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i=0; i<ARRAY_SIZE(debugfs_events_files); i++) { 780876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files = &debugfs_events_files[i]; 781876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_events_files[i] = debugfs_create_file(files->name, 782876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files->perm, 783876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->events_dir, 784876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv, 785876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti &files->fops); 786876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 787876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 788876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir); 789876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!priv->regs_dir) 790876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti goto exit; 791876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 792876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) { 793876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files = &debugfs_regs_files[i]; 794876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_regs_files[i] = debugfs_create_file(files->name, 795876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti files->perm, 796876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->regs_dir, 797876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv, 798876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti &files->fops); 799876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 800876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 801876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#ifdef PROC_DEBUG 802e98a88dd33b7188ce84533e128101dd9630ae592Holger Schurig lbs_debug_init(priv); 803876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#endif 804876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattiexit: 805876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return; 806876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 807876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 80869f9032d9dfeb763b467fdbe8cf5938f5457083aHolger Schurigvoid lbs_debugfs_remove_one(struct lbs_private *priv) 809876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 810876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int i; 811876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 812876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for(i=0; i<ARRAY_SIZE(debugfs_regs_files); i++) 813876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->debugfs_regs_files[i]); 814876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 815876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->regs_dir); 816876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 8170b7db95602d0eb5339c7b7a9c7beff4b146bdeecHolger Schurig for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++) 818876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->debugfs_events_files[i]); 819876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 820876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->events_dir); 821876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#ifdef PROC_DEBUG 822876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->debugfs_debug); 823876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti#endif 824876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for(i=0; i<ARRAY_SIZE(debugfs_files); i++) 825876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti debugfs_remove(priv->debugfs_files[i]); 8260b7db95602d0eb5339c7b7a9c7beff4b146bdeecHolger Schurig debugfs_remove(priv->debugfs_dir); 827876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 828876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 82946868202b2dd22156460a220553a223f406f4f22Holger Schurig 83046868202b2dd22156460a220553a223f406f4f22Holger Schurig 831876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/* debug entry */ 832876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 83346868202b2dd22156460a220553a223f406f4f22Holger Schurig#ifdef PROC_DEBUG 83446868202b2dd22156460a220553a223f406f4f22Holger Schurig 835aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n)) 836aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse#define item_addr(n) (offsetof(struct lbs_private, n)) 837876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 83846868202b2dd22156460a220553a223f406f4f22Holger Schurig 839876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistruct debug_data { 840876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char name[32]; 841876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti u32 size; 8424269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams size_t addr; 843876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 844876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 845aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse/* To debug any member of struct lbs_private, simply add one line here. 846876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 847876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosattistatic struct debug_data items[] = { 848876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti {"psmode", item_size(psmode), item_addr(psmode)}, 849876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti {"psstate", item_size(psstate), item_addr(psstate)}, 850876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 851876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 852d2f11e0991e3794f11d851b7ee0d98e064b10333Tony Breedsstatic int num_of_items = ARRAY_SIZE(items); 853876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 854876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 8558973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * lbs_debugfs_read - proc read function 856876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 8578973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @file: file to read 8588973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @userbuf: pointer to buffer 8598973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @count: number of bytes to read 8608973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @ppos: read data starting position 8618973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * 8628973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * returns: amount of data read or negative error code 863876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 8641007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, 865876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t count, loff_t *ppos) 866876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 867876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int val = 0; 868876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t pos = 0; 869876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti ssize_t res; 870876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *p; 871876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int i; 872876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti struct debug_data *d; 873876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti unsigned long addr = get_zeroed_page(GFP_KERNEL); 874876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *buf = (char *)addr; 875ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar if (!buf) 876ad43f8bfb7b9a6a8b800cdad24c4a62180a5eb3dKiran Divekar return -ENOMEM; 877876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 878876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p = buf; 879876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 88057674308d00b5ebb639ce53d388e61728e0c7f72Joe Perches d = file->private_data; 881876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 882876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i = 0; i < num_of_items; i++) { 883876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (d[i].size == 1) 884876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti val = *((u8 *) d[i].addr); 885876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti else if (d[i].size == 2) 886876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti val = *((u16 *) d[i].addr); 887876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti else if (d[i].size == 4) 888876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti val = *((u32 *) d[i].addr); 8894269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams else if (d[i].size == 8) 8904269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams val = *((u64 *) d[i].addr); 891876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 892876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti pos += sprintf(p + pos, "%s=%d\n", d[i].name, val); 893876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 894876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 895876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti res = simple_read_from_buffer(userbuf, count, ppos, p, pos); 896876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 897876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti free_page(addr); 898876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return res; 899876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 900876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 901876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 9028973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * lbs_debugfs_write - proc write function 9038973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * 9048973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @f: file pointer 9058973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @buf: pointer to data buffer 9068973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @cnt: data number to write 9078973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @ppos: file position 908876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 9098973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * returns: amount of data written 910876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 9111007832103d016d1563fab71d4cf2b057a0bccebHolger Schurigstatic ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, 912876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti size_t cnt, loff_t *ppos) 913876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 914876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int r, i; 915876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *pdata; 916876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *p; 917876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *p0; 918876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *p1; 919876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti char *p2; 92057674308d00b5ebb639ce53d388e61728e0c7f72Joe Perches struct debug_data *d = f->private_data; 921876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 922655b4d16ac5e551e5c8dac5812156edfd87bf822Jesper Juhl pdata = kmalloc(cnt, GFP_KERNEL); 923876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (pdata == NULL) 924876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 0; 925876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 926876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (copy_from_user(pdata, buf, cnt)) { 9279012b28a407511fb355f6d2176a12d4653489672Holger Schurig lbs_deb_debugfs("Copy from user failed\n"); 928876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti kfree(pdata); 929876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return 0; 930876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 931876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 932876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p0 = pdata; 933876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i = 0; i < num_of_items; i++) { 934876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti do { 935876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p = strstr(p0, d[i].name); 936876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (p == NULL) 937876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti break; 938876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p1 = strchr(p, '\n'); 939876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (p1 == NULL) 940876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti break; 941876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p0 = p1++; 942876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p2 = strchr(p, '='); 943876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!p2) 944876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti break; 945876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti p2++; 946d2f11e0991e3794f11d851b7ee0d98e064b10333Tony Breeds r = simple_strtoul(p2, NULL, 0); 947876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (d[i].size == 1) 948876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *((u8 *) d[i].addr) = (u8) r; 949876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti else if (d[i].size == 2) 950876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *((u16 *) d[i].addr) = (u16) r; 951876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti else if (d[i].size == 4) 952876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti *((u32 *) d[i].addr) = (u32) r; 9534269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams else if (d[i].size == 8) 9544269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams *((u64 *) d[i].addr) = (u64) r; 955876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti break; 956876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } while (1); 957876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti } 958876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti kfree(pdata); 959876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 9604269e2ad83036e1d8c076b1f1348f879a93be008Dan Williams return (ssize_t)cnt; 961876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 962876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 9634101dec9ca64d40f0d673f0a40ba46ba2c60e117Jan Engelhardtstatic const struct file_operations lbs_debug_fops = { 964876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .owner = THIS_MODULE, 965876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti .open = open_file_generic, 9661007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig .write = lbs_debugfs_write, 9671007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig .read = lbs_debugfs_read, 9686038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 969876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti}; 970876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 971876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti/** 9728973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * lbs_debug_init - create debug proc file 9738973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * 9748973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * @priv: pointer to &struct lbs_private 975876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti * 9768973a6e770fc891f92daacbc1c92c7cd396fcf7eRandy Dunlap * returns: N/A 977876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti */ 978e98a88dd33b7188ce84533e128101dd9630ae592Holger Schurigstatic void lbs_debug_init(struct lbs_private *priv) 979876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti{ 980876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti int i; 981876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 982876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti if (!priv->debugfs_dir) 983876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti return; 984876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 985876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti for (i = 0; i < num_of_items; i++) 986aa21c004f80bdf943736c62dccf0c0398d7824f3David Woodhouse items[i].addr += (size_t) priv; 987876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti 988876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_debug = debugfs_create_file("debug", 0644, 989876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti priv->debugfs_dir, &items[0], 9901007832103d016d1563fab71d4cf2b057a0bccebHolger Schurig &lbs_debug_fops); 991876c9d3aeb989cf1961f2c228d309ba5dcfb1172Marcelo Tosatti} 99246868202b2dd22156460a220553a223f406f4f22Holger Schurig#endif 993