[PATCH] staging:brcm80211:brcmfmac:add debugfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add debugfs in brcmfmac


Signed-off-by: Nohee Ko <noheek@xxxxxxxxxxxx>
---
 drivers/staging/brcm80211/Kconfig                |    9 ++-
 drivers/staging/brcm80211/brcmfmac/Makefile      |    2 +-
 drivers/staging/brcm80211/brcmfmac/debugfs.c     |   75 ++++++++++++
 drivers/staging/brcm80211/brcmfmac/debugfs.h     |   13 ++
 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c |  132 +++++++++++++++------
 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h |   24 ++++-
 6 files changed, 214 insertions(+), 41 deletions(-)
 create mode 100644 drivers/staging/brcm80211/brcmfmac/debugfs.c
 create mode 100644 drivers/staging/brcm80211/brcmfmac/debugfs.h

diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig
index 57d2d1b..fdc3cb0 100644
--- a/drivers/staging/brcm80211/Kconfig
+++ b/drivers/staging/brcm80211/Kconfig
@@ -1,4 +1,4 @@
-menuconfig BRCM80211
+config BRCM80211
 	tristate "Broadcom IEEE802.11n WLAN drivers"
 	depends on WLAN
 
@@ -30,4 +30,11 @@ config BRCMFMAC
 	  Broadcom IEEE802.11n FullMAC chipsets.  This driver uses the kernel's
 	  wireless extensions subsystem.  If you choose to build a module,
 	  it'll be called brcmfmac.ko.
+
+config BRCMFMAC_DEBUGFS
+	bool "Enable debugfs in brcmfmac"
+	depends on BRCMFMAC && DEBUG_FS
+	---help---
+	  This option will enable to access statistics for Broadcom fullmac
+	  Chipsets
 endchoice
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
index 76f2d8b..494d46e 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -44,4 +44,4 @@ DHDOFILES = dhd_linux.o ../util/linux_osl.o ../util/bcmutils.o dhd_common.o dhd_
 
 obj-m += brcmfmac.o
 brcmfmac-objs += $(DHDOFILES)
