xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_proc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &reg, &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