xref: /openbmc/linux/net/mac80211/debugfs_netdev.c (revision 060f35a317ef09101b128f399dce7ed13d019461)
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Copyright (c) 2006	Jiri Benc <jbenc@suse.cz>
4   * Copyright 2007	Johannes Berg <johannes@sipsolutions.net>
5   * Copyright (C) 2020-2023 Intel Corporation
6   */
7  
8  #include <linux/kernel.h>
9  #include <linux/device.h>
10  #include <linux/if.h>
11  #include <linux/if_ether.h>
12  #include <linux/interrupt.h>
13  #include <linux/netdevice.h>
14  #include <linux/rtnetlink.h>
15  #include <linux/slab.h>
16  #include <linux/notifier.h>
17  #include <net/mac80211.h>
18  #include <net/cfg80211.h>
19  #include "ieee80211_i.h"
20  #include "rate.h"
21  #include "debugfs.h"
22  #include "debugfs_netdev.h"
23  #include "driver-ops.h"
24  
ieee80211_if_read(void * data,char __user * userbuf,size_t count,loff_t * ppos,ssize_t (* format)(const void *,char *,int))25  static ssize_t ieee80211_if_read(
26  	void *data,
27  	char __user *userbuf,
28  	size_t count, loff_t *ppos,
29  	ssize_t (*format)(const void *, char *, int))
30  {
31  	char buf[200];
32  	ssize_t ret = -EINVAL;
33  
34  	read_lock(&dev_base_lock);
35  	ret = (*format)(data, buf, sizeof(buf));
36  	read_unlock(&dev_base_lock);
37  
38  	if (ret >= 0)
39  		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
40  
41  	return ret;
42  }
43  
ieee80211_if_write(void * data,const char __user * userbuf,size_t count,loff_t * ppos,ssize_t (* write)(void *,const char *,int))44  static ssize_t ieee80211_if_write(
45  	void *data,
46  	const char __user *userbuf,
47  	size_t count, loff_t *ppos,
48  	ssize_t (*write)(void *, const char *, int))
49  {
50  	char buf[64];
51  	ssize_t ret;
52  
53  	if (count >= sizeof(buf))
54  		return -E2BIG;
55  
56  	if (copy_from_user(buf, userbuf, count))
57  		return -EFAULT;
58  	buf[count] = '\0';
59  
60  	rtnl_lock();
61  	ret = (*write)(data, buf, count);
62  	rtnl_unlock();
63  
64  	return ret;
65  }
66  
67  #define IEEE80211_IF_FMT(name, type, field, format_string)		\
68  static ssize_t ieee80211_if_fmt_##name(					\
69  	const type *data, char *buf,					\
70  	int buflen)							\
71  {									\
72  	return scnprintf(buf, buflen, format_string, data->field);	\
73  }
74  #define IEEE80211_IF_FMT_DEC(name, type, field)				\
75  		IEEE80211_IF_FMT(name, type, field, "%d\n")
76  #define IEEE80211_IF_FMT_HEX(name, type, field)				\
77  		IEEE80211_IF_FMT(name, type, field, "%#x\n")
78  #define IEEE80211_IF_FMT_LHEX(name, type, field)			\
79  		IEEE80211_IF_FMT(name, type, field, "%#lx\n")
80  
81  #define IEEE80211_IF_FMT_HEXARRAY(name, type, field)			\
82  static ssize_t ieee80211_if_fmt_##name(					\
83  	const type *data,						\
84  	char *buf, int buflen)						\
85  {									\
86  	char *p = buf;							\
87  	int i;								\
88  	for (i = 0; i < sizeof(data->field); i++) {			\
89  		p += scnprintf(p, buflen + buf - p, "%.2x ",		\
90  				 data->field[i]);			\
91  	}								\
92  	p += scnprintf(p, buflen + buf - p, "\n");			\
93  	return p - buf;							\
94  }
95  
96  #define IEEE80211_IF_FMT_ATOMIC(name, type, field)			\
97  static ssize_t ieee80211_if_fmt_##name(					\
98  	const type *data,						\
99  	char *buf, int buflen)						\
100  {									\
101  	return scnprintf(buf, buflen, "%d\n", atomic_read(&data->field));\
102  }
103  
104  #define IEEE80211_IF_FMT_MAC(name, type, field)				\
105  static ssize_t ieee80211_if_fmt_##name(					\
106  	const type *data, char *buf,					\
107  	int buflen)							\
108  {									\
109  	return scnprintf(buf, buflen, "%pM\n", data->field);		\
110  }
111  
112  #define IEEE80211_IF_FMT_JIFFIES_TO_MS(name, type, field)		\
113  static ssize_t ieee80211_if_fmt_##name(					\
114  	const type *data,						\
115  	char *buf, int buflen)						\
116  {									\
117  	return scnprintf(buf, buflen, "%d\n",				\
118  			 jiffies_to_msecs(data->field));		\
119  }
120  
121  #define _IEEE80211_IF_FILE_OPS(name, _read, _write)			\
122  static const struct file_operations name##_ops = {			\
123  	.read = (_read),						\
124  	.write = (_write),						\
125  	.open = simple_open,						\
126  	.llseek = generic_file_llseek,					\
127  }
128  
129  #define _IEEE80211_IF_FILE_R_FN(name, type)				\
130  static ssize_t ieee80211_if_read_##name(struct file *file,		\
131  					char __user *userbuf,		\
132  					size_t count, loff_t *ppos)	\
133  {									\
134  	ssize_t (*fn)(const void *, char *, int) = (void *)		\
135  		((ssize_t (*)(const type, char *, int))			\
136  		 ieee80211_if_fmt_##name);				\
137  	return ieee80211_if_read(file->private_data,			\
138  				 userbuf, count, ppos, fn);		\
139  }
140  
141  #define _IEEE80211_IF_FILE_W_FN(name, type)				\
142  static ssize_t ieee80211_if_write_##name(struct file *file,		\
143  					 const char __user *userbuf,	\
144  					 size_t count, loff_t *ppos)	\
145  {									\
146  	ssize_t (*fn)(void *, const char *, int) = (void *)		\
147  		((ssize_t (*)(type, const char *, int))			\
148  		 ieee80211_if_parse_##name);				\
149  	return ieee80211_if_write(file->private_data, userbuf, count,	\
150  				  ppos, fn);				\
151  }
152  
153  #define IEEE80211_IF_FILE_R(name)					\
154  	_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *)	\
155  	_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL)
156  
157  #define IEEE80211_IF_FILE_W(name)					\
158  	_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *)	\
159  	_IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name)
160  
161  #define IEEE80211_IF_FILE_RW(name)					\
162  	_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *)	\
163  	_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *)	\
164  	_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name,		\
165  			       ieee80211_if_write_##name)
166  
167  #define IEEE80211_IF_FILE(name, field, format)				\
168  	IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field) \
169  	IEEE80211_IF_FILE_R(name)
170  
171  /* Same but with a link_ prefix in the ops variable name and different type */
172  #define IEEE80211_IF_LINK_FILE_R(name)					\
173  	_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *)	\
174  	_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL)
175  
176  #define IEEE80211_IF_LINK_FILE_W(name)					\
177  	_IEEE80211_IF_FILE_W_FN(name)					\
178  	_IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name)
179  
180  #define IEEE80211_IF_LINK_FILE_RW(name)					\
181  	_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *)	\
182  	_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_link_data *)	\
183  	_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name,	\
184  			       ieee80211_if_write_##name)
185  
186  #define IEEE80211_IF_LINK_FILE(name, field, format)				\
187  	IEEE80211_IF_FMT_##format(name, struct ieee80211_link_data, field) \
188  	IEEE80211_IF_LINK_FILE_R(name)
189  
190  /* common attributes */
191  IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[NL80211_BAND_2GHZ],
192  		  HEX);
193  IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[NL80211_BAND_5GHZ],
194  		  HEX);
195  IEEE80211_IF_FILE(rc_rateidx_mcs_mask_2ghz,
196  		  rc_rateidx_mcs_mask[NL80211_BAND_2GHZ], HEXARRAY);
197  IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
198  		  rc_rateidx_mcs_mask[NL80211_BAND_5GHZ], HEXARRAY);
199  
ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_2ghz(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)200  static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_2ghz(
201  				const struct ieee80211_sub_if_data *sdata,
202  				char *buf, int buflen)
203  {
204  	int i, len = 0;
205  	const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_2GHZ];
206  
207  	for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
208  		len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]);
209  	len += scnprintf(buf + len, buflen - len, "\n");
210  
211  	return len;
212  }
213  
214  IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_2ghz);
215  
ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_5ghz(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)216  static ssize_t ieee80211_if_fmt_rc_rateidx_vht_mcs_mask_5ghz(
217  				const struct ieee80211_sub_if_data *sdata,
218  				char *buf, int buflen)
219  {
220  	int i, len = 0;
221  	const u16 *mask = sdata->rc_rateidx_vht_mcs_mask[NL80211_BAND_5GHZ];
222  
223  	for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
224  		len += scnprintf(buf + len, buflen - len, "%04x ", mask[i]);
225  	len += scnprintf(buf + len, buflen - len, "\n");
226  
227  	return len;
228  }
229  
230  IEEE80211_IF_FILE_R(rc_rateidx_vht_mcs_mask_5ghz);
231  
232  IEEE80211_IF_FILE(flags, flags, HEX);
233  IEEE80211_IF_FILE(state, state, LHEX);
234  IEEE80211_IF_LINK_FILE(txpower, conf->txpower, DEC);
235  IEEE80211_IF_LINK_FILE(ap_power_level, ap_power_level, DEC);
236  IEEE80211_IF_LINK_FILE(user_power_level, user_power_level, DEC);
237  
238  static ssize_t
ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)239  ieee80211_if_fmt_hw_queues(const struct ieee80211_sub_if_data *sdata,
240  			   char *buf, int buflen)
241  {
242  	int len;
243  
244  	len = scnprintf(buf, buflen, "AC queues: VO:%d VI:%d BE:%d BK:%d\n",
245  			sdata->vif.hw_queue[IEEE80211_AC_VO],
246  			sdata->vif.hw_queue[IEEE80211_AC_VI],
247  			sdata->vif.hw_queue[IEEE80211_AC_BE],
248  			sdata->vif.hw_queue[IEEE80211_AC_BK]);
249  
250  	if (sdata->vif.type == NL80211_IFTYPE_AP)
251  		len += scnprintf(buf + len, buflen - len, "cab queue: %d\n",
252  				 sdata->vif.cab_queue);
253  
254  	return len;
255  }
256  IEEE80211_IF_FILE_R(hw_queues);
257  
258  /* STA attributes */
259  IEEE80211_IF_FILE(bssid, deflink.u.mgd.bssid, MAC);
260  IEEE80211_IF_FILE(aid, vif.cfg.aid, DEC);
261  IEEE80211_IF_FILE(beacon_timeout, u.mgd.beacon_timeout, JIFFIES_TO_MS);
262  
ieee80211_set_smps(struct ieee80211_link_data * link,enum ieee80211_smps_mode smps_mode)263  static int ieee80211_set_smps(struct ieee80211_link_data *link,
264  			      enum ieee80211_smps_mode smps_mode)
265  {
266  	struct ieee80211_sub_if_data *sdata = link->sdata;
267  	struct ieee80211_local *local = sdata->local;
268  	int err;
269  
270  	if (sdata->vif.driver_flags & IEEE80211_VIF_DISABLE_SMPS_OVERRIDE)
271  		return -EOPNOTSUPP;
272  
273  	if (!(local->hw.wiphy->features & NL80211_FEATURE_STATIC_SMPS) &&
274  	    smps_mode == IEEE80211_SMPS_STATIC)
275  		return -EINVAL;
276  
277  	/* auto should be dynamic if in PS mode */
278  	if (!(local->hw.wiphy->features & NL80211_FEATURE_DYNAMIC_SMPS) &&
279  	    (smps_mode == IEEE80211_SMPS_DYNAMIC ||
280  	     smps_mode == IEEE80211_SMPS_AUTOMATIC))
281  		return -EINVAL;
282  
283  	if (sdata->vif.type != NL80211_IFTYPE_STATION)
284  		return -EOPNOTSUPP;
285  
286  	sdata_lock(sdata);
287  	err = __ieee80211_request_smps_mgd(link->sdata, link, smps_mode);
288  	sdata_unlock(sdata);
289  
290  	return err;
291  }
292  
293  static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
294  	[IEEE80211_SMPS_AUTOMATIC] = "auto",
295  	[IEEE80211_SMPS_OFF] = "off",
296  	[IEEE80211_SMPS_STATIC] = "static",
297  	[IEEE80211_SMPS_DYNAMIC] = "dynamic",
298  };
299  
ieee80211_if_fmt_smps(const struct ieee80211_link_data * link,char * buf,int buflen)300  static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_link_data *link,
301  				     char *buf, int buflen)
302  {
303  	if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
304  		return snprintf(buf, buflen, "request: %s\nused: %s\n",
305  				smps_modes[link->u.mgd.req_smps],
306  				smps_modes[link->smps_mode]);
307  	return -EINVAL;
308  }
309  
ieee80211_if_parse_smps(struct ieee80211_link_data * link,const char * buf,int buflen)310  static ssize_t ieee80211_if_parse_smps(struct ieee80211_link_data *link,
311  				       const char *buf, int buflen)
312  {
313  	enum ieee80211_smps_mode mode;
314  
315  	for (mode = 0; mode < IEEE80211_SMPS_NUM_MODES; mode++) {
316  		if (strncmp(buf, smps_modes[mode], buflen) == 0) {
317  			int err = ieee80211_set_smps(link, mode);
318  			if (!err)
319  				return buflen;
320  			return err;
321  		}
322  	}
323  
324  	return -EINVAL;
325  }
326  IEEE80211_IF_LINK_FILE_RW(smps);
327  
ieee80211_if_parse_tkip_mic_test(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)328  static ssize_t ieee80211_if_parse_tkip_mic_test(
329  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
330  {
331  	struct ieee80211_local *local = sdata->local;
332  	u8 addr[ETH_ALEN];
333  	struct sk_buff *skb;
334  	struct ieee80211_hdr *hdr;
335  	__le16 fc;
336  
337  	if (!mac_pton(buf, addr))
338  		return -EINVAL;
339  
340  	if (!ieee80211_sdata_running(sdata))
341  		return -ENOTCONN;
342  
343  	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100);
344  	if (!skb)
345  		return -ENOMEM;
346  	skb_reserve(skb, local->hw.extra_tx_headroom);
347  
348  	hdr = skb_put_zero(skb, 24);
349  	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
350  
351  	switch (sdata->vif.type) {
352  	case NL80211_IFTYPE_AP:
353  		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
354  		/* DA BSSID SA */
355  		memcpy(hdr->addr1, addr, ETH_ALEN);
356  		memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
357  		memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN);
358  		break;
359  	case NL80211_IFTYPE_STATION:
360  		fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
361  		/* BSSID SA DA */
362  		sdata_lock(sdata);
363  		if (!sdata->u.mgd.associated) {
364  			sdata_unlock(sdata);
365  			dev_kfree_skb(skb);
366  			return -ENOTCONN;
367  		}
368  		memcpy(hdr->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
369  		memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
370  		memcpy(hdr->addr3, addr, ETH_ALEN);
371  		sdata_unlock(sdata);
372  		break;
373  	default:
374  		dev_kfree_skb(skb);
375  		return -EOPNOTSUPP;
376  	}
377  	hdr->frame_control = fc;
378  
379  	/*
380  	 * Add some length to the test frame to make it look bit more valid.
381  	 * The exact contents does not matter since the recipient is required
382  	 * to drop this because of the Michael MIC failure.
383  	 */
384  	skb_put_zero(skb, 50);
385  
386  	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE;
387  
388  	ieee80211_tx_skb(sdata, skb);
389  
390  	return buflen;
391  }
392  IEEE80211_IF_FILE_W(tkip_mic_test);
393  
ieee80211_if_parse_beacon_loss(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)394  static ssize_t ieee80211_if_parse_beacon_loss(
395  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
396  {
397  	if (!ieee80211_sdata_running(sdata) || !sdata->vif.cfg.assoc)
398  		return -ENOTCONN;
399  
400  	ieee80211_beacon_loss(&sdata->vif);
401  
402  	return buflen;
403  }
404  IEEE80211_IF_FILE_W(beacon_loss);
405  
ieee80211_if_fmt_uapsd_queues(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)406  static ssize_t ieee80211_if_fmt_uapsd_queues(
407  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
408  {
409  	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
410  
411  	return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_queues);
412  }
413  
ieee80211_if_parse_uapsd_queues(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)414  static ssize_t ieee80211_if_parse_uapsd_queues(
415  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
416  {
417  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
418  	u8 val;
419  	int ret;
420  
421  	ret = kstrtou8(buf, 0, &val);
422  	if (ret)
423  		return ret;
424  
425  	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
426  		return -ERANGE;
427  
428  	ifmgd->uapsd_queues = val;
429  
430  	return buflen;
431  }
432  IEEE80211_IF_FILE_RW(uapsd_queues);
433  
ieee80211_if_fmt_uapsd_max_sp_len(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)434  static ssize_t ieee80211_if_fmt_uapsd_max_sp_len(
435  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
436  {
437  	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
438  
439  	return snprintf(buf, buflen, "0x%x\n", ifmgd->uapsd_max_sp_len);
440  }
441  
ieee80211_if_parse_uapsd_max_sp_len(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)442  static ssize_t ieee80211_if_parse_uapsd_max_sp_len(
443  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
444  {
445  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
446  	unsigned long val;
447  	int ret;
448  
449  	ret = kstrtoul(buf, 0, &val);
450  	if (ret)
451  		return -EINVAL;
452  
453  	if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
454  		return -ERANGE;
455  
456  	ifmgd->uapsd_max_sp_len = val;
457  
458  	return buflen;
459  }
460  IEEE80211_IF_FILE_RW(uapsd_max_sp_len);
461  
ieee80211_if_fmt_tdls_wider_bw(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)462  static ssize_t ieee80211_if_fmt_tdls_wider_bw(
463  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
464  {
465  	const struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
466  	bool tdls_wider_bw;
467  
468  	tdls_wider_bw = ieee80211_hw_check(&sdata->local->hw, TDLS_WIDER_BW) &&
469  			!ifmgd->tdls_wider_bw_prohibited;
470  
471  	return snprintf(buf, buflen, "%d\n", tdls_wider_bw);
472  }
473  
ieee80211_if_parse_tdls_wider_bw(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)474  static ssize_t ieee80211_if_parse_tdls_wider_bw(
475  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
476  {
477  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
478  	u8 val;
479  	int ret;
480  
481  	ret = kstrtou8(buf, 0, &val);
482  	if (ret)
483  		return ret;
484  
485  	ifmgd->tdls_wider_bw_prohibited = !val;
486  	return buflen;
487  }
488  IEEE80211_IF_FILE_RW(tdls_wider_bw);
489  
490  /* AP attributes */
491  IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC);
492  IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC);
493  IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC);
494  IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC);
495  
ieee80211_if_fmt_num_buffered_multicast(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)496  static ssize_t ieee80211_if_fmt_num_buffered_multicast(
497  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
498  {
499  	return scnprintf(buf, buflen, "%u\n",
500  			 skb_queue_len(&sdata->u.ap.ps.bc_buf));
501  }
502  IEEE80211_IF_FILE_R(num_buffered_multicast);
503  
ieee80211_if_fmt_aqm(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)504  static ssize_t ieee80211_if_fmt_aqm(
505  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
506  {
507  	struct ieee80211_local *local = sdata->local;
508  	struct txq_info *txqi;
509  	int len;
510  
511  	if (!sdata->vif.txq)
512  		return 0;
513  
514  	txqi = to_txq_info(sdata->vif.txq);
515  
516  	spin_lock_bh(&local->fq.lock);
517  	rcu_read_lock();
518  
519  	len = scnprintf(buf,
520  			buflen,
521  			"ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets\n"
522  			"%u %u %u %u %u %u %u %u %u %u\n",
523  			txqi->txq.ac,
524  			txqi->tin.backlog_bytes,
525  			txqi->tin.backlog_packets,
526  			txqi->tin.flows,
527  			txqi->cstats.drop_count,
528  			txqi->cstats.ecn_mark,
529  			txqi->tin.overlimit,
530  			txqi->tin.collisions,
531  			txqi->tin.tx_bytes,
532  			txqi->tin.tx_packets);
533  
534  	rcu_read_unlock();
535  	spin_unlock_bh(&local->fq.lock);
536  
537  	return len;
538  }
539  IEEE80211_IF_FILE_R(aqm);
540  
541  IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX);
542  
543  /* IBSS attributes */
ieee80211_if_fmt_tsf(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)544  static ssize_t ieee80211_if_fmt_tsf(
545  	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
546  {
547  	struct ieee80211_local *local = sdata->local;
548  	u64 tsf;
549  
550  	tsf = drv_get_tsf(local, (struct ieee80211_sub_if_data *)sdata);
551  
552  	return scnprintf(buf, buflen, "0x%016llx\n", (unsigned long long) tsf);
553  }
554  
ieee80211_if_parse_tsf(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)555  static ssize_t ieee80211_if_parse_tsf(
556  	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
557  {
558  	struct ieee80211_local *local = sdata->local;
559  	unsigned long long tsf;
560  	int ret;
561  	int tsf_is_delta = 0;
562  
563  	if (strncmp(buf, "reset", 5) == 0) {
564  		if (local->ops->reset_tsf) {
565  			drv_reset_tsf(local, sdata);
566  			wiphy_info(local->hw.wiphy, "debugfs reset TSF\n");
567  		}
568  	} else {
569  		if (buflen > 10 && buf[1] == '=') {
570  			if (buf[0] == '+')
571  				tsf_is_delta = 1;
572  			else if (buf[0] == '-')
573  				tsf_is_delta = -1;
574  			else
575  				return -EINVAL;
576  			buf += 2;
577  		}
578  		ret = kstrtoull(buf, 10, &tsf);
579  		if (ret < 0)
580  			return ret;
581  		if (tsf_is_delta && local->ops->offset_tsf) {
582  			drv_offset_tsf(local, sdata, tsf_is_delta * tsf);
583  			wiphy_info(local->hw.wiphy,
584  				   "debugfs offset TSF by %018lld\n",
585  				   tsf_is_delta * tsf);
586  		} else if (local->ops->set_tsf) {
587  			if (tsf_is_delta)
588  				tsf = drv_get_tsf(local, sdata) +
589  				      tsf_is_delta * tsf;
590  			drv_set_tsf(local, sdata, tsf);
591  			wiphy_info(local->hw.wiphy,
592  				   "debugfs set TSF to %#018llx\n", tsf);
593  		}
594  	}
595  
596  	ieee80211_recalc_dtim(local, sdata);
597  	return buflen;
598  }
599  IEEE80211_IF_FILE_RW(tsf);
600  
ieee80211_if_fmt_valid_links(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)601  static ssize_t ieee80211_if_fmt_valid_links(const struct ieee80211_sub_if_data *sdata,
602  					    char *buf, int buflen)
603  {
604  	return snprintf(buf, buflen, "0x%x\n", sdata->vif.valid_links);
605  }
606  IEEE80211_IF_FILE_R(valid_links);
607  
ieee80211_if_fmt_active_links(const struct ieee80211_sub_if_data * sdata,char * buf,int buflen)608  static ssize_t ieee80211_if_fmt_active_links(const struct ieee80211_sub_if_data *sdata,
609  					     char *buf, int buflen)
610  {
611  	return snprintf(buf, buflen, "0x%x\n", sdata->vif.active_links);
612  }
613  
ieee80211_if_parse_active_links(struct ieee80211_sub_if_data * sdata,const char * buf,int buflen)614  static ssize_t ieee80211_if_parse_active_links(struct ieee80211_sub_if_data *sdata,
615  					       const char *buf, int buflen)
616  {
617  	u16 active_links;
618  
619  	if (kstrtou16(buf, 0, &active_links) || !active_links)
620  		return -EINVAL;
621  
622  	return ieee80211_set_active_links(&sdata->vif, active_links) ?: buflen;
623  }
624  IEEE80211_IF_FILE_RW(active_links);
625  
626  IEEE80211_IF_LINK_FILE(addr, conf->addr, MAC);
627  
628  #ifdef CONFIG_MAC80211_MESH
629  IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
630  
631  /* Mesh stats attributes */
632  IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
633  IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
634  IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
635  IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
636  IEEE80211_IF_FILE(dropped_frames_no_route,
637  		  u.mesh.mshstats.dropped_frames_no_route, DEC);
638  
639  /* Mesh parameters */
640  IEEE80211_IF_FILE(dot11MeshMaxRetries,
641  		  u.mesh.mshcfg.dot11MeshMaxRetries, DEC);
642  IEEE80211_IF_FILE(dot11MeshRetryTimeout,
643  		  u.mesh.mshcfg.dot11MeshRetryTimeout, DEC);
644  IEEE80211_IF_FILE(dot11MeshConfirmTimeout,
645  		  u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC);
646  IEEE80211_IF_FILE(dot11MeshHoldingTimeout,
647  		  u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC);
648  IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC);
649  IEEE80211_IF_FILE(element_ttl, u.mesh.mshcfg.element_ttl, DEC);
650  IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC);
651  IEEE80211_IF_FILE(dot11MeshMaxPeerLinks,
652  		  u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC);
653  IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout,
654  		  u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC);
655  IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval,
656  		  u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC);
657  IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval,
658  		  u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC);
659  IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime,
660  		  u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC);
661  IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries,
662  		  u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC);
663  IEEE80211_IF_FILE(path_refresh_time,
664  		  u.mesh.mshcfg.path_refresh_time, DEC);
665  IEEE80211_IF_FILE(min_discovery_timeout,
666  		  u.mesh.mshcfg.min_discovery_timeout, DEC);
667  IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
668  		  u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC);
669  IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
670  		  u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC);
671  IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
672  		  u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
673  IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
674  IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
675  IEEE80211_IF_FILE(ht_opmode, u.mesh.mshcfg.ht_opmode, DEC);
676  IEEE80211_IF_FILE(dot11MeshHWMPactivePathToRootTimeout,
677  		  u.mesh.mshcfg.dot11MeshHWMPactivePathToRootTimeout, DEC);
678  IEEE80211_IF_FILE(dot11MeshHWMProotInterval,
679  		  u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC);
680  IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval,
681  		  u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC);
682  IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC);
683  IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration,
684  		  u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC);
685  IEEE80211_IF_FILE(dot11MeshConnectedToMeshGate,
686  		  u.mesh.mshcfg.dot11MeshConnectedToMeshGate, DEC);
687  IEEE80211_IF_FILE(dot11MeshNolearn, u.mesh.mshcfg.dot11MeshNolearn, DEC);
688  IEEE80211_IF_FILE(dot11MeshConnectedToAuthServer,
689  		  u.mesh.mshcfg.dot11MeshConnectedToAuthServer, DEC);
690  #endif
691  
692  #define DEBUGFS_ADD_MODE(name, mode) \
693  	debugfs_create_file(#name, mode, sdata->vif.debugfs_dir, \
694  			    sdata, &name##_ops)
695  
696  #define DEBUGFS_ADD_X(_bits, _name, _mode) \
697  	debugfs_create_x##_bits(#_name, _mode, sdata->vif.debugfs_dir, \
698  				&sdata->vif._name)
699  
700  #define DEBUGFS_ADD_X8(_name, _mode) \
701  	DEBUGFS_ADD_X(8, _name, _mode)
702  
703  #define DEBUGFS_ADD_X16(_name, _mode) \
704  	DEBUGFS_ADD_X(16, _name, _mode)
705  
706  #define DEBUGFS_ADD_X32(_name, _mode) \
707  	DEBUGFS_ADD_X(32, _name, _mode)
708  
709  #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400)
710  
add_common_files(struct ieee80211_sub_if_data * sdata)711  static void add_common_files(struct ieee80211_sub_if_data *sdata)
712  {
713  	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
714  	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
715  	DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
716  	DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
717  	DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_2ghz);
718  	DEBUGFS_ADD(rc_rateidx_vht_mcs_mask_5ghz);
719  	DEBUGFS_ADD(hw_queues);
720  
721  	if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
722  	    sdata->vif.type != NL80211_IFTYPE_NAN)
723  		DEBUGFS_ADD(aqm);
724  }
725  
add_sta_files(struct ieee80211_sub_if_data * sdata)726  static void add_sta_files(struct ieee80211_sub_if_data *sdata)
727  {
728  	DEBUGFS_ADD(bssid);
729  	DEBUGFS_ADD(aid);
730  	DEBUGFS_ADD(beacon_timeout);
731  	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
732  	DEBUGFS_ADD_MODE(beacon_loss, 0200);
733  	DEBUGFS_ADD_MODE(uapsd_queues, 0600);
734  	DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600);
735  	DEBUGFS_ADD_MODE(tdls_wider_bw, 0600);
736  	DEBUGFS_ADD_MODE(valid_links, 0400);
737  	DEBUGFS_ADD_MODE(active_links, 0600);
738  	DEBUGFS_ADD_X16(dormant_links, 0400);
739  }
740  
add_ap_files(struct ieee80211_sub_if_data * sdata)741  static void add_ap_files(struct ieee80211_sub_if_data *sdata)
742  {
743  	DEBUGFS_ADD(num_mcast_sta);
744  	DEBUGFS_ADD(num_sta_ps);
745  	DEBUGFS_ADD(dtim_count);
746  	DEBUGFS_ADD(num_buffered_multicast);
747  	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
748  	DEBUGFS_ADD_MODE(multicast_to_unicast, 0600);
749  }
750  
add_vlan_files(struct ieee80211_sub_if_data * sdata)751  static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
752  {
753  	/* add num_mcast_sta_vlan using name num_mcast_sta */
754  	debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
755  			    sdata, &num_mcast_sta_vlan_ops);
756  }
757  
add_ibss_files(struct ieee80211_sub_if_data * sdata)758  static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
759  {
760  	DEBUGFS_ADD_MODE(tsf, 0600);
761  }
762  
763  #ifdef CONFIG_MAC80211_MESH
764  
add_mesh_files(struct ieee80211_sub_if_data * sdata)765  static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
766  {
767  	DEBUGFS_ADD_MODE(tsf, 0600);
768  	DEBUGFS_ADD_MODE(estab_plinks, 0400);
769  }
770  
add_mesh_stats(struct ieee80211_sub_if_data * sdata)771  static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
772  {
773  	struct dentry *dir = debugfs_create_dir("mesh_stats",
774  						sdata->vif.debugfs_dir);
775  #define MESHSTATS_ADD(name)\
776  	debugfs_create_file(#name, 0400, dir, sdata, &name##_ops)
777  
778  	MESHSTATS_ADD(fwded_mcast);
779  	MESHSTATS_ADD(fwded_unicast);
780  	MESHSTATS_ADD(fwded_frames);
781  	MESHSTATS_ADD(dropped_frames_ttl);
782  	MESHSTATS_ADD(dropped_frames_no_route);
783  #undef MESHSTATS_ADD
784  }
785  
add_mesh_config(struct ieee80211_sub_if_data * sdata)786  static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
787  {
788  	struct dentry *dir = debugfs_create_dir("mesh_config",
789  						sdata->vif.debugfs_dir);
790  
791  #define MESHPARAMS_ADD(name) \
792  	debugfs_create_file(#name, 0600, dir, sdata, &name##_ops)
793  
794  	MESHPARAMS_ADD(dot11MeshMaxRetries);
795  	MESHPARAMS_ADD(dot11MeshRetryTimeout);
796  	MESHPARAMS_ADD(dot11MeshConfirmTimeout);
797  	MESHPARAMS_ADD(dot11MeshHoldingTimeout);
798  	MESHPARAMS_ADD(dot11MeshTTL);
799  	MESHPARAMS_ADD(element_ttl);
800  	MESHPARAMS_ADD(auto_open_plinks);
801  	MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
802  	MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
803  	MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
804  	MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval);
805  	MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
806  	MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
807  	MESHPARAMS_ADD(path_refresh_time);
808  	MESHPARAMS_ADD(min_discovery_timeout);
809  	MESHPARAMS_ADD(dot11MeshHWMPRootMode);
810  	MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
811  	MESHPARAMS_ADD(dot11MeshForwarding);
812  	MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
813  	MESHPARAMS_ADD(rssi_threshold);
814  	MESHPARAMS_ADD(ht_opmode);
815  	MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout);
816  	MESHPARAMS_ADD(dot11MeshHWMProotInterval);
817  	MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval);
818  	MESHPARAMS_ADD(power_mode);
819  	MESHPARAMS_ADD(dot11MeshAwakeWindowDuration);
820  	MESHPARAMS_ADD(dot11MeshConnectedToMeshGate);
821  	MESHPARAMS_ADD(dot11MeshNolearn);
822  	MESHPARAMS_ADD(dot11MeshConnectedToAuthServer);
823  #undef MESHPARAMS_ADD
824  }
825  #endif
826  
add_files(struct ieee80211_sub_if_data * sdata)827  static void add_files(struct ieee80211_sub_if_data *sdata)
828  {
829  	if (!sdata->vif.debugfs_dir)
830  		return;
831  
832  	DEBUGFS_ADD(flags);
833  	DEBUGFS_ADD(state);
834  
835  	if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
836  		add_common_files(sdata);
837  
838  	switch (sdata->vif.type) {
839  	case NL80211_IFTYPE_MESH_POINT:
840  #ifdef CONFIG_MAC80211_MESH
841  		add_mesh_files(sdata);
842  		add_mesh_stats(sdata);
843  		add_mesh_config(sdata);
844  #endif
845  		break;
846  	case NL80211_IFTYPE_STATION:
847  		add_sta_files(sdata);
848  		break;
849  	case NL80211_IFTYPE_ADHOC:
850  		add_ibss_files(sdata);
851  		break;
852  	case NL80211_IFTYPE_AP:
853  		add_ap_files(sdata);
854  		break;
855  	case NL80211_IFTYPE_AP_VLAN:
856  		add_vlan_files(sdata);
857  		break;
858  	default:
859  		break;
860  	}
861  }
862  
863  #undef DEBUGFS_ADD_MODE
864  #undef DEBUGFS_ADD
865  
866  #define DEBUGFS_ADD_MODE(dentry, name, mode) \
867  	debugfs_create_file(#name, mode, dentry, \
868  			    link, &link_##name##_ops)
869  
870  #define DEBUGFS_ADD(dentry, name) DEBUGFS_ADD_MODE(dentry, name, 0400)
871  
add_link_files(struct ieee80211_link_data * link,struct dentry * dentry)872  static void add_link_files(struct ieee80211_link_data *link,
873  			   struct dentry *dentry)
874  {
875  	DEBUGFS_ADD(dentry, txpower);
876  	DEBUGFS_ADD(dentry, user_power_level);
877  	DEBUGFS_ADD(dentry, ap_power_level);
878  
879  	switch (link->sdata->vif.type) {
880  	case NL80211_IFTYPE_STATION:
881  		DEBUGFS_ADD_MODE(dentry, smps, 0600);
882  		break;
883  	default:
884  		break;
885  	}
886  }
887  
ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data * sdata)888  void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
889  {
890  	char buf[10+IFNAMSIZ];
891  
892  	sprintf(buf, "netdev:%s", sdata->name);
893  	sdata->vif.debugfs_dir = debugfs_create_dir(buf,
894  		sdata->local->hw.wiphy->debugfsdir);
895  	sdata->debugfs.subdir_stations = debugfs_create_dir("stations",
896  							sdata->vif.debugfs_dir);
897  	add_files(sdata);
898  
899  	if (!(sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO))
900  		add_link_files(&sdata->deflink, sdata->vif.debugfs_dir);
901  }
902  
ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data * sdata)903  void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
904  {
905  	if (!sdata->vif.debugfs_dir)
906  		return;
907  
908  	debugfs_remove_recursive(sdata->vif.debugfs_dir);
909  	sdata->vif.debugfs_dir = NULL;
910  	sdata->debugfs.subdir_stations = NULL;
911  }
912  
ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data * sdata)913  void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
914  {
915  	struct dentry *dir;
916  	char buf[10 + IFNAMSIZ];
917  
918  	dir = sdata->vif.debugfs_dir;
919  
920  	if (IS_ERR_OR_NULL(dir))
921  		return;
922  
923  	sprintf(buf, "netdev:%s", sdata->name);
924  	debugfs_rename(dir->d_parent, dir, dir->d_parent, buf);
925  }
926  
ieee80211_link_debugfs_add(struct ieee80211_link_data * link)927  void ieee80211_link_debugfs_add(struct ieee80211_link_data *link)
928  {
929  	char link_dir_name[10];
930  
931  	if (WARN_ON(!link->sdata->vif.debugfs_dir))
932  		return;
933  
934  	/* For now, this should not be called for non-MLO capable drivers */
935  	if (WARN_ON(!(link->sdata->local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)))
936  		return;
937  
938  	snprintf(link_dir_name, sizeof(link_dir_name),
939  		 "link-%d", link->link_id);
940  
941  	link->debugfs_dir =
942  		debugfs_create_dir(link_dir_name,
943  				   link->sdata->vif.debugfs_dir);
944  
945  	DEBUGFS_ADD(link->debugfs_dir, addr);
946  	add_link_files(link, link->debugfs_dir);
947  }
948  
ieee80211_link_debugfs_remove(struct ieee80211_link_data * link)949  void ieee80211_link_debugfs_remove(struct ieee80211_link_data *link)
950  {
951  	if (!link->sdata->vif.debugfs_dir || !link->debugfs_dir) {
952  		link->debugfs_dir = NULL;
953  		return;
954  	}
955  
956  	if (link->debugfs_dir == link->sdata->vif.debugfs_dir) {
957  		WARN_ON(link != &link->sdata->deflink);
958  		link->debugfs_dir = NULL;
959  		return;
960  	}
961  
962  	debugfs_remove_recursive(link->debugfs_dir);
963  	link->debugfs_dir = NULL;
964  }
965  
ieee80211_link_debugfs_drv_add(struct ieee80211_link_data * link)966  void ieee80211_link_debugfs_drv_add(struct ieee80211_link_data *link)
967  {
968  	if (WARN_ON(!link->debugfs_dir))
969  		return;
970  
971  	drv_link_add_debugfs(link->sdata->local, link->sdata,
972  			     link->conf, link->debugfs_dir);
973  }
974  
ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data * link)975  void ieee80211_link_debugfs_drv_remove(struct ieee80211_link_data *link)
976  {
977  	if (!link || !link->debugfs_dir)
978  		return;
979  
980  	if (WARN_ON(link->debugfs_dir == link->sdata->vif.debugfs_dir))
981  		return;
982  
983  	/* Recreate the directory excluding the driver data */
984  	debugfs_remove_recursive(link->debugfs_dir);
985  	link->debugfs_dir = NULL;
986  
987  	ieee80211_link_debugfs_add(link);
988  }
989