-
+brcmfmac-$(CONFIG_BRCMFMAC_DEBUGFS) += debugfs.o
diff --git a/drivers/staging/brcm80211/brcmfmac/debugfs.c b/drivers/staging/brcm80211/brcmfmac/debugfs.c
new file mode 100644
index 0000000..26123fc
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/debugfs.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include "wl_cfg80211.h"
+#include "debugfs.h"
+
+static int wl_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...)		\
+static ssize_t name## _read(struct file *file, char __user *userbuf,	\
+			    size_t count, loff_t *ppos)			\
+{									\
+	struct wl_priv *wl = file->private_data;		\
+	char buf[buflen];						\
+	int res;							\
+									\
+	res = scnprintf(buf, buflen, fmt "\n", ##value);		\
+	return simple_read_from_buffer(userbuf, count, ppos, buf, res);	\
+}									\
+									\
+static const struct file_operations name## _ops = {			\
+	.read = name## _read,						\
+	.open = wl_open_file_generic,				\
+};
+
+DEBUGFS_READONLY_FILE(beacon_int, 20, "%d", wl->profile->beacon_interval)
+DEBUGFS_READONLY_FILE(dtim_period, 20, "%d", wl->profile->dtim_period)
+
+#define DEBUGFS_ADD(name)						\
+	debugfs_create_file(#name, S_IRUGO, phyd, wl, &name## _ops);
+
+void wl_debugfs_add_params(struct wl_priv *wl)
+{
+	struct dentry *phyd = wl->debugfs.dir;
+
+	DEBUGFS_ADD(beacon_int);
+	DEBUGFS_ADD(dtim_period);
+}
+
+void wl_debugfs_add_netdev(struct wl_priv *wl)
+{
+	char buf[10+IFNAMSIZ];
+
+	sprintf(buf, "netdev:%s", wl_to_ndev(wl)->name);
+	wl->debugfs.dir = debugfs_create_dir(buf, wl_to_wiphy(wl)->debugfsdir);
+}
+
+void wl_debugfs_remove_netdev(struct wl_priv *wl)
+{
+	if (!wl->debugfs.dir)
+		return;
+
+	debugfs_remove_recursive(wl->debugfs.dir);
+	wl->debugfs.dir = NULL;
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/debugfs.h b/drivers/staging/brcm80211/brcmfmac/debugfs.h
new file mode 100644
index 0000000..aca0fa2
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/debugfs.h
@@ -0,0 +1,13 @@
+#ifndef _wl_debugfs_h_
+#define _wl_debugfs_h_
+
+#ifdef CONFIG_BRCMFMAC_DEBUGFS
+void wl_debugfs_add_params(struct wl_priv *wl);
+void wl_debugfs_add_netdev(struct wl_priv *wl);
+void wl_debugfs_remove_netdev(struct wl_priv *wl);
+#else
+static inline void wl_debugfs_add_params(struct wl_priv *wl) {}
+static inline void wl_debugfs_add_netdev(struct wl_priv *wl) {}
+static inline void wl_debugfs_remove_netdev(struct wl_priv *wl) {}
+#endif
+#endif /* __wl_debugfs_h */
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 20367a0..c3d5b41 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -47,7 +47,8 @@
 #include <net/rtnetlink.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/firmware.h>
-#include <wl_cfg80211.h>
+#include "wl_cfg80211.h"
+#include "debugfs.h"
 
 static struct sdio_func *cfg80211_sdio_func;
 static struct wl_dev *wl_cfg80211_dev;
@@ -332,6 +333,7 @@ static __used s32 wl_update_pmklist(struct net_device *dev,
 				      struct wl_pmk_list *pmk_list, s32 err);
 
 static void wl_set_mpc(struct net_device *ndev, int mpc);
+static u8 *wl_get_information_element(u8 *buf, s32 buf_len, enum wl_ie_id);
 
 #define WL_PRIV_GET() 							\
 	({								\
@@ -732,6 +734,7 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 	struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
 	struct net_device *ndev = wl_to_ndev(wl);
 	struct wlc_ssid ssid;
+	s32 passive_scan;
 	s32 err = 0;
 
 	/* Broadcast scan by default */
@@ -739,15 +742,12 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 
 	iscan->state = WL_ISCAN_STATE_SCANING;
 
-	if (wl->active_scan) {
-		s32 passive_scan = 0;
-		/* make it active scan */
-		err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
-				&passive_scan, sizeof(passive_scan));
-		if (unlikely(err)) {
-			WL_DBG(("error (%d)\n", err));
-			return err;
-		}
+	passive_scan = wl->active_scan ? 0 : 1;
+	err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
+			&passive_scan, sizeof(passive_scan));
+	if (unlikely(err)) {
+		WL_DBG(("error (%d)\n", err));
+		return err;
 	}
 	wl_set_mpc(ndev, 0);
 	wl->iscan_kickstart = true;
@@ -766,6 +766,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	struct wl_priv *wl = ndev_to_wl(ndev);
 	struct cfg80211_ssid *ssids;
 	struct wl_scan_req *sr = wl_to_sr(wl);
+	s32 passive_scan;
 	bool iscan_req;
 	bool spec_scan;
 	s32 err = 0;
@@ -823,16 +824,12 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 			WL_DBG(("Broadcast scan\n"));
 		}
 		WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
-		if (wl->active_scan) {
-			s32 pssive_scan = 0;
-			/* make it active scan */
-			err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-					&pssive_scan, sizeof(pssive_scan));
-			if (unlikely(err)) {
-				WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n",
-					err));
-				goto scan_out;
-			}
+		passive_scan = wl->active_scan ? 0 : 1;
+		err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+				&passive_scan, sizeof(passive_scan));
+		if (unlikely(err)) {
+			WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
+			goto scan_out;
 		}
 		wl_set_mpc(ndev, 0);
 		err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
