xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/smac/ssv6xxx_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3  * Copyright (c) 2015 iComm Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <linux/nl80211.h>
18 #include <linux/etherdevice.h>
19 #include <linux/delay.h>
20 #include <linux/version.h>
21 #include <linux/time.h>
22 #include <net/mac80211.h>
23 #include <ssv6200.h>
24 #include "dev.h"
25 #include "ssv6xxx_debugfs.h"
26 #ifdef CONFIG_SSV6XXX_DEBUGFS
27 #define QUEUE_STATUS_BUF_SIZE (4096)
queue_status_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)28 static ssize_t queue_status_read (struct file *file,
29                                   char __user *user_buf, size_t count,
30                                   loff_t *ppos)
31 {
32     struct ssv_softc *sc = (struct ssv_softc *)file->private_data;
33     char *status_buf = kzalloc(QUEUE_STATUS_BUF_SIZE, GFP_KERNEL);
34     ssize_t status_size;
35     ssize_t ret;
36     if (!status_buf)
37         return -ENOMEM;
38     status_size = ssv6xxx_tx_queue_status_dump(sc, status_buf,
39                                        QUEUE_STATUS_BUF_SIZE);
40     ret = simple_read_from_buffer(user_buf, count, ppos, status_buf,
41                                   status_size);
42     kfree(status_buf);
43     return ret;
44 }
queue_status_open(struct inode * inode,struct file * file)45 static int queue_status_open (struct inode *inode, struct file *file)
46 {
47     file->private_data = inode->i_private;
48     return 0;
49 }
50 static const struct file_operations queue_status_fops
51     = { .read = queue_status_read,
52         .open = queue_status_open };
53 #endif
ssv6xxx_init_debugfs(struct ssv_softc * sc,const char * name)54 int ssv6xxx_init_debugfs (struct ssv_softc *sc, const char *name)
55 {
56 #ifdef CONFIG_SSV6XXX_DEBUGFS
57     struct ieee80211_hw *hw = sc->hw;
58     struct dentry *phy_debugfs_dir = hw->wiphy->debugfsdir;
59     struct dentry *drv_debugfs_dir;
60     drv_debugfs_dir = debugfs_create_dir(name, phy_debugfs_dir);
61     if (!drv_debugfs_dir)
62     {
63         dev_err(sc->dev, "Failed to create debugfs.\n");
64         return -ENOMEM;
65     }
66     sc->debugfs_dir = drv_debugfs_dir;
67     sc->sh->hci.hci_ops->hci_init_debugfs(sc->debugfs_dir);
68     debugfs_create_file("queue_status", 00444, drv_debugfs_dir,
69                         sc, &queue_status_fops);
70 #endif
71     return 0;
72 }
ssv6xxx_deinit_debugfs(struct ssv_softc * sc)73 void ssv6xxx_deinit_debugfs (struct ssv_softc *sc)
74 {
75 #ifdef CONFIG_SSV6XXX_DEBUGFS
76     if (!sc->debugfs_dir)
77         return;
78     sc->sh->hci.hci_ops->hci_deinit_debugfs();
79     debugfs_remove_recursive(sc->debugfs_dir);
80     sc->debugfs_dir = NULL;
81 #endif
82 }
ssv6xxx_debugfs_add_interface(struct ssv_softc * sc,struct ieee80211_vif * vif)83 int ssv6xxx_debugfs_add_interface(struct ssv_softc *sc, struct ieee80211_vif *vif)
84 {
85 #ifdef CONFIG_SSV6XXX_DEBUGFS
86     struct dentry *drv_debugfs_dir = sc->debugfs_dir;
87     struct dentry *vif_debugfs_dir;
88     char vif_addr[18];
89     struct ssv_vif_priv_data *vif_priv = (struct ssv_vif_priv_data *)vif->drv_priv;
90     struct ssv_vif_info *vif_info = &sc->vif_info[vif_priv->vif_idx];
91     snprintf(vif_addr, sizeof(vif_addr), "%02X-%02X-%02X-%02X-%02X-%02X",
92             vif->addr[0], vif->addr[1], vif->addr[2],
93             vif->addr[3], vif->addr[4], vif->addr[5]);
94     vif_debugfs_dir = debugfs_create_dir(vif_addr, drv_debugfs_dir);
95     if (!vif_debugfs_dir)
96     {
97         dev_err(sc->dev, "Failed to create interface debugfs for %s.\n", vif_addr);
98         return -ENOMEM;
99     }
100     sc->debugfs_dir = drv_debugfs_dir;
101     vif_info->debugfs_dir = vif_debugfs_dir;
102 #endif
103     return 0;
104 }
ssv6xxx_debugfs_remove_interface(struct ssv_softc * sc,struct ieee80211_vif * vif)105 int ssv6xxx_debugfs_remove_interface(struct ssv_softc *sc, struct ieee80211_vif *vif)
106 {
107 #ifdef CONFIG_SSV6XXX_DEBUGFS
108     struct ssv_vif_priv_data *vif_priv = (struct ssv_vif_priv_data *)vif->drv_priv;
109     struct ssv_vif_info *vif_info = &sc->vif_info[vif_priv->vif_idx];
110     if ((vif_info->debugfs_dir == NULL) || (sc->debugfs_dir == NULL))
111         return 0;
112     debugfs_remove_recursive(vif_info->debugfs_dir);
113     vif_info->debugfs_dir = NULL;
114 #endif
115     return 0;
116 }
ssv6xxx_debugfs_remove_sta(struct ssv_softc * sc,struct ssv_sta_info * sta)117 int ssv6xxx_debugfs_remove_sta(struct ssv_softc *sc, struct ssv_sta_info *sta)
118 {
119 #ifdef CONFIG_SSV6XXX_DEBUGFS
120     struct ssv_vif_priv_data *vif_priv = (struct ssv_vif_priv_data *)sta->vif->drv_priv;
121     struct ssv_vif_info *vif_info = &sc->vif_info[vif_priv->vif_idx];
122     if ((sc->debugfs_dir == NULL) || (vif_info->debugfs_dir == NULL) || (sta->debugfs_dir == NULL))
123         return 0;
124     debugfs_remove_recursive(sta->debugfs_dir);
125     sta->debugfs_dir = NULL;
126 #endif
127     return 0;
128 }
ssv6xxx_debugfs_add_sta(struct ssv_softc * sc,struct ssv_sta_info * sta)129 int ssv6xxx_debugfs_add_sta(struct ssv_softc *sc, struct ssv_sta_info *sta)
130 {
131 #ifdef CONFIG_SSV6XXX_DEBUGFS
132     struct ssv_vif_priv_data *vif_priv = (struct ssv_vif_priv_data *)sta->vif->drv_priv;
133     struct ssv_vif_info *vif_info = &sc->vif_info[vif_priv->vif_idx];
134     struct dentry *vif_debugfs_dir = vif_info->debugfs_dir;
135     struct dentry *sta_debugfs_dir;
136     char sta_addr[18];
137     if (vif_debugfs_dir == NULL)
138         return 0;
139     snprintf(sta_addr, sizeof(sta_addr), "%02X-%02X-%02X-%02X-%02X-%02X",
140              sta->sta->addr[0], sta->sta->addr[1], sta->sta->addr[2],
141              sta->sta->addr[3], sta->sta->addr[4], sta->sta->addr[5]);
142     sta_debugfs_dir = debugfs_create_dir(sta_addr, vif_debugfs_dir);
143     if (!sta_debugfs_dir)
144     {
145         dev_err(sc->dev, "Failed to create interface debugfs for %s.\n", sta_addr);
146         return -ENOMEM;
147     }
148     sta->debugfs_dir = sta_debugfs_dir;
149 #endif
150     return 0;
151 }
152 #define DEBUGFS_ADD_FILE(name,parent,mode) do { \
153     if (!debugfs_create_file(#name, mode, parent, priv, \
154                  &ssv_dbgfs_##name##_ops)) \
155         goto err; \
156 } while (0)
157 #define DEBUGFS_ADD_BOOL(name,parent,ptr) do { \
158     struct dentry *__tmp; \
159     __tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \
160                     parent, ptr); \
161     if (IS_ERR(__tmp) || !__tmp) \
162         goto err; \
163 } while (0)
164 #define DEBUGFS_ADD_X32(name,parent,ptr) do { \
165     struct dentry *__tmp; \
166     __tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR, \
167                    parent, ptr); \
168     if (IS_ERR(__tmp) || !__tmp) \
169         goto err; \
170 } while (0)
171 #define DEBUGFS_ADD_U32(name,parent,ptr,mode) do { \
172     struct dentry *__tmp; \
173     __tmp = debugfs_create_u32(#name, mode, \
174                    parent, ptr); \
175     if (IS_ERR(__tmp) || !__tmp) \
176         goto err; \
177 } while (0)
178 #define DEBUGFS_READ_FUNC(name) \
179 static ssize_t ssv_dbgfs_##name##_read(struct file *file, \
180                     char __user *user_buf, \
181                     size_t count, loff_t *ppos);
182 #define DEBUGFS_WRITE_FUNC(name) \
183 static ssize_t ssv_dbgfs_##name##_write(struct file *file, \
184                     const char __user *user_buf, \
185                     size_t count, loff_t *ppos);
186 #define DEBUGFS_READ_FILE_OPS(name) \
187     DEBUGFS_READ_FUNC(name); \
188 static const struct file_operations ssv_dbgfs_##name##_ops = { \
189     .read = ssv_dbgfs_##name##_read, \
190     .open = ssv_dbgfs_open_file_generic, \
191     .llseek = generic_file_llseek, \
192 };
193 #define DEBUGFS_WRITE_FILE_OPS(name) \
194     DEBUGFS_WRITE_FUNC(name); \
195 static const struct file_operations ssv_dbgfs_##name##_ops = { \
196     .write = ssv_dbgfs_##name##_write, \
197     .open = ssv_dbgfs_open_file_generic, \
198     .llseek = generic_file_llseek, \
199 };
200 #define DEBUGFS_READ_WRITE_FILE_OPS(name) \
201     DEBUGFS_READ_FUNC(name); \
202     DEBUGFS_WRITE_FUNC(name); \
203 static const struct file_operations ssv_dbgfs_##name##_ops = { \
204     .write = ssv_dbgfs_##name##_write, \
205     .read = ssv_dbgfs_##name##_read, \
206     .open = ssv_dbgfs_open_file_generic, \
207     .llseek = generic_file_llseek, \
208 };
209