diff options
author | Ashwin <ashwin.bhat@broadcom.com> | 2015-07-10 15:17:29 -0700 |
---|---|---|
committer | Alexander Levitskiy <sanek@google.com> | 2015-08-07 18:10:15 +0000 |
commit | 42fe48d30c41874e679b6552798de94797c5f402 (patch) | |
tree | 3f7839e676604de53e60e016ae7f75ecc41ae57a | |
parent | 9f27dc0fbcf0291095d4e0792588f3cee33000b7 (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/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/bcmevent.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/bcmsdh.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 58 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/common/include/proto/bcmevent.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_linux.c | 140 | ||||
-rwxr-xr-x | drivers/net/wireless/bcmdhd/dhd_sdio.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/include/bcmsdh.h | 32 |
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); |