@@ -2264,6 +2261,8 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	struct ieee80211_supported_band *band;
 	struct wl_cfg80211_bss_info *notif_bss_info;
 	struct wl_scan_req *sr = wl_to_sr(wl);
+	struct beacon_proberesp *beacon_proberesp;
+	s32 mgmt_type;
 	u32 signal;
 	u32 freq;
 	s32 err = 0;
@@ -2289,13 +2288,18 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 		band = wiphy->bands[IEEE80211_BAND_5GHZ];
 	notif_bss_info->rssi = bi->RSSI;
 	memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
+	mgmt_type = wl->active_scan ?
+		IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
 	if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
 		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-						  IEEE80211_STYPE_PROBE_RESP);
-	}
-	mgmt->u.probe_resp.timestamp = 0;
-	mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period);
-	mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability);
+							mgmt_type);
+	}
+	beacon_proberesp = wl->active_scan ?
+		(struct beacon_proberesp *)&mgmt->u.probe_resp :
+		(struct beacon_proberesp *)&mgmt->u.beacon;
+	beacon_proberesp->timestamp = 0;
+	beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
+	beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
 	wl_rst_ie(wl);
 	/*
 	* wl_add_ie is not necessary because it can only add duplicated
@@ -2307,18 +2311,18 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	* bi->rateset.rates);
 	*/
 	wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
-	wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX -
+	wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
 		 offsetof(struct wl_cfg80211_bss_info, frame_buf));
 	notif_bss_info->frame_len =
 	    offsetof(struct ieee80211_mgmt,
-		     u.probe_resp.variable) + wl_get_ielen(wl);
+		     u.beacon.variable) + wl_get_ielen(wl);
 	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
 	channel = ieee80211_get_channel(wiphy, freq);
 
 	WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
 		bi->SSID,
 		notif_bss_info->rssi, notif_bss_info->channel,
-		mgmt->u.probe_resp.capab_info, &bi->BSSID));
+		mgmt->u.beacon.capab_info, &bi->BSSID));
 
 	signal = notif_bss_info->rssi * 100;
 	if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
@@ -2546,11 +2550,33 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 	}
 }
 
+static u8 *wl_get_information_element(u8 *buf, s32 buf_len, enum wl_ie_id ie_id)
+{
+	s32 ie_len;
+
+	for (; buf_len > 0; buf_len -= ie_len) {
+		if (*buf == ie_id) {
+			WL_DBG(("found Information Element ID - %d\n", ie_id));
+			return buf;
+		} else {
+			ie_len = 2 + *(buf + 1);
+			buf += ie_len;
+		}
+	}
+
+	return NULL;
+}
+
 static s32 wl_update_bss_info(struct wl_priv *wl)
 {
 	struct cfg80211_bss *bss;
 	struct wl_bss_info *bi;
 	struct wlc_ssid *ssid;
+	u16 beacon_interval;
+	u8 dtim_period;
+	size_t ie_len;
+	u8 *ie;
+	u8 *tim;
 	s32 err = 0;
 
 	if (wl_is_ibssmode(wl))
@@ -2580,11 +2606,38 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 		err = wl_inform_single_bss(wl, bi);
 		if (unlikely(err))
 			goto update_bss_info_out;
+
+		ie = ((u8 *)bi) + bi->ie_offset;
+		ie_len = bi->ie_length;
+		beacon_interval = cpu_to_le16(bi->beacon_period);
 	} else {
 		WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
+		ie = bss->information_elements;
+		ie_len = bss->len_information_elements;
+		beacon_interval = bss->beacon_interval;
 		cfg80211_put_bss(bss);
 	}
 
