1*4882a593Smuzhiyun /** @file moal_proc.c
2*4882a593Smuzhiyun *
3*4882a593Smuzhiyun * @brief This file contains functions for proc file.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2008-2022 NXP
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This software file (the File) is distributed by NXP
9*4882a593Smuzhiyun * under the terms of the GNU General Public License Version 2, June 1991
10*4882a593Smuzhiyun * (the License). You may use, redistribute and/or modify the File in
11*4882a593Smuzhiyun * accordance with the terms and conditions of the License, a copy of which
12*4882a593Smuzhiyun * is available by writing to the Free Software Foundation, Inc.,
13*4882a593Smuzhiyun * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14*4882a593Smuzhiyun * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17*4882a593Smuzhiyun * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18*4882a593Smuzhiyun * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
19*4882a593Smuzhiyun * this warranty disclaimer.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun */
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun /********************************************************
24*4882a593Smuzhiyun Change log:
25*4882a593Smuzhiyun 10/21/2008: initial version
26*4882a593Smuzhiyun ********************************************************/
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include "moal_main.h"
29*4882a593Smuzhiyun #ifdef UAP_SUPPORT
30*4882a593Smuzhiyun #include "moal_uap.h"
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun #ifdef SDIO
33*4882a593Smuzhiyun #include "moal_sdio.h"
34*4882a593Smuzhiyun #endif
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /********************************************************
37*4882a593Smuzhiyun Local Variables
38*4882a593Smuzhiyun ********************************************************/
39*4882a593Smuzhiyun #ifdef CONFIG_PROC_FS
40*4882a593Smuzhiyun #define STATUS_PROC "wifi_status"
41*4882a593Smuzhiyun #define MWLAN_PROC "mwlan"
42*4882a593Smuzhiyun #define WLAN_PROC "adapter%d"
43*4882a593Smuzhiyun /** Proc mwlan directory entry */
44*4882a593Smuzhiyun static struct proc_dir_entry *proc_mwlan;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
47*4882a593Smuzhiyun #define PROC_DIR NULL
48*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
49*4882a593Smuzhiyun #define PROC_DIR (&proc_root)
50*4882a593Smuzhiyun #else
51*4882a593Smuzhiyun #define PROC_DIR proc_net
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #ifdef STA_SUPPORT
55*4882a593Smuzhiyun static char *szModes[] = {
56*4882a593Smuzhiyun "Unknown",
57*4882a593Smuzhiyun "Managed",
58*4882a593Smuzhiyun "Ad-hoc",
59*4882a593Smuzhiyun "Auto",
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun #endif
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /********************************************************
64*4882a593Smuzhiyun Global Variables
65*4882a593Smuzhiyun ********************************************************/
66*4882a593Smuzhiyun int wifi_status;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /********************************************************
69*4882a593Smuzhiyun Local Functions
70*4882a593Smuzhiyun ********************************************************/
71*4882a593Smuzhiyun /**
72*4882a593Smuzhiyun * @brief Proc read function for info
73*4882a593Smuzhiyun *
74*4882a593Smuzhiyun * @param sfp pointer to seq_file structure
75*4882a593Smuzhiyun * @param data
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * @return Number of output data
78*4882a593Smuzhiyun */
woal_info_proc_read(struct seq_file * sfp,void * data)79*4882a593Smuzhiyun static int woal_info_proc_read(struct seq_file *sfp, void *data)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun struct net_device *netdev = (struct net_device *)sfp->private;
82*4882a593Smuzhiyun char fmt[MLAN_MAX_VER_STR_LEN];
83*4882a593Smuzhiyun moal_private *priv = (moal_private *)netdev_priv(netdev);
84*4882a593Smuzhiyun mlan_fw_info fw_info;
85*4882a593Smuzhiyun #ifdef STA_SUPPORT
86*4882a593Smuzhiyun int i = 0;
87*4882a593Smuzhiyun moal_handle *handle = NULL;
88*4882a593Smuzhiyun mlan_bss_info info;
89*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
90*4882a593Smuzhiyun struct dev_mc_list *mcptr = netdev->mc_list;
91*4882a593Smuzhiyun int mc_count = netdev->mc_count;
92*4882a593Smuzhiyun #else
93*4882a593Smuzhiyun struct netdev_hw_addr *mcptr = NULL;
94*4882a593Smuzhiyun int mc_count = netdev_mc_count(netdev);
95*4882a593Smuzhiyun #endif /* < 2.6.35 */
96*4882a593Smuzhiyun #else
97*4882a593Smuzhiyun #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
98*4882a593Smuzhiyun int i = 0;
99*4882a593Smuzhiyun #endif /* >= 2.6.29 */
100*4882a593Smuzhiyun #endif
101*4882a593Smuzhiyun #ifdef UAP_SUPPORT
102*4882a593Smuzhiyun mlan_ds_uap_stats ustats;
103*4882a593Smuzhiyun #endif
104*4882a593Smuzhiyun union {
105*4882a593Smuzhiyun t_u32 l;
106*4882a593Smuzhiyun t_u8 c[4];
107*4882a593Smuzhiyun } ver;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun fw_info.uuid_lo = fw_info.uuid_hi = 0x0ULL;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun ENTER();
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (priv == NULL)
114*4882a593Smuzhiyun goto exit;
115*4882a593Smuzhiyun #ifdef STA_SUPPORT
116*4882a593Smuzhiyun handle = priv->phandle;
117*4882a593Smuzhiyun if (handle == NULL)
118*4882a593Smuzhiyun goto exit;
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (!MODULE_GET) {
122*4882a593Smuzhiyun LEAVE();
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun memset(fmt, 0, sizeof(fmt));
127*4882a593Smuzhiyun #ifdef UAP_SUPPORT
128*4882a593Smuzhiyun memset(&ustats, 0, sizeof(ustats));
129*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
130*4882a593Smuzhiyun seq_printf(sfp, "driver_name = "
131*4882a593Smuzhiyun "\"uap\"\n");
132*4882a593Smuzhiyun woal_uap_get_version(priv, fmt, sizeof(fmt) - 1);
133*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
134*4882a593Smuzhiyun woal_uap_get_stats(priv, MOAL_IOCTL_WAIT, &ustats)) {
135*4882a593Smuzhiyun MODULE_PUT;
136*4882a593Smuzhiyun LEAVE();
137*4882a593Smuzhiyun return -EFAULT;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun #endif /* UAP_SUPPORT*/
141*4882a593Smuzhiyun #ifdef STA_SUPPORT
142*4882a593Smuzhiyun memset(&info, 0, sizeof(info));
143*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
144*4882a593Smuzhiyun woal_get_version(handle, fmt, sizeof(fmt) - 1);
145*4882a593Smuzhiyun if (MLAN_STATUS_SUCCESS !=
146*4882a593Smuzhiyun woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &info)) {
147*4882a593Smuzhiyun MODULE_PUT;
148*4882a593Smuzhiyun LEAVE();
149*4882a593Smuzhiyun return -EFAULT;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun seq_printf(sfp, "driver_name = "
152*4882a593Smuzhiyun "\"wlan\"\n");
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun #endif
155*4882a593Smuzhiyun seq_printf(sfp, "driver_version = %s", fmt);
156*4882a593Smuzhiyun seq_printf(sfp, "\ninterface_name=\"%s\"\n", netdev->name);
157*4882a593Smuzhiyun ver.l = handle->fw_release_number;
158*4882a593Smuzhiyun seq_printf(sfp, "firmware_major_version=%u.%u.%u\n", ver.c[2], ver.c[1],
159*4882a593Smuzhiyun ver.c[0]);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
162*4882a593Smuzhiyun if (fw_info.uuid_lo || fw_info.uuid_hi)
163*4882a593Smuzhiyun seq_printf(sfp, "uuid = %llx%llx\n", fw_info.uuid_lo,
164*4882a593Smuzhiyun fw_info.uuid_hi);
165*4882a593Smuzhiyun #ifdef WIFI_DIRECT_SUPPORT
166*4882a593Smuzhiyun if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) {
167*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA)
168*4882a593Smuzhiyun seq_printf(sfp, "bss_mode = \"WIFIDIRECT-Client\"\n");
169*4882a593Smuzhiyun else
170*4882a593Smuzhiyun seq_printf(sfp, "bss_mode = \"WIFIDIRECT-GO\"\n");
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun #endif
173*4882a593Smuzhiyun #ifdef STA_SUPPORT
174*4882a593Smuzhiyun if (priv->bss_type == MLAN_BSS_TYPE_STA)
175*4882a593Smuzhiyun seq_printf(sfp, "bss_mode =\"%s\"\n", szModes[info.bss_mode]);
176*4882a593Smuzhiyun #endif
177*4882a593Smuzhiyun seq_printf(sfp, "media_state=\"%s\"\n",
178*4882a593Smuzhiyun ((priv->media_connected == MFALSE) ? "Disconnected" :
179*4882a593Smuzhiyun "Connected"));
180*4882a593Smuzhiyun seq_printf(sfp, "mac_address=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
181*4882a593Smuzhiyun netdev->dev_addr[0], netdev->dev_addr[1],
182*4882a593Smuzhiyun netdev->dev_addr[2], netdev->dev_addr[3],
183*4882a593Smuzhiyun netdev->dev_addr[4], netdev->dev_addr[5]);
184*4882a593Smuzhiyun #ifdef STA_SUPPORT
185*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) {
186*4882a593Smuzhiyun seq_printf(sfp, "multicast_count=\"%d\"\n", mc_count);
187*4882a593Smuzhiyun seq_printf(sfp, "essid=\"%s\"\n", info.ssid.ssid);
188*4882a593Smuzhiyun seq_printf(sfp, "bssid=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
189*4882a593Smuzhiyun info.bssid[0], info.bssid[1], info.bssid[2],
190*4882a593Smuzhiyun info.bssid[3], info.bssid[4], info.bssid[5]);
191*4882a593Smuzhiyun seq_printf(sfp, "channel=\"%d\"\n", (int)info.bss_chan);
192*4882a593Smuzhiyun seq_printf(sfp, "region_code = \"%02x\"\n",
193*4882a593Smuzhiyun (t_u8)info.region_code);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /*
196*4882a593Smuzhiyun * Put out the multicast list
197*4882a593Smuzhiyun */
198*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
199*4882a593Smuzhiyun for (i = 0; i < netdev->mc_count; i++) {
200*4882a593Smuzhiyun seq_printf(
201*4882a593Smuzhiyun sfp,
202*4882a593Smuzhiyun "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
203*4882a593Smuzhiyun i, mcptr->dmi_addr[0], mcptr->dmi_addr[1],
204*4882a593Smuzhiyun mcptr->dmi_addr[2], mcptr->dmi_addr[3],
205*4882a593Smuzhiyun mcptr->dmi_addr[4], mcptr->dmi_addr[5]);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun mcptr = mcptr->next;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun #else
210*4882a593Smuzhiyun netdev_for_each_mc_addr (mcptr, netdev)
211*4882a593Smuzhiyun seq_printf(
212*4882a593Smuzhiyun sfp,
213*4882a593Smuzhiyun "multicast_address[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
214*4882a593Smuzhiyun i++, mcptr->addr[0], mcptr->addr[1],
215*4882a593Smuzhiyun mcptr->addr[2], mcptr->addr[3], mcptr->addr[4],
216*4882a593Smuzhiyun mcptr->addr[5]);
217*4882a593Smuzhiyun #endif /* < 2.6.35 */
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun #endif
220*4882a593Smuzhiyun seq_printf(sfp, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
221*4882a593Smuzhiyun seq_printf(sfp, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
222*4882a593Smuzhiyun seq_printf(sfp, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
223*4882a593Smuzhiyun seq_printf(sfp, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
224*4882a593Smuzhiyun seq_printf(sfp, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
225*4882a593Smuzhiyun seq_printf(sfp, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
226*4882a593Smuzhiyun seq_printf(sfp, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
227*4882a593Smuzhiyun seq_printf(sfp, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
228*4882a593Smuzhiyun seq_printf(sfp, "carrier %s\n",
229*4882a593Smuzhiyun ((netif_carrier_ok(priv->netdev)) ? "on" : "off"));
230*4882a593Smuzhiyun #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
231*4882a593Smuzhiyun for (i = 0; i < (int)netdev->num_tx_queues; i++) {
232*4882a593Smuzhiyun seq_printf(sfp, "tx queue %d: %s\n", i,
233*4882a593Smuzhiyun ((netif_tx_queue_stopped(
234*4882a593Smuzhiyun netdev_get_tx_queue(netdev, 0))) ?
235*4882a593Smuzhiyun "stopped" :
236*4882a593Smuzhiyun "started"));
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun #else
239*4882a593Smuzhiyun seq_printf(sfp, "tx queue %s\n",
240*4882a593Smuzhiyun ((netif_queue_stopped(priv->netdev)) ? "stopped" :
241*4882a593Smuzhiyun "started"));
242*4882a593Smuzhiyun #endif
243*4882a593Smuzhiyun #ifdef UAP_SUPPORT
244*4882a593Smuzhiyun if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
245*4882a593Smuzhiyun seq_printf(sfp, "tkip_mic_failures = %u\n",
246*4882a593Smuzhiyun ustats.tkip_mic_failures);
247*4882a593Smuzhiyun seq_printf(sfp, "ccmp_decrypt_errors = %u\n",
248*4882a593Smuzhiyun ustats.ccmp_decrypt_errors);
249*4882a593Smuzhiyun seq_printf(sfp, "wep_undecryptable_count = %u\n",
250*4882a593Smuzhiyun ustats.wep_undecryptable_count);
251*4882a593Smuzhiyun seq_printf(sfp, "wep_icv_error_count = %u\n",
252*4882a593Smuzhiyun ustats.wep_icv_error_count);
253*4882a593Smuzhiyun seq_printf(sfp, "decrypt_failure_count = %u\n",
254*4882a593Smuzhiyun ustats.decrypt_failure_count);
255*4882a593Smuzhiyun seq_printf(sfp, "mcast_tx_count = %u\n", ustats.mcast_tx_count);
256*4882a593Smuzhiyun seq_printf(sfp, "failed_count = %u\n", ustats.failed_count);
257*4882a593Smuzhiyun seq_printf(sfp, "retry_count = %u\n", ustats.retry_count);
258*4882a593Smuzhiyun seq_printf(sfp, "multiple_retry_count = %u\n",
259*4882a593Smuzhiyun ustats.multi_retry_count);
260*4882a593Smuzhiyun seq_printf(sfp, "frame_duplicate_count = %u\n",
261*4882a593Smuzhiyun ustats.frame_dup_count);
262*4882a593Smuzhiyun seq_printf(sfp, "rts_success_count = %u\n",
263*4882a593Smuzhiyun ustats.rts_success_count);
264*4882a593Smuzhiyun seq_printf(sfp, "rts_failure_count = %u\n",
265*4882a593Smuzhiyun ustats.rts_failure_count);
266*4882a593Smuzhiyun seq_printf(sfp, "ack_failure_count = %u\n",
267*4882a593Smuzhiyun ustats.ack_failure_count);
268*4882a593Smuzhiyun seq_printf(sfp, "rx_fragment_count = %u\n",
269*4882a593Smuzhiyun ustats.rx_fragment_count);
270*4882a593Smuzhiyun seq_printf(sfp, "mcast_rx_frame_count = %u\n",
271*4882a593Smuzhiyun ustats.mcast_rx_frame_count);
272*4882a593Smuzhiyun seq_printf(sfp, "fcs_error_count = %u\n",
273*4882a593Smuzhiyun ustats.fcs_error_count);
274*4882a593Smuzhiyun seq_printf(sfp, "tx_frame_count = %u\n", ustats.tx_frame_count);
275*4882a593Smuzhiyun seq_printf(sfp, "rsna_tkip_cm_invoked = %u\n",
276*4882a593Smuzhiyun ustats.rsna_tkip_cm_invoked);
277*4882a593Smuzhiyun seq_printf(sfp, "rsna_4way_hshk_failures = %u\n",
278*4882a593Smuzhiyun ustats.rsna_4way_hshk_failures);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun #endif /* UAP_SUPPORT */
281*4882a593Smuzhiyun seq_printf(sfp, "=== tp_acnt.on:%d drop_point:%d ===\n",
282*4882a593Smuzhiyun handle->tp_acnt.on, handle->tp_acnt.drop_point);
283*4882a593Smuzhiyun seq_printf(sfp, "====Tx accounting====\n");
284*4882a593Smuzhiyun for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
285*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx packets : %lu\n", i,
286*4882a593Smuzhiyun handle->tp_acnt.tx_packets[i]);
287*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx packets last: %lu\n", i,
288*4882a593Smuzhiyun handle->tp_acnt.tx_packets_last[i]);
289*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx packets rate: %lu\n", i,
290*4882a593Smuzhiyun handle->tp_acnt.tx_packets_rate[i]);
291*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx bytes : %lu\n", i,
292*4882a593Smuzhiyun handle->tp_acnt.tx_bytes[i]);
293*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx bytes last : %lu\n", i,
294*4882a593Smuzhiyun handle->tp_acnt.tx_bytes_last[i]);
295*4882a593Smuzhiyun seq_printf(sfp, "[%d] Tx bytes rate : %luMbps\n", i,
296*4882a593Smuzhiyun handle->tp_acnt.tx_bytes_rate[i] * 8 / 1024 / 1024);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu cnt : %lu\n",
299*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_cnt);
300*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu cnt last : %lu\n",
301*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_cnt_last);
302*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu cnt rate : %lu\n",
303*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_cnt_rate);
304*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu pkt cnt : %lu\n",
305*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_pkt_cnt);
306*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu pkt cnt last : %lu\n",
307*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_pkt_cnt_last);
308*4882a593Smuzhiyun seq_printf(sfp, "Tx amsdu pkt cnt rate : %lu\n",
309*4882a593Smuzhiyun handle->tp_acnt.tx_amsdu_pkt_cnt_rate);
310*4882a593Smuzhiyun seq_printf(sfp, "Tx intr cnt : %lu\n",
311*4882a593Smuzhiyun handle->tp_acnt.tx_intr_cnt);
312*4882a593Smuzhiyun seq_printf(sfp, "Tx intr last : %lu\n",
313*4882a593Smuzhiyun handle->tp_acnt.tx_intr_last);
314*4882a593Smuzhiyun seq_printf(sfp, "Tx intr rate : %lu\n",
315*4882a593Smuzhiyun handle->tp_acnt.tx_intr_rate);
316*4882a593Smuzhiyun seq_printf(sfp, "Tx pending : %lu\n",
317*4882a593Smuzhiyun handle->tp_acnt.tx_pending);
318*4882a593Smuzhiyun seq_printf(sfp, "Tx xmit skb realloc : %lu\n",
319*4882a593Smuzhiyun handle->tp_acnt.tx_xmit_skb_realloc_cnt);
320*4882a593Smuzhiyun seq_printf(sfp, "Tx stop queue cnt : %lu\n",
321*4882a593Smuzhiyun handle->tp_acnt.tx_stop_queue_cnt);
322*4882a593Smuzhiyun seq_printf(sfp, "====Rx accounting====\n");
323*4882a593Smuzhiyun for (i = 0; i < MAX_TP_ACCOUNT_DROP_POINT_NUM; i++) {
324*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx packets : %lu\n", i,
325*4882a593Smuzhiyun handle->tp_acnt.rx_packets[i]);
326*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx packets last: %lu\n", i,
327*4882a593Smuzhiyun handle->tp_acnt.rx_packets_last[i]);
328*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx packets rate: %lu\n", i,
329*4882a593Smuzhiyun handle->tp_acnt.rx_packets_rate[i]);
330*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx bytes : %lu\n", i,
331*4882a593Smuzhiyun handle->tp_acnt.rx_bytes[i]);
332*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx bytes last : %lu\n", i,
333*4882a593Smuzhiyun handle->tp_acnt.rx_bytes_last[i]);
334*4882a593Smuzhiyun seq_printf(sfp, "[%d] Rx bytes rate : %luMbps\n", i,
335*4882a593Smuzhiyun handle->tp_acnt.rx_bytes_rate[i] * 8 / 1024 / 1024);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu cnt : %lu\n",
338*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_cnt);
339*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu cnt last : %lu\n",
340*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_cnt_last);
341*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu cnt rate : %lu\n",
342*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_cnt_rate);
343*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu pkt cnt : %lu\n",
344*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_pkt_cnt);
345*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu pkt cnt last : %lu\n",
346*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_pkt_cnt_last);
347*4882a593Smuzhiyun seq_printf(sfp, "Rx amsdu pkt cnt rate : %lu\n",
348*4882a593Smuzhiyun handle->tp_acnt.rx_amsdu_pkt_cnt_rate);
349*4882a593Smuzhiyun seq_printf(sfp, "Rx intr cnt : %lu\n",
350*4882a593Smuzhiyun handle->tp_acnt.rx_intr_cnt);
351*4882a593Smuzhiyun seq_printf(sfp, "Rx intr last : %lu\n",
352*4882a593Smuzhiyun handle->tp_acnt.rx_intr_last);
353*4882a593Smuzhiyun seq_printf(sfp, "Rx intr rate : %lu\n",
354*4882a593Smuzhiyun handle->tp_acnt.rx_intr_rate);
355*4882a593Smuzhiyun seq_printf(sfp, "Rx pending : %lu\n",
356*4882a593Smuzhiyun handle->tp_acnt.rx_pending);
357*4882a593Smuzhiyun seq_printf(sfp, "Rx pause : %lu\n",
358*4882a593Smuzhiyun handle->tp_acnt.rx_paused_cnt);
359*4882a593Smuzhiyun seq_printf(sfp, "Rx rdptr full cnt : %lu\n",
360*4882a593Smuzhiyun handle->tp_acnt.rx_rdptr_full_cnt);
361*4882a593Smuzhiyun exit:
362*4882a593Smuzhiyun LEAVE();
363*4882a593Smuzhiyun MODULE_PUT;
364*4882a593Smuzhiyun return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
woal_info_proc_open(struct inode * inode,struct file * file)367*4882a593Smuzhiyun static int woal_info_proc_open(struct inode *inode, struct file *file)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
370*4882a593Smuzhiyun return single_open(file, woal_info_proc_read, pde_data(inode));
371*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
372*4882a593Smuzhiyun return single_open(file, woal_info_proc_read, PDE_DATA(inode));
373*4882a593Smuzhiyun #else
374*4882a593Smuzhiyun return single_open(file, woal_info_proc_read, PDE(inode)->data);
375*4882a593Smuzhiyun #endif
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
379*4882a593Smuzhiyun static const struct proc_ops info_proc_fops = {
380*4882a593Smuzhiyun .proc_open = woal_info_proc_open,
381*4882a593Smuzhiyun .proc_read = seq_read,
382*4882a593Smuzhiyun .proc_lseek = seq_lseek,
383*4882a593Smuzhiyun .proc_release = single_release,
384*4882a593Smuzhiyun };
385*4882a593Smuzhiyun #else
386*4882a593Smuzhiyun static const struct file_operations info_proc_fops = {
387*4882a593Smuzhiyun .owner = THIS_MODULE,
388*4882a593Smuzhiyun .open = woal_info_proc_open,
389*4882a593Smuzhiyun .read = seq_read,
390*4882a593Smuzhiyun .llseek = seq_lseek,
391*4882a593Smuzhiyun .release = single_release,
392*4882a593Smuzhiyun };
393*4882a593Smuzhiyun #endif
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun #ifdef SDIO
396*4882a593Smuzhiyun #define CMD52_STR_LEN 50
397*4882a593Smuzhiyun /*
398*4882a593Smuzhiyun * @brief Parse cmd52 string
399*4882a593Smuzhiyun *
400*4882a593Smuzhiyun * @param buffer A pointer user buffer
401*4882a593Smuzhiyun * @param len Length user buffer
402*4882a593Smuzhiyun * @param func Parsed func number
403*4882a593Smuzhiyun * @param reg Parsed reg value
404*4882a593Smuzhiyun * @param val Parsed value to set
405*4882a593Smuzhiyun * @return BT_STATUS_SUCCESS
406*4882a593Smuzhiyun */
parse_cmd52_string(const char * buffer,size_t len,int * func,int * reg,int * val)407*4882a593Smuzhiyun static int parse_cmd52_string(const char *buffer, size_t len, int *func,
408*4882a593Smuzhiyun int *reg, int *val)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun int ret = MLAN_STATUS_SUCCESS;
411*4882a593Smuzhiyun char *string = NULL;
412*4882a593Smuzhiyun char *pos = NULL;
413*4882a593Smuzhiyun gfp_t flag;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun ENTER();
416*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
417*4882a593Smuzhiyun string = kzalloc(CMD52_STR_LEN, flag);
418*4882a593Smuzhiyun if (string == NULL)
419*4882a593Smuzhiyun return -ENOMEM;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun moal_memcpy_ext(NULL, string, buffer + strlen("sdcmd52rw="),
422*4882a593Smuzhiyun len - strlen("sdcmd52rw="), CMD52_STR_LEN - 1);
423*4882a593Smuzhiyun string = strstrip(string);
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun *func = -1;
426*4882a593Smuzhiyun *reg = -1;
427*4882a593Smuzhiyun *val = -1;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun /* Get func */
430*4882a593Smuzhiyun pos = strsep(&string, " \t");
431*4882a593Smuzhiyun if (pos)
432*4882a593Smuzhiyun *func = woal_string_to_number(pos);
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* Get reg */
435*4882a593Smuzhiyun pos = strsep(&string, " \t");
436*4882a593Smuzhiyun if (pos)
437*4882a593Smuzhiyun *reg = woal_string_to_number(pos);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Get val (optional) */
440*4882a593Smuzhiyun pos = strsep(&string, " \t");
441*4882a593Smuzhiyun if (pos)
442*4882a593Smuzhiyun *val = woal_string_to_number(pos);
443*4882a593Smuzhiyun kfree(string);
444*4882a593Smuzhiyun LEAVE();
445*4882a593Smuzhiyun return ret;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun #endif
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /**
450*4882a593Smuzhiyun * @brief config proc write function
451*4882a593Smuzhiyun *
452*4882a593Smuzhiyun * @param f file pointer
453*4882a593Smuzhiyun * @param buf pointer to data buffer
454*4882a593Smuzhiyun * @param count data number to write
455*4882a593Smuzhiyun * @param off Offset
456*4882a593Smuzhiyun *
457*4882a593Smuzhiyun * @return number of data
458*4882a593Smuzhiyun */
woal_config_write(struct file * f,const char __user * buf,size_t count,loff_t * off)459*4882a593Smuzhiyun static ssize_t woal_config_write(struct file *f, const char __user *buf,
460*4882a593Smuzhiyun size_t count, loff_t *off)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun char databuf[200];
463*4882a593Smuzhiyun char *line = NULL;
464*4882a593Smuzhiyun t_u32 config_data = 0;
465*4882a593Smuzhiyun struct seq_file *sfp = f->private_data;
466*4882a593Smuzhiyun moal_handle *handle = (moal_handle *)sfp->private;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun #ifdef SDIO
469*4882a593Smuzhiyun int func = 0, reg = 0, val = 0;
470*4882a593Smuzhiyun #endif
471*4882a593Smuzhiyun moal_handle *ref_handle = NULL;
472*4882a593Smuzhiyun t_u32 cmd = 0;
473*4882a593Smuzhiyun int copy_len;
474*4882a593Smuzhiyun moal_private *priv = NULL;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun ENTER();
477*4882a593Smuzhiyun if (!MODULE_GET) {
478*4882a593Smuzhiyun LEAVE();
479*4882a593Smuzhiyun return 0;
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (count >= sizeof(databuf)) {
483*4882a593Smuzhiyun MODULE_PUT;
484*4882a593Smuzhiyun LEAVE();
485*4882a593Smuzhiyun return (int)count;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun memset(databuf, 0, sizeof(databuf));
488*4882a593Smuzhiyun copy_len = MIN((sizeof(databuf) - 1), count);
489*4882a593Smuzhiyun if (copy_from_user(databuf, buf, copy_len)) {
490*4882a593Smuzhiyun MODULE_PUT;
491*4882a593Smuzhiyun LEAVE();
492*4882a593Smuzhiyun return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun line = databuf;
495*4882a593Smuzhiyun if (!strncmp(databuf, "soft_reset", strlen("soft_reset"))) {
496*4882a593Smuzhiyun line += strlen("soft_reset") + 1;
497*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
498*4882a593Smuzhiyun PRINTM(MINFO, "soft_reset: %d\n", (int)config_data);
499*4882a593Smuzhiyun if (woal_request_soft_reset(handle) == MLAN_STATUS_SUCCESS)
500*4882a593Smuzhiyun handle->hardware_status = HardwareStatusReset;
501*4882a593Smuzhiyun else
502*4882a593Smuzhiyun PRINTM(MERROR, "Could not perform soft reset\n");
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun if (!strncmp(databuf, "drv_mode", strlen("drv_mode"))) {
505*4882a593Smuzhiyun line += strlen("drv_mode") + 1;
506*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
507*4882a593Smuzhiyun PRINTM(MINFO, "drv_mode: %d\n", (int)config_data);
508*4882a593Smuzhiyun if (config_data != (t_u32)handle->params.drv_mode)
509*4882a593Smuzhiyun if (woal_switch_drv_mode(handle, config_data) !=
510*4882a593Smuzhiyun MLAN_STATUS_SUCCESS) {
511*4882a593Smuzhiyun PRINTM(MERROR, "Could not switch drv mode\n");
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun #ifdef SDIO
515*4882a593Smuzhiyun if (IS_SD(handle->card_type)) {
516*4882a593Smuzhiyun if (!strncmp(databuf, "sdcmd52rw=", strlen("sdcmd52rw=")) &&
517*4882a593Smuzhiyun count > strlen("sdcmd52rw=")) {
518*4882a593Smuzhiyun parse_cmd52_string((const char *)databuf, (size_t)count,
519*4882a593Smuzhiyun &func, ®, &val);
520*4882a593Smuzhiyun woal_sdio_read_write_cmd52(handle, func, reg, val);
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun #endif /* SD */
524*4882a593Smuzhiyun if (!strncmp(databuf, "debug_dump", strlen("debug_dump"))) {
525*4882a593Smuzhiyun PRINTM(MERROR, "Recevie debug_dump command\n");
526*4882a593Smuzhiyun #ifdef USB
527*4882a593Smuzhiyun if (!IS_USB(handle->card_type))
528*4882a593Smuzhiyun #endif
529*4882a593Smuzhiyun handle->driver_status = MTRUE;
530*4882a593Smuzhiyun ref_handle = (moal_handle *)handle->pref_mac;
531*4882a593Smuzhiyun if (ref_handle) {
532*4882a593Smuzhiyun priv = woal_get_priv(ref_handle, MLAN_BSS_ROLE_ANY);
533*4882a593Smuzhiyun if (priv) {
534*4882a593Smuzhiyun handle->fw_dump_status = MTRUE;
535*4882a593Smuzhiyun woal_mlan_debug_info(priv);
536*4882a593Smuzhiyun woal_moal_debug_info(priv, NULL, MFALSE);
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
540*4882a593Smuzhiyun if (priv) {
541*4882a593Smuzhiyun handle->fw_dump_status = MTRUE;
542*4882a593Smuzhiyun woal_mlan_debug_info(priv);
543*4882a593Smuzhiyun woal_moal_debug_info(priv, NULL, MFALSE);
544*4882a593Smuzhiyun handle->ops.dump_fw_info(handle);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (!strncmp(databuf, "fwdump_file=", strlen("fwdump_file="))) {
549*4882a593Smuzhiyun int len = copy_len - strlen("fwdump_file=");
550*4882a593Smuzhiyun gfp_t flag;
551*4882a593Smuzhiyun if (len) {
552*4882a593Smuzhiyun kfree(handle->fwdump_fname);
553*4882a593Smuzhiyun flag = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC :
554*4882a593Smuzhiyun GFP_KERNEL;
555*4882a593Smuzhiyun handle->fwdump_fname = kzalloc(len, flag);
556*4882a593Smuzhiyun if (handle->fwdump_fname)
557*4882a593Smuzhiyun moal_memcpy_ext(handle, handle->fwdump_fname,
558*4882a593Smuzhiyun databuf +
559*4882a593Smuzhiyun strlen("fwdump_file="),
560*4882a593Smuzhiyun len - 1, len - 1);
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun if (!strncmp(databuf, "fw_reload", strlen("fw_reload"))) {
564*4882a593Smuzhiyun if (!strncmp(databuf, "fw_reload=", strlen("fw_reload="))) {
565*4882a593Smuzhiyun line += strlen("fw_reload") + 1;
566*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun #ifdef SDIO_MMC
569*4882a593Smuzhiyun else if (IS_SD(handle->card_type))
570*4882a593Smuzhiyun config_data = FW_RELOAD_SDIO_INBAND_RESET;
571*4882a593Smuzhiyun #endif
572*4882a593Smuzhiyun PRINTM(MMSG, "Request fw_reload=%d\n", config_data);
573*4882a593Smuzhiyun woal_request_fw_reload(handle, config_data);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun if (!strncmp(databuf, "drop_point=", strlen("drop_point="))) {
576*4882a593Smuzhiyun line += strlen("drop_point") + 1;
577*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
578*4882a593Smuzhiyun if (config_data) {
579*4882a593Smuzhiyun handle->tp_acnt.on = 1;
580*4882a593Smuzhiyun handle->tp_acnt.drop_point = config_data;
581*4882a593Smuzhiyun if (handle->is_tp_acnt_timer_set == MFALSE) {
582*4882a593Smuzhiyun woal_initialize_timer(&handle->tp_acnt.timer,
583*4882a593Smuzhiyun woal_tp_acnt_timer_func,
584*4882a593Smuzhiyun handle);
585*4882a593Smuzhiyun handle->is_tp_acnt_timer_set = MTRUE;
586*4882a593Smuzhiyun woal_mod_timer(&handle->tp_acnt.timer, 1000);
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun } else {
589*4882a593Smuzhiyun if (handle->is_tp_acnt_timer_set) {
590*4882a593Smuzhiyun woal_cancel_timer(&handle->tp_acnt.timer);
591*4882a593Smuzhiyun handle->is_tp_acnt_timer_set = MFALSE;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun memset((void *)&handle->tp_acnt, 0,
594*4882a593Smuzhiyun sizeof(moal_tp_acnt_t));
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
597*4882a593Smuzhiyun if (priv)
598*4882a593Smuzhiyun woal_set_tp_state(priv);
599*4882a593Smuzhiyun PRINTM(MMSG, "on=%d drop_point=%d\n", handle->tp_acnt.on,
600*4882a593Smuzhiyun handle->tp_acnt.drop_point);
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun if (!strncmp(databuf, "hssetpara=", strlen("hssetpara="))) {
603*4882a593Smuzhiyun line += strlen("hssetpara") + 1;
604*4882a593Smuzhiyun PRINTM(MCMND, "hssetpara=%s\n", line);
605*4882a593Smuzhiyun woal_process_proc_hssetpara(handle, line);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun if (!strncmp(databuf, "rf_test_mode", strlen("rf_test_mode"))) {
608*4882a593Smuzhiyun line += strlen("rf_test_mode") + 1;
609*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
610*4882a593Smuzhiyun PRINTM(MINFO, "RF test mode: %d\n", (int)config_data);
611*4882a593Smuzhiyun if (config_data != (t_u32)handle->rf_test_mode)
612*4882a593Smuzhiyun if (woal_process_rf_test_mode(handle, config_data) !=
613*4882a593Smuzhiyun MLAN_STATUS_SUCCESS)
614*4882a593Smuzhiyun PRINTM(MERROR, "Could not set RF test mode\n");
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun if (!strncmp(databuf, "tx_antenna", strlen("tx_antenna"))) {
617*4882a593Smuzhiyun line += strlen("tx_antenna") + 1;
618*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
619*4882a593Smuzhiyun cmd = MFG_CMD_TX_ANT;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun if (!strncmp(databuf, "rx_antenna", strlen("rx_antenna"))) {
622*4882a593Smuzhiyun line += strlen("rx_antenna") + 1;
623*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
624*4882a593Smuzhiyun cmd = MFG_CMD_RX_ANT;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun if (!strncmp(databuf, "radio_mode", strlen("radio_mode"))) {
627*4882a593Smuzhiyun line += strlen("radio_mode") + 1;
628*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
629*4882a593Smuzhiyun cmd = MFG_CMD_RADIO_MODE_CFG;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun if (!strncmp(databuf, "channel", strlen("channel"))) {
632*4882a593Smuzhiyun line += strlen("channel") + 1;
633*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
634*4882a593Smuzhiyun cmd = MFG_CMD_RF_CHAN;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun if (!strncmp(databuf, "band", strlen("band"))) {
637*4882a593Smuzhiyun line += strlen("band") + 1;
638*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
639*4882a593Smuzhiyun cmd = MFG_CMD_RF_BAND_AG;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun if (!strncmp(databuf, "bw", strlen("bw"))) {
642*4882a593Smuzhiyun line += strlen("bw") + 1;
643*4882a593Smuzhiyun config_data = (t_u32)woal_string_to_number(line);
644*4882a593Smuzhiyun cmd = MFG_CMD_RF_CHANNELBW;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun if (!strncmp(databuf, "get_and_reset_per", strlen("get_and_reset_per")))
647*4882a593Smuzhiyun cmd = MFG_CMD_CLR_RX_ERR;
648*4882a593Smuzhiyun if (!strncmp(databuf, "tx_power=", strlen("tx_power=")) &&
649*4882a593Smuzhiyun count > strlen("tx_power="))
650*4882a593Smuzhiyun cmd = MFG_CMD_RFPWR;
651*4882a593Smuzhiyun if (!strncmp(databuf, "tx_frame=", strlen("tx_frame=")) &&
652*4882a593Smuzhiyun count > strlen("tx_frame="))
653*4882a593Smuzhiyun cmd = MFG_CMD_TX_FRAME;
654*4882a593Smuzhiyun if (!strncmp(databuf, "tx_continuous=", strlen("tx_continuous=")) &&
655*4882a593Smuzhiyun count > strlen("tx_continuous="))
656*4882a593Smuzhiyun cmd = MFG_CMD_TX_CONT;
657*4882a593Smuzhiyun if (!strncmp(databuf, "he_tb_tx=", strlen("he_tb_tx=")) &&
658*4882a593Smuzhiyun count > strlen("he_tb_tx="))
659*4882a593Smuzhiyun cmd = MFG_CMD_CONFIG_MAC_HE_TB_TX;
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun if (cmd && handle->rf_test_mode &&
662*4882a593Smuzhiyun (woal_process_rf_test_mode_cmd(
663*4882a593Smuzhiyun handle, cmd, (const char *)databuf, (size_t)count,
664*4882a593Smuzhiyun MLAN_ACT_SET, config_data) != MLAN_STATUS_SUCCESS)) {
665*4882a593Smuzhiyun PRINTM(MERROR, "RF test mode cmd error\n");
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun if (cmd && !handle->rf_test_mode)
668*4882a593Smuzhiyun PRINTM(MERROR, "RF test mode is disabled\n");
669*4882a593Smuzhiyun MODULE_PUT;
670*4882a593Smuzhiyun LEAVE();
671*4882a593Smuzhiyun return (int)count;
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun /**
675*4882a593Smuzhiyun * @brief config proc read function
676*4882a593Smuzhiyun *
677*4882a593Smuzhiyun * @param sfp pointer to seq_file structure
678*4882a593Smuzhiyun * @param data
679*4882a593Smuzhiyun *
680*4882a593Smuzhiyun * @return number of output data
681*4882a593Smuzhiyun */
woal_config_read(struct seq_file * sfp,void * data)682*4882a593Smuzhiyun static int woal_config_read(struct seq_file *sfp, void *data)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun moal_handle *handle = (moal_handle *)sfp->private;
685*4882a593Smuzhiyun int i;
686*4882a593Smuzhiyun moal_private *priv = woal_get_priv(handle, MLAN_BSS_ROLE_ANY);
687*4882a593Smuzhiyun mlan_ds_hs_cfg hscfg;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun ENTER();
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun if (!MODULE_GET) {
692*4882a593Smuzhiyun LEAVE();
693*4882a593Smuzhiyun return 0;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun seq_printf(sfp, "hardware_status=%d\n", (int)handle->hardware_status);
697*4882a593Smuzhiyun seq_printf(sfp, "netlink_num=%d\n", (int)handle->netlink_num);
698*4882a593Smuzhiyun seq_printf(sfp, "drv_mode=%d\n", (int)handle->params.drv_mode);
699*4882a593Smuzhiyun if (priv) {
700*4882a593Smuzhiyun memset(&hscfg, 0, sizeof(mlan_ds_hs_cfg));
701*4882a593Smuzhiyun woal_set_get_hs_params(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
702*4882a593Smuzhiyun &hscfg);
703*4882a593Smuzhiyun seq_printf(sfp, "hssetpara=%d,0x%x,%d,%d\n", hscfg.conditions,
704*4882a593Smuzhiyun hscfg.gpio, hscfg.gap, hscfg.hs_wake_interval);
705*4882a593Smuzhiyun }
706*4882a593Smuzhiyun #ifdef SDIO
707*4882a593Smuzhiyun if (IS_SD(handle->card_type)) {
708*4882a593Smuzhiyun seq_printf(sfp, "sdcmd52rw=%d 0x%0x 0x%02X\n",
709*4882a593Smuzhiyun handle->cmd52_func, handle->cmd52_reg,
710*4882a593Smuzhiyun handle->cmd52_val);
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun #endif /* SD */
713*4882a593Smuzhiyun seq_printf(sfp, "rf_test_mode=%u\n", handle->rf_test_mode);
714*4882a593Smuzhiyun if (handle->rf_test_mode && handle->rf_data) {
715*4882a593Smuzhiyun seq_printf(sfp, "tx_antenna=%u\n", handle->rf_data->tx_antenna);
716*4882a593Smuzhiyun seq_printf(sfp, "rx_antenna=%u\n", handle->rf_data->rx_antenna);
717*4882a593Smuzhiyun seq_printf(sfp, "band=%u\n", handle->rf_data->band);
718*4882a593Smuzhiyun seq_printf(sfp, "bw=%u\n", handle->rf_data->bandwidth);
719*4882a593Smuzhiyun if (handle->rf_data->channel)
720*4882a593Smuzhiyun seq_printf(sfp, "channel=%u\n",
721*4882a593Smuzhiyun handle->rf_data->channel);
722*4882a593Smuzhiyun else
723*4882a593Smuzhiyun seq_printf(sfp, "channel=\n");
724*4882a593Smuzhiyun if (handle->rf_data->radio_mode[0])
725*4882a593Smuzhiyun seq_printf(sfp, "radio_mode[0]=%u\n",
726*4882a593Smuzhiyun handle->rf_data->radio_mode[0]);
727*4882a593Smuzhiyun else
728*4882a593Smuzhiyun seq_printf(sfp, "radio_mode[0]=\n");
729*4882a593Smuzhiyun if (handle->rf_data->radio_mode[1])
730*4882a593Smuzhiyun seq_printf(sfp, "radio_mode[1]=%u\n",
731*4882a593Smuzhiyun handle->rf_data->radio_mode[1]);
732*4882a593Smuzhiyun else
733*4882a593Smuzhiyun seq_printf(sfp, "radio_mode[1]=\n");
734*4882a593Smuzhiyun seq_printf(sfp, "total rx pkt count=%u\n",
735*4882a593Smuzhiyun handle->rf_data->rx_tot_pkt_count);
736*4882a593Smuzhiyun seq_printf(sfp, "rx multicast/broadcast pkt count=%u\n",
737*4882a593Smuzhiyun handle->rf_data->rx_mcast_bcast_pkt_count);
738*4882a593Smuzhiyun seq_printf(sfp, "rx fcs error pkt count=%u\n",
739*4882a593Smuzhiyun handle->rf_data->rx_pkt_fcs_err_count);
740*4882a593Smuzhiyun if (handle->rf_data->tx_power_data[0]) {
741*4882a593Smuzhiyun seq_printf(sfp, "tx_power=%u",
742*4882a593Smuzhiyun handle->rf_data->tx_power_data[0]);
743*4882a593Smuzhiyun seq_printf(sfp, " %u",
744*4882a593Smuzhiyun handle->rf_data->tx_power_data[1]);
745*4882a593Smuzhiyun seq_printf(sfp, " %u\n",
746*4882a593Smuzhiyun handle->rf_data->tx_power_data[2]);
747*4882a593Smuzhiyun } else
748*4882a593Smuzhiyun seq_printf(sfp, "tx_power=\n");
749*4882a593Smuzhiyun seq_printf(sfp, "tx_continuous=%u",
750*4882a593Smuzhiyun handle->rf_data->tx_cont_data[0]);
751*4882a593Smuzhiyun if (handle->rf_data->tx_cont_data[0] == MTRUE) {
752*4882a593Smuzhiyun seq_printf(sfp, " %u",
753*4882a593Smuzhiyun handle->rf_data->tx_cont_data[1]);
754*4882a593Smuzhiyun seq_printf(sfp, " 0x%x",
755*4882a593Smuzhiyun handle->rf_data->tx_cont_data[2]);
756*4882a593Smuzhiyun for (i = 3; i < 6; i++)
757*4882a593Smuzhiyun seq_printf(sfp, " %u",
758*4882a593Smuzhiyun handle->rf_data->tx_cont_data[i]);
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun seq_printf(sfp, "\n");
761*4882a593Smuzhiyun seq_printf(sfp, "tx_frame=%u",
762*4882a593Smuzhiyun handle->rf_data->tx_frame_data[0]);
763*4882a593Smuzhiyun if (handle->rf_data->tx_frame_data[0] == MTRUE) {
764*4882a593Smuzhiyun seq_printf(sfp, " %u",
765*4882a593Smuzhiyun handle->rf_data->tx_frame_data[1]);
766*4882a593Smuzhiyun seq_printf(sfp, " 0x%x",
767*4882a593Smuzhiyun handle->rf_data->tx_frame_data[2]);
768*4882a593Smuzhiyun for (i = 3; i < 13; i++)
769*4882a593Smuzhiyun seq_printf(sfp, " %u",
770*4882a593Smuzhiyun handle->rf_data->tx_frame_data[i]);
771*4882a593Smuzhiyun for (i = 13; i < 20; i++)
772*4882a593Smuzhiyun seq_printf(sfp, " %d",
773*4882a593Smuzhiyun handle->rf_data->tx_frame_data[i]);
774*4882a593Smuzhiyun seq_printf(sfp, " %02x:%02x:%02x:%02x:%02x:%02x",
775*4882a593Smuzhiyun handle->rf_data->bssid[0],
776*4882a593Smuzhiyun handle->rf_data->bssid[1],
777*4882a593Smuzhiyun handle->rf_data->bssid[2],
778*4882a593Smuzhiyun handle->rf_data->bssid[3],
779*4882a593Smuzhiyun handle->rf_data->bssid[4],
780*4882a593Smuzhiyun handle->rf_data->bssid[5]);
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun seq_printf(sfp, "\n");
783*4882a593Smuzhiyun seq_printf(sfp, "he_tb_tx=%u", handle->rf_data->he_tb_tx[0]);
784*4882a593Smuzhiyun if (handle->rf_data->he_tb_tx[0] == MTRUE) {
785*4882a593Smuzhiyun seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[1]);
786*4882a593Smuzhiyun seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[2]);
787*4882a593Smuzhiyun seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[3]);
788*4882a593Smuzhiyun seq_printf(sfp, " %u", handle->rf_data->he_tb_tx[4]);
789*4882a593Smuzhiyun }
790*4882a593Smuzhiyun seq_printf(sfp, "\n");
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun MODULE_PUT;
793*4882a593Smuzhiyun LEAVE();
794*4882a593Smuzhiyun return 0;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
woal_config_proc_open(struct inode * inode,struct file * file)797*4882a593Smuzhiyun static int woal_config_proc_open(struct inode *inode, struct file *file)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
800*4882a593Smuzhiyun return single_open(file, woal_config_read, pde_data(inode));
801*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
802*4882a593Smuzhiyun return single_open(file, woal_config_read, PDE_DATA(inode));
803*4882a593Smuzhiyun #else
804*4882a593Smuzhiyun return single_open(file, woal_config_read, PDE(inode)->data);
805*4882a593Smuzhiyun #endif
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
809*4882a593Smuzhiyun static const struct proc_ops config_proc_fops = {
810*4882a593Smuzhiyun .proc_open = woal_config_proc_open,
811*4882a593Smuzhiyun .proc_read = seq_read,
812*4882a593Smuzhiyun .proc_lseek = seq_lseek,
813*4882a593Smuzhiyun .proc_release = single_release,
814*4882a593Smuzhiyun .proc_write = woal_config_write,
815*4882a593Smuzhiyun };
816*4882a593Smuzhiyun #else
817*4882a593Smuzhiyun static const struct file_operations config_proc_fops = {
818*4882a593Smuzhiyun .owner = THIS_MODULE,
819*4882a593Smuzhiyun .open = woal_config_proc_open,
820*4882a593Smuzhiyun .read = seq_read,
821*4882a593Smuzhiyun .llseek = seq_lseek,
822*4882a593Smuzhiyun .release = single_release,
823*4882a593Smuzhiyun .write = woal_config_write,
824*4882a593Smuzhiyun };
825*4882a593Smuzhiyun #endif
826*4882a593Smuzhiyun
woal_drv_dump_read(struct seq_file * sfp,void * data)827*4882a593Smuzhiyun static int woal_drv_dump_read(struct seq_file *sfp, void *data)
828*4882a593Smuzhiyun {
829*4882a593Smuzhiyun moal_handle *handle = (moal_handle *)sfp->private;
830*4882a593Smuzhiyun int ret = 0;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun ENTER();
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun if (MODULE_GET == 0) {
835*4882a593Smuzhiyun LEAVE();
836*4882a593Smuzhiyun return 0;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun if (!handle) {
840*4882a593Smuzhiyun PRINTM(MERROR, "handle is NULL!\n");
841*4882a593Smuzhiyun LEAVE();
842*4882a593Smuzhiyun return 0;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun if (!handle->drv_dump_buf || !handle->drv_dump_len)
845*4882a593Smuzhiyun handle->drv_dump_buf =
846*4882a593Smuzhiyun woal_dump_drv_info(handle, &handle->drv_dump_len);
847*4882a593Smuzhiyun if (!handle->drv_dump_buf || !handle->drv_dump_len) {
848*4882a593Smuzhiyun PRINTM(MERROR,
849*4882a593Smuzhiyun "driver dump buffer is NULL or total length is zero\n");
850*4882a593Smuzhiyun goto done;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun if (sfp->size < handle->drv_dump_len) {
853*4882a593Smuzhiyun PRINTM(MERROR,
854*4882a593Smuzhiyun "drv dump size too big, size=%d, drv_dump_len=%d\n",
855*4882a593Smuzhiyun (int)sfp->size, handle->drv_dump_len);
856*4882a593Smuzhiyun sfp->count = sfp->size;
857*4882a593Smuzhiyun ret = 0;
858*4882a593Smuzhiyun MODULE_PUT;
859*4882a593Smuzhiyun return ret;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun memset(sfp->buf, 0x00, sfp->size);
862*4882a593Smuzhiyun sfp->count = handle->drv_dump_len;
863*4882a593Smuzhiyun moal_memcpy_ext(handle, sfp->buf, handle->drv_dump_buf,
864*4882a593Smuzhiyun handle->drv_dump_len, sfp->size);
865*4882a593Smuzhiyun done:
866*4882a593Smuzhiyun moal_vfree(handle, handle->drv_dump_buf);
867*4882a593Smuzhiyun handle->drv_dump_len = 0;
868*4882a593Smuzhiyun handle->drv_dump_buf = NULL;
869*4882a593Smuzhiyun MODULE_PUT;
870*4882a593Smuzhiyun LEAVE();
871*4882a593Smuzhiyun return 0;
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun
woal_drv_dump_proc_open(struct inode * inode,struct file * file)874*4882a593Smuzhiyun static int woal_drv_dump_proc_open(struct inode *inode, struct file *file)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
877*4882a593Smuzhiyun return single_open(file, woal_drv_dump_read, pde_data(inode));
878*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
879*4882a593Smuzhiyun return single_open(file, woal_drv_dump_read, PDE_DATA(inode));
880*4882a593Smuzhiyun #else
881*4882a593Smuzhiyun return single_open(file, woal_drv_dump_read, PDE(inode)->data);
882*4882a593Smuzhiyun #endif
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
886*4882a593Smuzhiyun static const struct proc_ops drv_dump_fops = {
887*4882a593Smuzhiyun .proc_open = woal_drv_dump_proc_open,
888*4882a593Smuzhiyun .proc_read = seq_read,
889*4882a593Smuzhiyun .proc_lseek = seq_lseek,
890*4882a593Smuzhiyun .proc_release = single_release,
891*4882a593Smuzhiyun };
892*4882a593Smuzhiyun #else
893*4882a593Smuzhiyun static const struct file_operations drv_dump_fops = {
894*4882a593Smuzhiyun .owner = THIS_MODULE,
895*4882a593Smuzhiyun .open = woal_drv_dump_proc_open,
896*4882a593Smuzhiyun .read = seq_read,
897*4882a593Smuzhiyun .llseek = seq_lseek,
898*4882a593Smuzhiyun .release = single_release,
899*4882a593Smuzhiyun };
900*4882a593Smuzhiyun #endif
901*4882a593Smuzhiyun
woal_fw_dump_read(struct seq_file * sfp,void * data)902*4882a593Smuzhiyun static int woal_fw_dump_read(struct seq_file *sfp, void *data)
903*4882a593Smuzhiyun {
904*4882a593Smuzhiyun moal_handle *handle = (moal_handle *)sfp->private;
905*4882a593Smuzhiyun int ret = 0;
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun ENTER();
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun if (MODULE_GET == 0) {
910*4882a593Smuzhiyun LEAVE();
911*4882a593Smuzhiyun return 0;
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (!handle) {
915*4882a593Smuzhiyun PRINTM(MERROR, "handle is null!\n");
916*4882a593Smuzhiyun goto done;
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun if (handle->fw_dump == MTRUE) {
920*4882a593Smuzhiyun PRINTM(MERROR, "fw dump is in progress\n");
921*4882a593Smuzhiyun goto done;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun if (!handle->fw_dump_buf || !handle->fw_dump_len) {
925*4882a593Smuzhiyun PRINTM(MERROR,
926*4882a593Smuzhiyun "fw dump buffer is NULL or total length is zero\n");
927*4882a593Smuzhiyun goto done;
928*4882a593Smuzhiyun }
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun if (sfp->size < handle->fw_dump_len) {
931*4882a593Smuzhiyun PRINTM(MERROR,
932*4882a593Smuzhiyun "fw dump size too big, size=%d, fw_dump_len=%ld\n",
933*4882a593Smuzhiyun (int)sfp->size, (long int)handle->fw_dump_len);
934*4882a593Smuzhiyun sfp->count = sfp->size;
935*4882a593Smuzhiyun ret = 0;
936*4882a593Smuzhiyun MODULE_PUT;
937*4882a593Smuzhiyun return ret;
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun sfp->count = handle->fw_dump_len;
941*4882a593Smuzhiyun moal_memcpy_ext(handle, sfp->buf, handle->fw_dump_buf,
942*4882a593Smuzhiyun handle->fw_dump_len, sfp->size);
943*4882a593Smuzhiyun moal_vfree(handle, handle->fw_dump_buf);
944*4882a593Smuzhiyun handle->fw_dump_buf = NULL;
945*4882a593Smuzhiyun handle->fw_dump_len = 0;
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun done:
948*4882a593Smuzhiyun MODULE_PUT;
949*4882a593Smuzhiyun LEAVE();
950*4882a593Smuzhiyun return 0;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun
woal_fw_dump_proc_open(struct inode * inode,struct file * file)953*4882a593Smuzhiyun static int woal_fw_dump_proc_open(struct inode *inode, struct file *file)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
956*4882a593Smuzhiyun return single_open(file, woal_fw_dump_read, pde_data(inode));
957*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
958*4882a593Smuzhiyun return single_open(file, woal_fw_dump_read, PDE_DATA(inode));
959*4882a593Smuzhiyun #else
960*4882a593Smuzhiyun return single_open(file, woal_fw_dump_read, PDE(inode)->data);
961*4882a593Smuzhiyun #endif
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
965*4882a593Smuzhiyun static const struct proc_ops fw_dump_fops = {
966*4882a593Smuzhiyun .proc_open = woal_fw_dump_proc_open,
967*4882a593Smuzhiyun .proc_read = seq_read,
968*4882a593Smuzhiyun .proc_lseek = seq_lseek,
969*4882a593Smuzhiyun .proc_release = single_release,
970*4882a593Smuzhiyun };
971*4882a593Smuzhiyun #else
972*4882a593Smuzhiyun static const struct file_operations fw_dump_fops = {
973*4882a593Smuzhiyun .owner = THIS_MODULE,
974*4882a593Smuzhiyun .open = woal_fw_dump_proc_open,
975*4882a593Smuzhiyun .read = seq_read,
976*4882a593Smuzhiyun .llseek = seq_lseek,
977*4882a593Smuzhiyun .release = single_release,
978*4882a593Smuzhiyun };
979*4882a593Smuzhiyun #endif
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun /**
982*4882a593Smuzhiyun * @brief wifi status proc read function
983*4882a593Smuzhiyun *
984*4882a593Smuzhiyun * @param sfp pointer to seq_file structure
985*4882a593Smuzhiyun * @param data
986*4882a593Smuzhiyun *
987*4882a593Smuzhiyun * @return number of output data
988*4882a593Smuzhiyun */
woal_wifi_status_read(struct seq_file * sfp,void * data)989*4882a593Smuzhiyun static int woal_wifi_status_read(struct seq_file *sfp, void *data)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun ENTER();
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun if (!MODULE_GET) {
994*4882a593Smuzhiyun LEAVE();
995*4882a593Smuzhiyun return 0;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun seq_printf(sfp, "%d\n", wifi_status);
999*4882a593Smuzhiyun
1000*4882a593Smuzhiyun MODULE_PUT;
1001*4882a593Smuzhiyun LEAVE();
1002*4882a593Smuzhiyun return 0;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun
woal_wifi_status_proc_open(struct inode * inode,struct file * file)1005*4882a593Smuzhiyun static int woal_wifi_status_proc_open(struct inode *inode, struct file *file)
1006*4882a593Smuzhiyun {
1007*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
1008*4882a593Smuzhiyun return single_open(file, woal_wifi_status_read, pde_data(inode));
1009*4882a593Smuzhiyun #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
1010*4882a593Smuzhiyun return single_open(file, woal_wifi_status_read, PDE_DATA(inode));
1011*4882a593Smuzhiyun #else
1012*4882a593Smuzhiyun return single_open(file, woal_wifi_status_read, PDE(inode)->data);
1013*4882a593Smuzhiyun #endif
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
1017*4882a593Smuzhiyun static const struct proc_ops wifi_status_proc_fops = {
1018*4882a593Smuzhiyun .proc_open = woal_wifi_status_proc_open,
1019*4882a593Smuzhiyun .proc_read = seq_read,
1020*4882a593Smuzhiyun .proc_lseek = seq_lseek,
1021*4882a593Smuzhiyun .proc_release = single_release,
1022*4882a593Smuzhiyun };
1023*4882a593Smuzhiyun #else
1024*4882a593Smuzhiyun static const struct file_operations wifi_status_proc_fops = {
1025*4882a593Smuzhiyun .owner = THIS_MODULE,
1026*4882a593Smuzhiyun .open = woal_wifi_status_proc_open,
1027*4882a593Smuzhiyun .read = seq_read,
1028*4882a593Smuzhiyun .llseek = seq_lseek,
1029*4882a593Smuzhiyun .release = single_release,
1030*4882a593Smuzhiyun };
1031*4882a593Smuzhiyun #endif
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun /********************************************************
1034*4882a593Smuzhiyun Global Functions
1035*4882a593Smuzhiyun ********************************************************/
1036*4882a593Smuzhiyun /**
1037*4882a593Smuzhiyun * @brief Convert string to number
1038*4882a593Smuzhiyun *
1039*4882a593Smuzhiyun * @param s Pointer to numbered string
1040*4882a593Smuzhiyun *
1041*4882a593Smuzhiyun * @return Converted number from string s
1042*4882a593Smuzhiyun */
woal_string_to_number(char * s)1043*4882a593Smuzhiyun int woal_string_to_number(char *s)
1044*4882a593Smuzhiyun {
1045*4882a593Smuzhiyun int r = 0;
1046*4882a593Smuzhiyun int base = 0;
1047*4882a593Smuzhiyun int pn = 1;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun if (!strncmp(s, "-", 1)) {
1050*4882a593Smuzhiyun pn = -1;
1051*4882a593Smuzhiyun s++;
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun if (!strncmp(s, "0x", 2) || !strncmp(s, "0X", 2)) {
1054*4882a593Smuzhiyun base = 16;
1055*4882a593Smuzhiyun s += 2;
1056*4882a593Smuzhiyun } else
1057*4882a593Smuzhiyun base = 10;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun for (; *s; s++) {
1060*4882a593Smuzhiyun if ((*s >= '0') && (*s <= '9'))
1061*4882a593Smuzhiyun r = (r * base) + (*s - '0');
1062*4882a593Smuzhiyun else if ((*s >= 'A') && (*s <= 'F'))
1063*4882a593Smuzhiyun r = (r * base) + (*s - 'A' + 10);
1064*4882a593Smuzhiyun else if ((*s >= 'a') && (*s <= 'f'))
1065*4882a593Smuzhiyun r = (r * base) + (*s - 'a' + 10);
1066*4882a593Smuzhiyun else
1067*4882a593Smuzhiyun break;
1068*4882a593Smuzhiyun }
1069*4882a593Smuzhiyun
1070*4882a593Smuzhiyun return r * pn;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun /**
1074*4882a593Smuzhiyun * @brief This function creates proc mwlan directory
1075*4882a593Smuzhiyun * directory structure
1076*4882a593Smuzhiyun *
1077*4882a593Smuzhiyun * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1078*4882a593Smuzhiyun */
woal_root_proc_init(void)1079*4882a593Smuzhiyun mlan_status woal_root_proc_init(void)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun ENTER();
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun PRINTM(MINFO, "Create /proc/mwlan directory\n");
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun proc_mwlan = proc_mkdir(MWLAN_PROC, PROC_DIR);
1086*4882a593Smuzhiyun if (!proc_mwlan) {
1087*4882a593Smuzhiyun PRINTM(MERROR,
1088*4882a593Smuzhiyun "woal_root_proc_init: Cannot create /proc/mwlan\n");
1089*4882a593Smuzhiyun LEAVE();
1090*4882a593Smuzhiyun return MLAN_STATUS_FAILURE;
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun /* create /proc/mwlan/wifi_status */
1094*4882a593Smuzhiyun proc_create_data(STATUS_PROC, 0666, proc_mwlan, &wifi_status_proc_fops,
1095*4882a593Smuzhiyun NULL);
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun LEAVE();
1098*4882a593Smuzhiyun return MLAN_STATUS_SUCCESS;
1099*4882a593Smuzhiyun }
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun /**
1102*4882a593Smuzhiyun * @brief This function removes proc mwlan directory
1103*4882a593Smuzhiyun * directory structure
1104*4882a593Smuzhiyun *
1105*4882a593Smuzhiyun * @return N/A
1106*4882a593Smuzhiyun */
woal_root_proc_remove(void)1107*4882a593Smuzhiyun void woal_root_proc_remove(void)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun ENTER();
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun remove_proc_entry(STATUS_PROC, proc_mwlan);
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun remove_proc_entry(MWLAN_PROC, PROC_DIR);
1114*4882a593Smuzhiyun proc_mwlan = NULL;
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun LEAVE();
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun /**
1120*4882a593Smuzhiyun * @brief Create the top level proc directory
1121*4882a593Smuzhiyun *
1122*4882a593Smuzhiyun * @param handle Pointer to woal_handle
1123*4882a593Smuzhiyun *
1124*4882a593Smuzhiyun * @return N/A
1125*4882a593Smuzhiyun */
woal_proc_init(moal_handle * handle)1126*4882a593Smuzhiyun void woal_proc_init(moal_handle *handle)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun struct proc_dir_entry *r;
1129*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
1130*4882a593Smuzhiyun struct proc_dir_entry *pde = proc_mwlan;
1131*4882a593Smuzhiyun #endif
1132*4882a593Smuzhiyun char config_proc_dir[20];
1133*4882a593Smuzhiyun char drv_dump_dir[20];
1134*4882a593Smuzhiyun char fw_dump_dir[20];
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun ENTER();
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun if (handle->proc_wlan) {
1139*4882a593Smuzhiyun PRINTM(MMSG, "woal_proc_init: proc_wlan is already exist %s\n",
1140*4882a593Smuzhiyun handle->proc_wlan_name);
1141*4882a593Smuzhiyun goto done;
1142*4882a593Smuzhiyun }
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun snprintf(handle->proc_wlan_name, sizeof(handle->proc_wlan_name),
1145*4882a593Smuzhiyun WLAN_PROC, handle->handle_idx);
1146*4882a593Smuzhiyun PRINTM(MINFO, "Create Proc Interface %s\n", handle->proc_wlan_name);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
1149*4882a593Smuzhiyun /* Check if directory already exists */
1150*4882a593Smuzhiyun for (pde = pde->subdir; pde; pde = pde->next) {
1151*4882a593Smuzhiyun if (pde->namelen &&
1152*4882a593Smuzhiyun !strcmp(handle->proc_wlan_name, pde->name)) {
1153*4882a593Smuzhiyun /* Directory exists */
1154*4882a593Smuzhiyun PRINTM(MWARN, "proc interface already exists!\n");
1155*4882a593Smuzhiyun handle->proc_wlan = pde;
1156*4882a593Smuzhiyun break;
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun if (pde == NULL) {
1160*4882a593Smuzhiyun handle->proc_wlan =
1161*4882a593Smuzhiyun proc_mkdir(handle->proc_wlan_name, proc_mwlan);
1162*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1163*4882a593Smuzhiyun if (handle->proc_wlan)
1164*4882a593Smuzhiyun atomic_set(&handle->proc_wlan->count, 1);
1165*4882a593Smuzhiyun #endif
1166*4882a593Smuzhiyun }
1167*4882a593Smuzhiyun #else
1168*4882a593Smuzhiyun handle->proc_wlan = proc_mkdir(handle->proc_wlan_name, proc_mwlan);
1169*4882a593Smuzhiyun #endif
1170*4882a593Smuzhiyun if (!handle->proc_wlan) {
1171*4882a593Smuzhiyun PRINTM(MERROR, "Cannot create proc interface %s!\n",
1172*4882a593Smuzhiyun handle->proc_wlan_name);
1173*4882a593Smuzhiyun goto done;
1174*4882a593Smuzhiyun }
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun strcpy(config_proc_dir, "config");
1177*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1178*4882a593Smuzhiyun r = proc_create_data(config_proc_dir, 0666, handle->proc_wlan,
1179*4882a593Smuzhiyun &config_proc_fops, handle);
1180*4882a593Smuzhiyun #else
1181*4882a593Smuzhiyun r = create_proc_entry(config_proc_dir, 0644, handle->proc_wlan);
1182*4882a593Smuzhiyun if (r) {
1183*4882a593Smuzhiyun r->data = handle;
1184*4882a593Smuzhiyun r->proc_fops = &config_proc_fops;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun #endif
1187*4882a593Smuzhiyun if (!r)
1188*4882a593Smuzhiyun PRINTM(MERROR, "Fail to create proc config\n");
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun strcpy(drv_dump_dir, "drv_dump");
1191*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1192*4882a593Smuzhiyun r = proc_create_data(drv_dump_dir, 0644, handle->proc_wlan,
1193*4882a593Smuzhiyun &drv_dump_fops, handle);
1194*4882a593Smuzhiyun #else
1195*4882a593Smuzhiyun r = create_proc_entry(drv_dump_dir, 0644, handle->proc_wlan);
1196*4882a593Smuzhiyun if (r) {
1197*4882a593Smuzhiyun r->data = handle;
1198*4882a593Smuzhiyun r->proc_fops = &drv_dump_fops;
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun #endif
1201*4882a593Smuzhiyun if (!r)
1202*4882a593Smuzhiyun PRINTM(MERROR, "Failed to create proc drv dump\n");
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun strcpy(fw_dump_dir, "fw_dump");
1205*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1206*4882a593Smuzhiyun r = proc_create_data(fw_dump_dir, 0644, handle->proc_wlan,
1207*4882a593Smuzhiyun &fw_dump_fops, handle);
1208*4882a593Smuzhiyun #else
1209*4882a593Smuzhiyun r = create_proc_entry(fw_dump_dir, 0644, handle->proc_wlan);
1210*4882a593Smuzhiyun if (r) {
1211*4882a593Smuzhiyun r->data = handle;
1212*4882a593Smuzhiyun r->proc_fops = &fw_dump_fops;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun #endif
1215*4882a593Smuzhiyun if (!r)
1216*4882a593Smuzhiyun PRINTM(MERROR, "Failed to create proc fw dump\n");
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun done:
1219*4882a593Smuzhiyun LEAVE();
1220*4882a593Smuzhiyun }
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun /**
1223*4882a593Smuzhiyun * @brief Remove the top level proc directory
1224*4882a593Smuzhiyun *
1225*4882a593Smuzhiyun * @param handle pointer moal_handle
1226*4882a593Smuzhiyun *
1227*4882a593Smuzhiyun * @return N/A
1228*4882a593Smuzhiyun */
woal_proc_exit(moal_handle * handle)1229*4882a593Smuzhiyun void woal_proc_exit(moal_handle *handle)
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun char config_proc_dir[20];
1232*4882a593Smuzhiyun char drv_dump_dir[20];
1233*4882a593Smuzhiyun char fw_dump_dir[20];
1234*4882a593Smuzhiyun
1235*4882a593Smuzhiyun ENTER();
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun PRINTM(MINFO, "Remove Proc Interface %s\n", handle->proc_wlan_name);
1238*4882a593Smuzhiyun if (handle->proc_wlan) {
1239*4882a593Smuzhiyun strcpy(config_proc_dir, "config");
1240*4882a593Smuzhiyun remove_proc_entry(config_proc_dir, handle->proc_wlan);
1241*4882a593Smuzhiyun strcpy(drv_dump_dir, "drv_dump");
1242*4882a593Smuzhiyun remove_proc_entry(drv_dump_dir, handle->proc_wlan);
1243*4882a593Smuzhiyun strcpy(fw_dump_dir, "fw_dump");
1244*4882a593Smuzhiyun remove_proc_entry(fw_dump_dir, handle->proc_wlan);
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1247*4882a593Smuzhiyun /* Remove only if we are the only instance using this */
1248*4882a593Smuzhiyun if (atomic_read(&(handle->proc_wlan->count)) > 1) {
1249*4882a593Smuzhiyun PRINTM(MWARN, "More than one interface using proc!\n");
1250*4882a593Smuzhiyun } else {
1251*4882a593Smuzhiyun #endif
1252*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1253*4882a593Smuzhiyun atomic_dec(&(handle->proc_wlan->count));
1254*4882a593Smuzhiyun #endif
1255*4882a593Smuzhiyun remove_proc_entry(handle->proc_wlan_name, proc_mwlan);
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun handle->proc_wlan = NULL;
1258*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1259*4882a593Smuzhiyun }
1260*4882a593Smuzhiyun #endif
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun if (handle->fw_dump_buf) {
1263*4882a593Smuzhiyun moal_vfree(handle, handle->fw_dump_buf);
1264*4882a593Smuzhiyun handle->fw_dump_buf = NULL;
1265*4882a593Smuzhiyun handle->fw_dump_len = 0;
1266*4882a593Smuzhiyun }
1267*4882a593Smuzhiyun if (handle->drv_dump_buf) {
1268*4882a593Smuzhiyun moal_vfree(handle, handle->drv_dump_buf);
1269*4882a593Smuzhiyun handle->drv_dump_len = 0;
1270*4882a593Smuzhiyun handle->drv_dump_buf = NULL;
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun LEAVE();
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun /**
1276*4882a593Smuzhiyun * @brief Create proc file for interface
1277*4882a593Smuzhiyun *
1278*4882a593Smuzhiyun * @param priv pointer moal_private
1279*4882a593Smuzhiyun *
1280*4882a593Smuzhiyun * @return N/A
1281*4882a593Smuzhiyun */
woal_create_proc_entry(moal_private * priv)1282*4882a593Smuzhiyun void woal_create_proc_entry(moal_private *priv)
1283*4882a593Smuzhiyun {
1284*4882a593Smuzhiyun struct proc_dir_entry *r;
1285*4882a593Smuzhiyun struct net_device *dev = priv->netdev;
1286*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1287*4882a593Smuzhiyun char proc_dir_name[22];
1288*4882a593Smuzhiyun #endif
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun ENTER();
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1293*4882a593Smuzhiyun if (!priv->proc_entry) {
1294*4882a593Smuzhiyun memset(proc_dir_name, 0, sizeof(proc_dir_name));
1295*4882a593Smuzhiyun memcpy(proc_dir_name, priv->phandle->proc_wlan_name,
1296*4882a593Smuzhiyun sizeof(proc_dir_name) - 2);
1297*4882a593Smuzhiyun proc_dir_name[strlen(proc_dir_name)] = '/';
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun if (strlen(dev->name) >
1300*4882a593Smuzhiyun ((sizeof(proc_dir_name) - 1) - (strlen(proc_dir_name)))) {
1301*4882a593Smuzhiyun PRINTM(MERROR,
1302*4882a593Smuzhiyun "Failed to create proc entry, device name is too long\n");
1303*4882a593Smuzhiyun LEAVE();
1304*4882a593Smuzhiyun return;
1305*4882a593Smuzhiyun }
1306*4882a593Smuzhiyun strcat(proc_dir_name, dev->name);
1307*4882a593Smuzhiyun /* Try to create adapterX/dev_name directory first under
1308*4882a593Smuzhiyun * /proc/mwlan/ */
1309*4882a593Smuzhiyun priv->proc_entry = proc_mkdir(proc_dir_name, proc_mwlan);
1310*4882a593Smuzhiyun if (priv->proc_entry) {
1311*4882a593Smuzhiyun /* Success. Continue normally */
1312*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1313*4882a593Smuzhiyun if (!priv->phandle->proc_wlan) {
1314*4882a593Smuzhiyun priv->phandle->proc_wlan =
1315*4882a593Smuzhiyun priv->proc_entry->parent;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun atomic_inc(&(priv->phandle->proc_wlan->count));
1318*4882a593Smuzhiyun #endif
1319*4882a593Smuzhiyun } else {
1320*4882a593Smuzhiyun /* Failure. adapterX/ may not exist. Try to create that
1321*4882a593Smuzhiyun * first */
1322*4882a593Smuzhiyun priv->phandle->proc_wlan = proc_mkdir(
1323*4882a593Smuzhiyun priv->phandle->proc_wlan_name, proc_mwlan);
1324*4882a593Smuzhiyun if (!priv->phandle->proc_wlan) {
1325*4882a593Smuzhiyun /* Failure. Something broken */
1326*4882a593Smuzhiyun LEAVE();
1327*4882a593Smuzhiyun return;
1328*4882a593Smuzhiyun } else {
1329*4882a593Smuzhiyun /* Success. Now retry creating mlanX */
1330*4882a593Smuzhiyun priv->proc_entry =
1331*4882a593Smuzhiyun proc_mkdir(proc_dir_name, proc_mwlan);
1332*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1333*4882a593Smuzhiyun atomic_inc(&(priv->phandle->proc_wlan->count));
1334*4882a593Smuzhiyun #endif
1335*4882a593Smuzhiyun }
1336*4882a593Smuzhiyun }
1337*4882a593Smuzhiyun #else
1338*4882a593Smuzhiyun if (priv->phandle->proc_wlan && !priv->proc_entry) {
1339*4882a593Smuzhiyun priv->proc_entry =
1340*4882a593Smuzhiyun proc_mkdir(dev->name, priv->phandle->proc_wlan);
1341*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1342*4882a593Smuzhiyun atomic_inc(&(priv->phandle->proc_wlan->count));
1343*4882a593Smuzhiyun #endif /* < 3.10.0 */
1344*4882a593Smuzhiyun #endif /* < 2.6.26 */
1345*4882a593Smuzhiyun strcpy(priv->proc_entry_name, dev->name);
1346*4882a593Smuzhiyun if (priv->proc_entry) {
1347*4882a593Smuzhiyun #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
1348*4882a593Smuzhiyun r = proc_create_data("info", 0, priv->proc_entry,
1349*4882a593Smuzhiyun &info_proc_fops, dev);
1350*4882a593Smuzhiyun #else
1351*4882a593Smuzhiyun r = create_proc_entry("info", 0, priv->proc_entry);
1352*4882a593Smuzhiyun if (r) {
1353*4882a593Smuzhiyun r->data = dev;
1354*4882a593Smuzhiyun r->proc_fops = &info_proc_fops;
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun #endif
1357*4882a593Smuzhiyun if (!r)
1358*4882a593Smuzhiyun PRINTM(MMSG, "Fail to create proc info\n");
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun LEAVE();
1363*4882a593Smuzhiyun }
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun /**
1366*4882a593Smuzhiyun * @brief Remove proc file
1367*4882a593Smuzhiyun *
1368*4882a593Smuzhiyun * @param priv Pointer moal_private
1369*4882a593Smuzhiyun *
1370*4882a593Smuzhiyun * @return N/A
1371*4882a593Smuzhiyun */
1372*4882a593Smuzhiyun void woal_proc_remove(moal_private *priv)
1373*4882a593Smuzhiyun {
1374*4882a593Smuzhiyun ENTER();
1375*4882a593Smuzhiyun if (priv->phandle->proc_wlan && priv->proc_entry) {
1376*4882a593Smuzhiyun remove_proc_entry("info", priv->proc_entry);
1377*4882a593Smuzhiyun remove_proc_entry(priv->proc_entry_name,
1378*4882a593Smuzhiyun priv->phandle->proc_wlan);
1379*4882a593Smuzhiyun #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
1380*4882a593Smuzhiyun atomic_dec(&(priv->phandle->proc_wlan->count));
1381*4882a593Smuzhiyun #endif
1382*4882a593Smuzhiyun priv->proc_entry = NULL;
1383*4882a593Smuzhiyun }
1384*4882a593Smuzhiyun LEAVE();
1385*4882a593Smuzhiyun }
1386*4882a593Smuzhiyun #endif
1387