aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshwin <ashwin.bhat@broadcom.com>2015-07-10 15:17:29 -0700
committerAlexander Levitskiy <sanek@google.com>2015-08-07 18:10:15 +0000
commit42fe48d30c41874e679b6552798de94797c5f402 (patch)
tree3f7839e676604de53e60e016ae7f75ecc41ae57a
parent9f27dc0fbcf0291095d4e0792588f3cee33000b7 (diff)
net: wireless: bcmdhd: Added wake dump countersandroid-m-preview-2_r0.6
Added debug wakeup counters to dump for sdio for power related issues. bug 22776056 Change-Id: I01805fa0557be546eb20599ccc1dc8694f78f926 Signed-off-by: Ashwin <ashwin.bhat@broadcom.com>
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile4
-rw-r--r--drivers/net/wireless/bcmdhd/bcmevent.c19
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh.c12
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_linux.c58
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c23
-rw-r--r--drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h1
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h25
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c140
-rwxr-xr-xdrivers/net/wireless/bcmdhd/dhd_sdio.c44
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh.h32
10 files changed, 279 insertions, 79 deletions
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 19fd823e43f2..484262d63005 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -59,6 +59,10 @@ DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_HIGH=-60
DHDCFLAGS += -DCUSTOM_TDLS_RSSI_THRESHOLD_LOW=-70
DHDCFLAGS += -DCUSTOM_TDLS_IDLE_MODE_SETTING=40000
+# debug info
+ DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS
+ DHDCFLAGS += -DDHD_WAKE_EVENT_STATUS
+
#########################
# Chip dependent feature
#########################
diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c
index dcbbb019bcfb..8261f230c8b6 100644
--- a/drivers/net/wireless/bcmdhd/bcmevent.c
+++ b/drivers/net/wireless/bcmdhd/bcmevent.c
@@ -162,3 +162,22 @@ const bcmevent_name_t bcmevent_names[] = {
};
const int bcmevent_names_size = ARRAYSIZE(bcmevent_names);
+
+const char *bcmevent_get_name(uint event_type)
+{
+ const char *event_name = NULL;
+
+ uint idx;
+ for (idx = 0; idx < bcmevent_names_size; idx++) {
+
+ if (bcmevent_names[idx].event == event_type) {
+ event_name = bcmevent_names[idx].name;
+ break;
+ }
+ }
+
+ /* if we find an event name in the array, return it.
+ * otherwise return unknown string.
+ */
+ return ((event_name) ? event_name : "Unknown Event");
+}
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c
index b2ffb18d64e1..bb264e89943b 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh.c
@@ -48,18 +48,6 @@
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
-/**
- * BCMSDH API context
- */
-struct bcmsdh_info
-{
- bool init_success; /* underlying driver successfully attached */
- void *sdioh; /* handler for sdioh */
- uint32 vendevid; /* Target Vendor and Device ID on SD bus */
- osl_t *osh;
- bool regfail; /* Save status of last reg_read/reg_write call */
- uint32 sbwad; /* Save backplane window address */
-};
/* local copy of bcm sd handler */
bcmsdh_info_t * l_bcmsdh = NULL;
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
index 77ea8139ce98..0cd2430d2bbc 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
@@ -2,13 +2,13 @@
* SDIO access interface for drivers - linux specific (pci only)
*
* Copyright (C) 1999-2013, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -16,7 +16,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -35,6 +35,9 @@
#include <linux/pci.h>
#include <linux/completion.h>
+#ifdef DHD_WAKE_STATUS
+#include <linux/wakeup_reason.h>
+#endif
#include <osl.h>
#include <pcicfg.h>
@@ -47,7 +50,7 @@ extern void dhdsdio_isr(void * args);
#include <bcmutils.h>
#include <dngl_stats.h>
#include <dhd.h>
-#endif
+#endif
/**
* SDIO Host Controller info
@@ -71,7 +74,7 @@ struct bcmsdh_hc {
bool oob_irq_enable_flag;
#if defined(OOB_INTR_ONLY)
spinlock_t irq_lock;
-#endif
+#endif
};
static bcmsdh_hc_t *sdhcinfo = NULL;
@@ -146,11 +149,11 @@ EXPORT_SYMBOL(bcmsdh_remove);
/* forward declarations */
static int __devinit bcmsdh_probe(struct device *dev);
static int __devexit bcmsdh_remove(struct device *dev);
-#endif
+#endif
#if !defined(BCMLXSDMMC)
static
-#endif
+#endif
int bcmsdh_probe(struct device *dev)
{
osl_t *osh = NULL;
@@ -160,7 +163,7 @@ int bcmsdh_probe(struct device *dev)
#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
struct platform_device *pdev;
struct resource *r;
-#endif
+#endif
int irq = 0;
uint32 vendevid;
unsigned long irq_flags = 0;
@@ -171,7 +174,7 @@ int bcmsdh_probe(struct device *dev)
irq = platform_get_irq(pdev, 0);
if (!r || irq < 0)
return -ENXIO;
-#endif
+#endif
#if defined(OOB_INTR_ONLY)
#ifdef HW_OOB
@@ -187,7 +190,7 @@ int bcmsdh_probe(struct device *dev)
SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
goto err;
}
-#endif
+#endif
/* allocate SDIO Host Controller state info */
if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) {
SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
@@ -216,7 +219,7 @@ int bcmsdh_probe(struct device *dev)
SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
goto err;
}
-#endif
+#endif
sdhc->sdh = sdh;
sdhc->oob_irq = irq;
sdhc->oob_flags = irq_flags;
@@ -224,7 +227,7 @@ int bcmsdh_probe(struct device *dev)
sdhc->oob_irq_enable_flag = FALSE;
#if defined(OOB_INTR_ONLY)
spin_lock_init(&sdhc->irq_lock);
-#endif
+#endif
/* chain SDIO Host Controller info together */
sdhc->next = sdhcinfo;
@@ -260,9 +263,34 @@ err:
return -ENODEV;
}
+#ifdef DHD_WAKE_STATUS
+int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh)
+{
+ return bcmsdh->total_wake_count;
+}
+
+int bcmsdh_set_get_wake(int flag)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (sdhcinfo) {
+ bcmsdh_info_t *bcmsdh = sdhcinfo->sdh;
+ spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
+
+ ret = bcmsdh->pkt_wake;
+ bcmsdh->total_wake_count += flag;
+ bcmsdh->pkt_wake = flag;
+
+ spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
+ }
+ return ret;
+}
+#endif
+
#if !defined(BCMLXSDMMC)
static
-#endif
+#endif
int bcmsdh_remove(struct device *dev)
{
bcmsdh_hc_t *sdhc, *prev;
@@ -311,7 +339,7 @@ int bcmsdh_remove(struct device *dev)
#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY)
dev_set_drvdata(dev, NULL);
-#endif
+#endif
return 0;
}
@@ -698,7 +726,7 @@ bool bcmsdh_is_oob_intr_registered(void)
else
return FALSE;
}
-#endif
+#endif
#if defined(BCMLXSDMMC)
void *bcmsdh_get_drvdata(void)
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
index a2d5cfb56a97..dc95c86ad023 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c
@@ -2,13 +2,13 @@
* BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel
*
* Copyright (C) 1999-2013, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -16,7 +16,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -81,7 +81,6 @@
#ifdef WL_CFG80211
extern void wl_cfg80211_set_parent_dev(void *dev);
#endif
-
extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
extern int dhd_os_check_wakelock(void *dhdp);
@@ -228,7 +227,7 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev)
#ifdef CONFIG_PARTIALRESUME
wifi_process_partial_resume(WIFI_PR_INIT);
#endif
-#endif
+#endif
dhd_mmc_suspend = TRUE;
smp_mb();
@@ -239,18 +238,26 @@ static int bcmsdh_sdmmc_resume(struct device *pdev)
{
#if defined(OOB_INTR_ONLY)
struct sdio_func *func = dev_to_sdio_func(pdev);
-#endif
+#endif
+ int wakeup = 0;
+#if defined(CONFIG_PARTIALRESUME) || defined(DHD_WAKE_STATUS)
+ wakeup = check_wakeup_reason(bcmsdh_get_irq());
+#endif /* CONFIG_PARTIALRESUME || DHD_WAKE_STATUS */
sd_trace(("%s Enter\n", __FUNCTION__));
dhd_mmc_suspend = FALSE;
#if defined(OOB_INTR_ONLY)
if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) {
+ if (wakeup) {
#ifdef CONFIG_PARTIALRESUME
- if (check_wakeup_reason(bcmsdh_get_irq()))
wifi_process_partial_resume(WIFI_PR_NOTIFY_RESUME);
#endif
+#ifdef DHD_WAKE_STATUS
+ bcmsdh_set_get_wake(1);
+#endif
+ }
bcmsdh_oob_intr_set(1);
}
-#endif
+#endif
smp_mb();
return 0;
}
diff --git a/drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h
index 26612d5d24b6..7d29e8e3ea8c 100644
--- a/drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h
+++ b/drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h
@@ -234,6 +234,7 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
#define WLC_E_ROAM_EXP_EVENT 143 /* Expanded roam event */
#define WLC_E_LAST 144 /* highest val + 1 for range checking */
+extern const char *bcmevent_get_name(uint event_type);
/* Table of event name strings for UIs and debugging dumps */
typedef struct {
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index b66c5f725dcb..86fd40106de4 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -350,6 +350,28 @@ typedef struct dhd_pub {
bool lazy_roam_enable;
#endif /* GSCAN_SUPPORT */
} dhd_pub_t;
+
+typedef struct {
+ uint rxwake;
+ uint rcwake;
+#ifdef DHD_WAKE_RX_STATUS
+ uint rx_bcast;
+ uint rx_arp;
+ uint rx_mcast;
+ uint rx_multi_ipv6;
+ uint rx_icmpv6;
+ uint rx_icmpv6_ra;
+ uint rx_icmpv6_na;
+ uint rx_icmpv6_ns;
+ uint rx_multi_ipv4;
+ uint rx_multi_other;
+ uint rx_ucast;
+#endif
+#ifdef DHD_WAKE_EVENT_STATUS
+ uint rc_event[WLC_E_LAST];
+#endif
+} wake_counts_t;
+
typedef struct dhd_cmn {
osl_t *osh; /* OSL handle */
dhd_pub_t *dhd;
@@ -527,7 +549,8 @@ extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason);
extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
-extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt, uint8 chan);
+extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt,
+ uint8 chan, int pkt_wake, wake_counts_t *wcp);
/* Return pointer to interface name */
extern char *dhd_ifname(dhd_pub_t *dhdp, int idx);
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index c7a18b3148bb..c890a92cd1e1 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -3,13 +3,13 @@
* Basically selected code segments from usb-cdc.c and usb-rndis.c
*
* Copyright (C) 1999-2013, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -17,7 +17,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -145,10 +145,10 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait);
#if defined(OOB_INTR_ONLY)
extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable);
-#endif
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1)
static void dhd_hang_process(struct work_struct *work);
-#endif
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
MODULE_LICENSE("GPL v2");
#endif /* LinuxVer */
@@ -794,7 +794,6 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf),
TRUE, 0) < 0)
DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__));
-
#ifndef ENABLE_FW_ROAM_SUSPEND
/* Disable firmware roaming during suspend */
bcm_mkiovar("roam_off", (char *)&roamvar, 4,
@@ -1540,7 +1539,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
/* Look into the packet and update the packet priority */
#ifndef PKTPRIO_OVERRIDE
if (PKTPRIO(pktbuf) == 0)
-#endif
+#endif
pktsetprio(pktbuf, FALSE);
#ifdef PROP_TXSTATUS
@@ -1758,6 +1757,8 @@ static const PKTTYPE_INFO packet_type_info[] =
{ ETHER_TYPE_BRCM, "BRCM" },
{ ETHER_TYPE_802_1X, "802.1X" },
{ ETHER_TYPE_WAI, "WAPI" },
+ { ETHER_TYPE_IPV6, "IPv6" },
+ { ETHER_TYPE_8021Q, "1Q" },
{ 0, ""}
};
@@ -1826,7 +1827,8 @@ static int dhd_rx_suspend_again(struct sk_buff *skb)
#endif
void
-dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
+dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan,
+ int pkt_wake, wake_counts_t *wcp)
{
dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
struct sk_buff *skb;
@@ -1842,11 +1844,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
void *skbhead = NULL;
void *skbprev = NULL;
#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
+#if defined(DHD_RX_DUMP) || defined(DHD_WAKE_STATUS)
+ char *dump_data;
+#endif /* DHD_RX_DUMP || DHD_WAKE_STATUS */
#ifdef DHD_RX_DUMP
#ifdef DHD_RX_FULL_DUMP
int k;
#endif /* DHD_RX_FULL_DUMP */
- char *dump_data;
uint16 protocol;
#endif /* DHD_RX_DUMP */
@@ -1905,8 +1909,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
eth = skb->data;
len = skb->len;
-#ifdef DHD_RX_DUMP
+#if defined(DHD_RX_DUMP) || defined(DHD_WAKE_STATUS)
dump_data = skb->data;
+#endif /* DHD_RX_DUMP || DHD_WAKE_STATUS */
+#ifdef DHD_RX_DUMP
protocol = (dump_data[12] << 8) | dump_data[13];
DHD_ERROR(("RX DUMP - %s\n", _get_packet_type_str(protocol)));
@@ -1981,7 +1987,18 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
wl_event_to_host_order(&event);
if (!tout_ctrl)
tout_ctrl = DHD_PACKET_TIMEOUT_MS;
-
+#ifdef DHD_WAKE_STATUS
+ if (unlikely(pkt_wake)) {
+ wcp->rcwake++;
+ DHD_ERROR(("DHD_WAKE_DBG: %s - %d\n", bcmevent_get_name(event.event_type),
+ event.event_type));
+#ifdef DHD_WAKE_EVENT_STATUS
+ if (event.event_type < WLC_E_LAST)
+ wcp->rc_event[event.event_type]++;
+#endif
+ pkt_wake = 0;
+ }
+#endif
#if defined(PNO_SUPPORT)
if (event.event_type == WLC_E_PFN_NET_FOUND) {
/* enforce custom wake lock to garantee that Kernel not suspended */
@@ -1999,8 +2016,67 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
#else
tout_rx = DHD_PACKET_TIMEOUT_MS;
#endif
+#ifdef DHD_WAKE_STATUS
+ if (unlikely(pkt_wake)) {
+ wcp->rxwake++;
+#ifdef DHD_WAKE_RX_STATUS
+#define ETHER_ICMP6_HEADER 20
+#define ETHER_IPV6_SADDR (ETHER_ICMP6_HEADER + 2)
+#define ETHER_IPV6_DAADR (ETHER_IPV6_SADDR + IPV6_ADDR_LEN)
+#define ETHER_ICMPV6_TYPE (ETHER_IPV6_DAADR + IPV6_ADDR_LEN)
+ if (ntoh16(skb->protocol) == ETHER_TYPE_ARP) { /* ARP */
+ wcp->rx_arp++;
+ DHD_ERROR(("DHD_WAKE_DBG: ARP\n"));
+ }
+ if (dump_data[0] == 0xFF) { /* Broadcast */
+ wcp->rx_bcast++;
+ DHD_ERROR(("DHD_WAKE_DBG: BCAST\n"));
+ } else if (dump_data[0] & 0x01) { /* Multicast */
+ wcp->rx_mcast++;
+ DHD_ERROR(("DHD_WAKE_DBG: Multicast "));
+ if (ntoh16(skb->protocol) == ETHER_TYPE_IPV6) {
+ wcp->rx_multi_ipv6++;
+ if ((skb->len > ETHER_ICMP6_HEADER) &&
+ (dump_data[ETHER_ICMP6_HEADER] == IPPROTO_ICMPV6)) {
+ wcp->rx_icmpv6++;
+ if (skb->len > ETHER_ICMPV6_TYPE) {
+ switch (dump_data[ETHER_ICMPV6_TYPE]) {
+ case NDISC_ROUTER_ADVERTISEMENT:
+ wcp->rx_icmpv6_ra++;
+ DHD_ERROR(("RA"));
+ break;
+ case NDISC_NEIGHBOUR_ADVERTISEMENT:
+ wcp->rx_icmpv6_na++;
+ DHD_ERROR(("NA"));
+ break;
+ case NDISC_NEIGHBOUR_SOLICITATION:
+ wcp->rx_icmpv6_ns++;
+ DHD_ERROR(("NS"));
+ break;
+ }
+ }
+ }
+ DHD_ERROR(("\n"));
+ } else if (dump_data[2] == 0x5E) {
+ wcp->rx_multi_ipv4++;
+ DHD_ERROR(("ipv4\n"));
+ } else {
+ wcp->rx_multi_other++;
+ DHD_ERROR(("other\n"));
+ }
+ } else { /* Unicast */
+ wcp->rx_ucast++;
+ DHD_ERROR(("DHD_WAKE_DBG: Unicast\n"));
+ }
+#undef ETHER_ICMP6_HEADER
+#undef ETHER_IPV6_SADDR
+#undef ETHER_IPV6_DAADR
+#undef ETHER_ICMPV6_TYPE
+#endif
+ pkt_wake = 0;
+ }
+#endif
}
-
ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
ifp = dhd->iflist[ifidx];
@@ -2946,7 +3022,7 @@ exit:
#if defined(WL_CFG80211)
if (ifidx == 0 && !dhd_download_fw_on_driverload)
wl_android_wifi_off(net);
-#endif
+#endif
dhd->pub.rxcnt_timeout = 0;
dhd->pub.txcnt_timeout = 0;
@@ -2998,7 +3074,7 @@ dhd_open(struct net_device *net)
goto exit;
}
-#endif
+#endif
ifidx = dhd_net2idx(dhd, net);
DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
@@ -3028,7 +3104,7 @@ dhd_open(struct net_device *net)
goto exit;
}
}
-#endif
+#endif
if (dhd->pub.busstate != DHD_BUS_DATA) {
@@ -3127,7 +3203,7 @@ dhd_osl_detach(osl_t *osh)
#if defined(BCMLXSDMMC)
up(&dhd_chipup_sem);
#endif
-#endif
+#endif
}
int
@@ -3580,7 +3656,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* Enable oob at firmware */
dhd_enable_oob_intr(dhd->pub.bus, TRUE);
-#endif
+#endif
/* If bus is not ready, can't come up */
if (dhd->pub.busstate != DHD_BUS_DATA) {
@@ -3749,13 +3825,13 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd)
return ret;
#else
return 0;
-#endif
+#endif
}
}
}
return 0;
}
-#endif
+#endif
int
dhd_preinit_ioctls(dhd_pub_t *dhd)
{
@@ -3971,7 +4047,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
#else
(void)concurrent_mode;
-#endif
+#endif
}
DHD_ERROR(("Firmware up: op_mode=0x%04x, "
@@ -4060,7 +4136,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if (ap_fw_loaded == TRUE) {
dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0);
}
-#endif
+#endif
#if defined(KEEP_ALIVE)
{
@@ -4069,7 +4145,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(SOFTAP)
if (ap_fw_loaded == FALSE)
-#endif
+#endif
if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
if ((res = dhd_keep_alive_onoff(dhd)) < 0)
DHD_ERROR(("%s set keeplive failed %d\n",
@@ -4240,7 +4316,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if (arpoe && !ap_fw_loaded) {
#else
if (arpoe) {
-#endif
+#endif
dhd_arp_offload_enable(dhd, TRUE);
dhd_arp_offload_set(dhd, dhd_arp_mode);
} else {
@@ -4278,7 +4354,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(PROP_TXSTATUS) && defined(PROP_TXSTATUS_VSDB)
bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, buf, sizeof(buf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
-#endif
+#endif
#endif /* DISABLE_11N */
@@ -4683,7 +4759,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
dhd_registration_check = TRUE;
up(&dhd_registration_sem);
}
-#endif
+#endif
return 0;
fail:
@@ -4720,7 +4796,7 @@ dhd_bus_detach(dhd_pub_t *dhdp)
#if defined(OOB_INTR_ONLY)
bcmsdh_unregister_oob_intr();
-#endif
+#endif
}
}
}
@@ -4945,7 +5021,7 @@ dhd_module_init(void)
#if 1 && defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
int retry = POWERUP_MAX_RETRY;
int chip_up = 0;
-#endif
+#endif
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -4965,7 +5041,7 @@ dhd_module_init(void)
DHD_ERROR(("Invalid module parameters.\n"));
error = -EINVAL;
} while (0);
-#endif
+#endif
if (error)
goto fail_0;
@@ -5007,7 +5083,7 @@ dhd_module_init(void)
goto fail_1;
#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */
-#endif
+#endif
#if defined(CONFIG_WIFI_CONTROL_FUNC) && defined(BCMLXSDMMC)
/* If the wifi_set_power() is failed,
@@ -5022,7 +5098,7 @@ dhd_module_init(void)
#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
sema_init(&dhd_registration_sem, 0);
-#endif
+#endif
error = dhd_bus_register();
@@ -5063,7 +5139,7 @@ fail_1:
#if defined(CONFIG_WIFI_CONTROL_FUNC)
wl_android_wifictrl_func_del();
-#endif
+#endif
/* Call customer gpio to turn off power with WL_REG_ON signal */
dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
@@ -5480,7 +5556,7 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
dhd_os_sdunlock(dhd);
wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout);
dhd_os_sdlock(dhd);
-#endif
+#endif
return;
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 5e4fa1bd1d08..6fb3b9279ca4 100755
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -370,6 +370,7 @@ typedef struct dhd_bus {
uint8 glom_mode; /* Glom mode - 0-copy mode, 1 - Multi-descriptor mode */
uint32 glomsize; /* Glom size limitation */
#endif
+ wake_counts_t wake_counts;
} dhd_bus_t;
/* clkstate */
@@ -2833,7 +2834,9 @@ void
dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
{
dhd_bus_t *bus = dhdp->bus;
-
+#if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS)
+ int i;
+#endif
bcm_bprintf(strbuf, "Bus SDIO structure:\n");
bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
@@ -2842,6 +2845,29 @@ dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
bus->rxlen, bus->rx_seq);
bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
+#ifdef DHD_WAKE_STATUS
+ bcm_bprintf(strbuf, "wake %u rxwake %u readctrlwake %u\n",
+ bcmsdh_get_total_wake(bus->sdh), bus->wake_counts.rxwake,
+ bus->wake_counts.rcwake);
+#ifdef DHD_WAKE_RX_STATUS
+ bcm_bprintf(strbuf, " unicast %u multicast %u broadcast %u arp %u\n",
+ bus->wake_counts.rx_ucast, bus->wake_counts.rx_mcast,
+ bus->wake_counts.rx_bcast, bus->wake_counts.rx_arp);
+ bcm_bprintf(strbuf, " multi4 %u multi6 %u icmp6 %u multiother %u\n",
+ bus->wake_counts.rx_multi_ipv4, bus->wake_counts.rx_multi_ipv6,
+ bus->wake_counts.rx_icmpv6, bus->wake_counts.rx_multi_other);
+ bcm_bprintf(strbuf, " icmp6_ra %u, icmp6_na %u, icmp6_ns %u\n",
+ bus->wake_counts.rx_icmpv6_ra, bus->wake_counts.rx_icmpv6_na,
+ bus->wake_counts.rx_icmpv6_ns);
+#endif
+#ifdef DHD_WAKE_EVENT_STATUS
+ for (i = 0; i < WLC_E_LAST; i++)
+ if (bus->wake_counts.rc_event[i] != 0)
+ bcm_bprintf(strbuf, " %s = %u\n", bcmevent_get_name(i),
+ bus->wake_counts.rc_event[i]);
+ bcm_bprintf(strbuf, "\n");
+#endif
+#endif
bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
bus->pollrate, bus->pollcnt, bus->regfails);
@@ -4897,7 +4923,7 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord
void **pkt, uint32 *pkt_count);
static uint8
-dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
+dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq, int pkt_wake)
{
uint16 dlen, totlen;
uint8 *dptr, num = 0;
@@ -5310,7 +5336,8 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
} while (temp);
if (cnt) {
dhd_os_sdunlock(bus->dhd);
- dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
+ dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0, pkt_wake, &bus->wake_counts);
+ pkt_wake = 0;
dhd_os_sdlock(bus->dhd);
}
}
@@ -5348,13 +5375,16 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
uint reorder_info_len;
uint pkt_count;
-
+ int pkt_wake = 0;
#if defined(DHD_DEBUG) || defined(SDTEST)
bool sdtest = FALSE; /* To limit message spew from test mode */
#endif
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
+#ifdef DHD_WAKE_STATUS
+ pkt_wake = bcmsdh_set_get_wake(0);
+#endif
bus->readframes = TRUE;
if (!KSO_ENAB(bus)) {
@@ -5396,7 +5426,8 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
uint8 cnt;
DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
__FUNCTION__, bus->glomd, bus->glom));
- cnt = dhdsdio_rxglom(bus, rxseq);
+ cnt = dhdsdio_rxglom(bus, rxseq, pkt_wake);
+ pkt_wake = 0;
DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
rxseq += cnt - 1;
rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
@@ -5913,7 +5944,8 @@ deliver:
/* Unlock during rx call */
dhd_os_sdunlock(bus->dhd);
- dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
+ dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan, pkt_wake, &bus->wake_counts);
+ pkt_wake = 0;
dhd_os_sdlock(bus->dhd);
}
rxcount = maxframes - rxleft;
diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h
index 4937daaa0942..bf4fcb65692f 100644
--- a/drivers/net/wireless/bcmdhd/include/bcmsdh.h
+++ b/drivers/net/wireless/bcmdhd/include/bcmsdh.h
@@ -4,13 +4,13 @@
* abstract OS and BUS specific details of SDIO
*
* Copyright (C) 1999-2013, Broadcom Corporation
- *
+ *
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
- *
+ *
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
@@ -18,7 +18,7 @@
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
- *
+ *
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
@@ -44,8 +44,25 @@ extern const uint bcmsdh_msglevel;
#define BCMSDH_ADAPTER
#endif /* BCMSDIO && (BCMSDIOH_STD || BCMSDIOH_BCM || BCMSDIOH_SPI) */
+/**
+ * BCMSDH API context
+ */
+typedef struct bcmsdh_info
+{
+ bool init_success; /* underlying driver successfully attached */
+ void *sdioh; /* handler for sdioh */
+ uint32 vendevid; /* Target Vendor and Device ID on SD bus */
+ osl_t *osh;
+ bool regfail; /* Save status of last reg_read/reg_write call */
+ uint32 sbwad; /* Save backplane window address */
+#ifdef DHD_WAKE_STATUS
+ unsigned int total_wake_count;
+ int pkt_wake;
+ int wake_irq;
+#endif
+} bcmsdh_info_t;
+
/* forward declarations */
-typedef struct bcmsdh_info bcmsdh_info_t;
typedef void (*bcmsdh_cb_fn_t)(void *);
extern struct device *pm_dev;
@@ -80,6 +97,11 @@ extern void bcmsdh_intr_forward(void *sdh, bool pass);
extern bool bcmsdh_intr_pending(void *sdh);
#endif
+#ifdef DHD_WAKE_STATUS
+int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh);
+int bcmsdh_set_get_wake(int flag);
+#endif
+
/* Register a callback to be called if and when bcmsdh detects
* device removal. No-op in the case of non-removable/hardwired devices.
*/
@@ -216,7 +238,7 @@ extern int bcmsdh_register_oob_intr(void * dhdp);
extern void bcmsdh_unregister_oob_intr(void);
extern void bcmsdh_oob_intr_set(bool enable);
extern bool bcmsdh_is_oob_intr_registered(void);
-#endif
+#endif
/* Function to pass device-status bits to DHD. */
extern uint32 bcmsdh_get_dstatus(void *sdh);