+	tim = wl_get_information_element(ie, ie_len, WL_TIM);
+	if (tim) {
+		dtim_period = tim[3];
+	} else {
+		/*
+		* active scan was done so we could not get dtim
+		* information out of probe response.
+		* so we speficially query dtim information to dongle.
+		*/
+		err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
+			&dtim_period, sizeof(dtim_period));
+		if (unlikely(err)) {
+			WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
+			goto update_bss_info_out;
+		}
+	}
+
+	wl_update_prof(wl, NULL, &beacon_interval, WL_PROF_BEACONINT);
+	wl_update_prof(wl, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
+
 update_bss_info_out:
 	rtnl_unlock();
 	return err;
@@ -3108,18 +3161,10 @@ static s32 wl_init_priv(struct wl_priv *wl)
 
 	wl->scan_request = NULL;
 	wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
-#ifndef WL_ISCAN_DISABLED
 	wl->iscan_on = true;	/* iscan on & off switch.
 				 we enable iscan per default */
-#else
-	wl->iscan_on = false;
-#endif				/* WL_ISCAN_DISABLED */
-#ifndef WL_ROAM_DISABLED
-	wl->roam_on = true;	/* roam on & off switch.
+	wl->roam_on = false;	/* roam on & off switch.
 				 we enable roam per default */
-#else
-	wl->roam_on = false;
-#endif				/* WL_ROAM_DISABLED */
 
 	wl->iscan_kickstart = false;
 	wl->active_scan = true;	/* we do active scan for
@@ -3788,6 +3833,9 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl)
 {
 	s32 err = 0;
 
+	wl_debugfs_add_netdev(wl);
+	wl_debugfs_add_params(wl);
+
 	err = wl_config_dongle(wl, false);
 	if (unlikely(err))
 		return err;
@@ -3825,6 +3873,8 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
 	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
 	clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
+	wl_debugfs_remove_netdev(wl);
+
 	return err;
 }
 
@@ -3906,7 +3956,13 @@ wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
 		memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
 		break;
 	case WL_PROF_ACT:
-		wl->profile->active = *(bool *) data;
+		wl->profile->active = *(bool *)data;
+		break;
+	case WL_PROF_BEACONINT:
+		wl->profile->beacon_interval = *(u16 *)data;
+		break;
+	case WL_PROF_DTIMPERIOD:
+		wl->profile->dtim_period = *(u8 *)data;
 		break;
 	default:
 		WL_ERR(("unsupported item (%d)\n", item));
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index d125d90..956feba 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -112,6 +112,11 @@ do {									\
 				 */
 #define WL_FILE_NAME_MAX		256
 
+/* information elements */
+enum wl_ie_id {
+	WL_TIM = 5
+};
+
 /* dongle status */
 enum wl_status {
 	WL_STATUS_READY,
@@ -136,7 +141,9 @@ enum wl_prof_list {
 	WL_PROF_IBSS,
 	WL_PROF_BAND,
 	WL_PROF_BSSID,
-	WL_PROF_ACT
+	WL_PROF_ACT,
+	WL_PROF_BEACONINT,
+	WL_PROF_DTIMPERIOD
 };
 
 /* dongle iscan state */
@@ -151,6 +158,14 @@ enum wl_fw_status {
 	WL_NVRAM_LOADING_DONE
 };
 
+/* beacon / probe_response */
+struct beacon_proberesp {
+	__le64 timestamp;
+	__le16 beacon_int;
+	__le16 capab_info;
+	u8 variable[0];
+} __attribute__ ((packed));
+
 /* dongle configuration */
 struct wl_conf {
 	u32 mode;		/* adhoc , infrastructure or ap */
@@ -229,6 +244,8 @@ struct wl_profile {
 	u32 mode;
 	struct wlc_ssid ssid;
 	u8 bssid[ETHER_ADDR_LEN];
+	u16 beacon_interval;
+	u8 dtim_period;
 	struct wl_security sec;
 	struct wl_ibss ibss;
 	s32 band;
@@ -329,6 +346,11 @@ struct wl_priv {
 	bool scan_tried;	/* indicates if first scan attempted */
 	u8 *ioctl_buf;	/* ioctl buffer */
 	u8 *extra_buf;	/* maily to grab assoc information */
+#ifdef CONFIG_BRCMFMAC_DEBUGFS
+	struct {
+		struct dentry *dir;
+	} debugfs;
+#endif
 	u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
 };
 
-- 
1.7.0.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux