aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/dhd_linux.c
diff options
context:
space:
mode:
authorsbrissen <sbrissen@hotmail.com>2013-04-24 13:09:33 -0400
committersbrissen <sbrissen@hotmail.com>2013-04-25 10:50:50 -0400
commitc421809918b7106b40a81134f9fb5103146fc715 (patch)
tree89b0147d51d2b2650c5ded666a08613ba0cab3c1 /drivers/net/wireless/bcmdhd/dhd_linux.c
parent43aaedbcde478c8e032771d62a1956133b29b1d4 (diff)
downloadkernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.zip
kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.gz
kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.bz2
update bcmdhd driver from GT-9505 Source
drivers pulled from http://review.cyanogenmod.org/#/c/36122/ Change-Id: Ide4aef99ee1d594f4222ae69aca0bdb7d563e80a
Diffstat (limited to 'drivers/net/wireless/bcmdhd/dhd_linux.c')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c1808
1 files changed, 1191 insertions, 617 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index 8702a44..ff8e634 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c 358016 2012-09-20 22:36:51Z $
+ * $Id: dhd_linux.c 394719 2013-04-03 13:22:12Z $
*/
#include <typedefs.h>
@@ -78,6 +78,7 @@
#define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */
#define TSMAX 1000 /* max no. of timing record kept */
#define NUMBIN 34
+
static uint32 tsidx = 0;
static uint32 htsf_seqnum = 0;
uint32 tsfsync;
@@ -95,20 +96,14 @@ typedef struct histo_ {
static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
#endif /* WLMEDIA_HTSF */
-#ifndef DTIM_COUNT
-#define DTIM_COUNT 3
-#endif
-
-#if defined(PKT_FILTER_SUPPORT)
-#if defined(BLOCK_IPV6_PACKET)
+#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4)
#define HEX_PREF_STR "0x"
#define UNI_FILTER_STR "010000000000"
#define ZERO_ADDR_STR "000000000000"
#define ETHER_TYPE_STR "0000"
#define IPV6_FILTER_STR "20"
#define ZERO_TYPE_STR "00"
-#endif /* BLOCK_IPV6_PACKET */
-#endif /* PKT_FILTER_SUPPORT */
+#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */
#if defined(SOFTAP)
extern bool ap_cfg_running;
@@ -130,7 +125,7 @@ extern bool ap_fw_loaded;
#include <wl_android.h>
#ifdef ARP_OFFLOAD_SUPPORT
-void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add);
+void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx);
static int dhd_device_event(struct notifier_block *this,
unsigned long event,
void *ptr);
@@ -196,13 +191,14 @@ extern wl_iw_extra_params_t g_wl_iw_params;
#endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
#endif /* CUSTOMER_HW4 && CONFIG_PARTIALSUSPEND_SLP */
-extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
+extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
#ifdef PKT_FILTER_SUPPORT
extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg);
extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
#endif
+#ifdef CUSTOMER_HW4
#ifdef READ_MACADDR
extern int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac);
#endif
@@ -222,11 +218,20 @@ extern int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac);
#ifdef MIMO_ANT_SETTING
extern int dhd_sel_ant_from_file(dhd_pub_t *dhd);
#endif
-
#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE
int dhd_customer_set_country(dhd_pub_t *dhd);
#endif
+#else
+
+#ifdef READ_MACADDR
+extern int dhd_read_macaddr(struct dhd_info *dhd);
+#endif
+#ifdef WRITE_MACADDR
+extern int dhd_write_macaddr(struct ether_addr *mac);
+#endif
+#endif /* CUSTOMER_HW4 */
+
/* Interface control information */
typedef struct dhd_if {
struct dhd_info *info; /* back pointer to dhd_info */
@@ -273,11 +278,6 @@ static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0;
#endif /* WLMEDIA_HTSF */
-#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP)
-/* SLP_wakelock_alternative_code */
-extern struct device *pm_dev;
-#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */
-
/* Local private structure (extension of pub) */
typedef struct dhd_info {
#if defined(CONFIG_WIRELESS_EXT)
@@ -310,6 +310,10 @@ typedef struct dhd_info {
tsk_ctl_t thr_dpc_ctl;
tsk_ctl_t thr_wdt_ctl;
+#ifdef RXFRAME_THREAD
+ tsk_ctl_t thr_rxf_ctl;
+ spinlock_t rxf_lock;
+#endif /* RXFRAME_THREAD */
#endif /* DHDTHREAD */
bool dhd_tasklet_create;
tsk_ctl_t thr_sysioc_ctl;
@@ -319,9 +323,10 @@ typedef struct dhd_info {
/* Wakelocks */
#if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- struct wake_lock wl_wifi; /* Wifi wakelock */
- struct wake_lock wl_rxwake; /* Wifi rx wakelock */
- struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */
+ struct wake_lock *wl_wifi; /* Wifi wakelock */
+ struct wake_lock *wl_rxwake; /* Wifi rx wakelock */
+ struct wake_lock *wl_ctrlwake; /* Wifi ctrl wakelock */
+ struct wake_lock *wl_wdwake; /* Wifi wd wakelock */
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
@@ -333,6 +338,7 @@ typedef struct dhd_info {
#endif
spinlock_t wakelock_spinlock;
int wakelock_counter;
+ int wakelock_wd_counter;
int wakelock_rx_timeout_enable;
int wakelock_ctrl_timeout_enable;
@@ -345,7 +351,7 @@ typedef struct dhd_info {
#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
struct early_suspend early_suspend;
-#endif /* CONFIG_HAS_EARLYSUSPEND && defined(DHD_USE_EARLYSUSPEND) */
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
#ifdef ARP_OFFLOAD_SUPPORT
u32 pend_ipaddr;
@@ -357,6 +363,9 @@ typedef struct dhd_info {
bool rpcth_timer_active;
bool fdaggr;
#endif
+#ifdef DHDTCPACK_SUPPRESS
+ spinlock_t tcpack_lock;
+#endif /* DHDTCPACK_SUPPRESS */
} dhd_info_t;
/* Flag to indicate if we should download firmware on driver load */
@@ -368,10 +377,6 @@ uint dhd_download_fw_on_driverload = TRUE;
char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
-/* information string to keep firmware, chio, cheip version info visiable from log */
-char info_string[MOD_PARAM_INFOLEN];
-module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
-
int op_mode = 0;
int disable_proptx = 0;
module_param(op_mode, int, 0644);
@@ -391,11 +396,22 @@ module_param(dhd_sysioc, uint, 0);
/* Error bits */
module_param(dhd_msg_level, int, 0);
+#ifdef ARP_OFFLOAD_SUPPORT
+/* ARP offload enable */
+uint dhd_arp_enable = TRUE;
+module_param(dhd_arp_enable, uint, 0);
+#endif /* ARP_OFFLOAD_SUPPORT */
+
+
/* Disable Prop tx */
module_param(disable_proptx, int, 0644);
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
+#ifdef CUSTOMER_HW4
module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660);
+#else
+module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
+#endif /* CUSTOMER_HW4 */
/* Watchdog interval */
uint dhd_watchdog_ms = 10;
@@ -407,16 +423,25 @@ uint dhd_console_ms = 0;
module_param(dhd_console_ms, uint, 0644);
#endif /* defined(DHD_DEBUG) */
+#ifdef REPEAT_READFRAME
+uint dhd_doflow = 1;
+module_param(dhd_doflow, uint, 0644);
+
+uint dhd_dpcpoll = 1;
+module_param(dhd_dpcpoll, uint, 0644);
+#endif /* REPEAT_READFRAME */
+
uint dhd_slpauto = TRUE;
module_param(dhd_slpauto, uint, 0);
/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
+#if defined(CUSTOMER_HW4)
uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY | ARP_OL_SNOOP;
-module_param(dhd_arp_mode, uint, 0);
+#else
+uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY;
+#endif
-/* ARP offload enable */
-uint dhd_arp_enable = TRUE;
-module_param(dhd_arp_enable, uint, 0);
+module_param(dhd_arp_mode, uint, 0);
#ifdef PKT_FILTER_SUPPORT
/* Global Pkt filter enable control */
@@ -444,6 +469,12 @@ module_param(dhd_watchdog_prio, int, 0);
int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING;
module_param(dhd_dpc_prio, int, 0);
+#ifdef RXFRAME_THREAD
+/* RX frame thread priority */
+int dhd_rxf_prio = CUSTOM_RXF_PRIO_SETTING;
+module_param(dhd_rxf_prio, int, 0);
+#endif /* RXFRAME_THREAD */
+
/* DPC thread priority, -1 to use tasklet */
extern int dhd_dongle_memsize;
module_param(dhd_dongle_memsize, int, 0);
@@ -546,10 +577,14 @@ static void dhd_dump_htsfhisto(histo_t *his, char *s);
int dhd_monitor_init(void *dhd_pub);
int dhd_monitor_uninit(void);
-#ifdef CONFIG_CONTROL_PM
+#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM)
bool g_pm_control;
void sec_control_pm(dhd_pub_t *dhd, uint *);
-#endif
+#endif /* CUSTOMER_HW4 & CONFIG_CONTROL_PM */
+
+#if defined(CUSTOMER_HW4) && defined(USE_WL_FRAMEBURST)
+uint32 sec_control_frameburst(void);
+#endif /* CUSTOMER_HW4 & CONFIG_CONTROL_PM */
#if defined(CONFIG_WIRELESS_EXT)
@@ -602,9 +637,77 @@ extern int register_pm_notifier(struct notifier_block *nb);
extern int unregister_pm_notifier(struct notifier_block *nb);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+/* Request scheduling of the bus rx frame */
+static void dhd_sched_rxf(dhd_pub_t *dhdp, void *skb);
+static void dhd_os_rxflock(dhd_pub_t *pub);
+static void dhd_os_rxfunlock(dhd_pub_t *pub);
+
+static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb)
+{
+ uint32 store_idx;
+ uint32 sent_idx;
+
+ if (!skb) {
+ DHD_ERROR(("dhd_rxf_enqueue: NULL skb!!!\n"));
+ return BCME_ERROR;
+ }
+
+ dhd_os_rxflock(dhdp);
+ store_idx = dhdp->store_idx;
+ sent_idx = dhdp->sent_idx;
+ if (dhdp->skbbuf[store_idx] != NULL) {
+ /* Make sure the previous packets are processed */
+ /* Do I need to make this context sleep here? Definitely in Single processor case */
+ dhd_os_rxfunlock(dhdp);
+ DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n",
+ skb, store_idx, sent_idx));
+ msleep(1);
+ return BCME_ERROR;
+ }
+ DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n",
+ skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1)));
+ dhdp->skbbuf[store_idx] = skb;
+ dhdp->store_idx = (store_idx + 1) & (MAXSKBPEND - 1);
+ dhd_os_rxfunlock(dhdp);
+
+ return BCME_OK;
+}
+
+static inline void* dhd_rxf_dequeue(dhd_pub_t *dhdp)
+{
+ uint32 store_idx;
+ uint32 sent_idx;
+ void *skb;
+
+ dhd_os_rxflock(dhdp);
+
+ store_idx = dhdp->store_idx;
+ sent_idx = dhdp->sent_idx;
+ skb = dhdp->skbbuf[sent_idx];
+
+ if (skb == NULL) {
+ dhd_os_rxfunlock(dhdp);
+ DHD_ERROR(("dhd_rxf_dequeue: Dequeued packet is NULL, store idx %d sent idx %d\n",
+ store_idx, sent_idx));
+ return NULL;
+ }
+
+ dhdp->skbbuf[sent_idx] = NULL;
+ dhdp->sent_idx = (sent_idx + 1) & (MAXSKBPEND - 1);
+
+ DHD_TRACE(("dhd_rxf_dequeue: netif_rx_ni(%p), sent idx %d\n",
+ skb, sent_idx));
+
+ dhd_os_rxfunlock(dhdp);
+
+ return skb;
+}
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
+
void dhd_set_packet_filter(dhd_pub_t *dhd)
-#ifdef PKT_FILTER_SUPPORT
{
+#ifdef PKT_FILTER_SUPPORT
int i;
DHD_TRACE(("%s: enter\n", __FUNCTION__));
@@ -613,7 +716,7 @@ void dhd_set_packet_filter(dhd_pub_t *dhd)
dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]);
}
}
-#endif
+#endif /* PKT_FILTER_SUPPORT */
}
void dhd_enable_packet_filter(int value, dhd_pub_t *dhd)
@@ -625,7 +728,8 @@ void dhd_enable_packet_filter(int value, dhd_pub_t *dhd)
/* 1 - Enable packet filter, only allow unicast packet to send up */
/* 0 - Disable packet filter */
if (dhd_pkt_filter_enable && (!value ||
- (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) {
+ (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress)))
+ {
for (i = 0; i < dhd->pktfilter_count; i++) {
#ifdef PASS_ARP_PACKET
if (value && (i == dhd->pktfilter_count -1) &&
@@ -647,120 +751,127 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
{
#ifndef SUPPORT_PM2_ONLY
int power_mode = PM_MAX;
-#endif
+#endif /* SUPPORT_PM2_ONLY */
/* wl_pkt_filter_enable_t enable_parm; */
char iovbuf[32];
-#if !defined(CUSTOMER_HW4)
- int bcn_li_dtim = DTIM_COUNT;
-#endif
-#ifndef DISABLE_FW_ROAM_SUSPEND
+ int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */
+#ifndef ENABLE_FW_ROAM_SUSPEND
uint roamvar = 1;
-#endif
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP)
int bcn_li_bcn;
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-#ifdef PASS_ALL_MCAST_PKTS
+#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */
+#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4)
+ struct dhd_info *dhdinfo = dhd->info;
uint32 allmulti;
-#endif /* PASS_ALL_MCAST_PKTS */
+ uint i;
+#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */
+
+ if (!dhd)
+ return -ENODEV;
DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n",
__FUNCTION__, value, dhd->in_suspend));
dhd_suspend_lock(dhd);
- if (dhd && dhd->up) {
+ if (dhd->up) {
if (value && dhd->in_suspend) {
#ifdef PKT_FILTER_SUPPORT
dhd->early_suspended = 1;
#endif
/* Kernel suspended */
- DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__));
+ DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
#ifndef SUPPORT_PM2_ONLY
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode), TRUE, 0);
-#endif
-#ifdef PKT_FILTER_SUPPORT
+#endif /* SUPPORT_PM2_ONLY */
+
/* Enable packet filter, only allow unicast packet to send up */
- if (!dhd->dhcp_in_progress)
- dhd_enable_packet_filter(1, dhd);
-#endif /* PKT_FILTER_SUPPORT */
-#ifdef PASS_ALL_MCAST_PKTS
+ dhd_enable_packet_filter(1, dhd);
+
+#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4)
allmulti = 0;
- bcm_mkiovar("allmulti", (char *)&allmulti,
- 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* PASS_ALL_MCAST_PKTS */
+ bcm_mkiovar("allmulti", (char *)&allmulti, 4,
+ iovbuf, sizeof(iovbuf));
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net)
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, i);
+ }
+#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */
-#if !defined(CUSTOMER_HW4)
/* If DTIM skip is set up as default, force it to wake
* each third DTIM for better power savings. Note that
* one side effect is a chance to miss BC/MC packet.
*/
- bcn_li_dtim = dhd_get_dtim_skip(dhd);
+ bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd);
bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* !defined(CUSTOMER_HW4) */
-#ifndef DISABLE_FW_ROAM_SUSPEND
+ 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,
iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP)
bcn_li_bcn = 0;
bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn,
4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-
+#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */
} else {
#ifdef PKT_FILTER_SUPPORT
dhd->early_suspended = 0;
#endif
/* Kernel resumed */
- DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__));
+ DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__));
#ifndef SUPPORT_PM2_ONLY
power_mode = PM_FAST;
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode), TRUE, 0);
-#endif
+#endif /* SUPPORT_PM2_ONLY */
#ifdef PKT_FILTER_SUPPORT
/* disable pkt filter */
dhd_enable_packet_filter(0, dhd);
#endif /* PKT_FILTER_SUPPORT */
-#ifdef PASS_ALL_MCAST_PKTS
+#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4)
allmulti = 1;
- bcm_mkiovar("allmulti", (char *)&allmulti,
- 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* PASS_ALL_MCAST_PKTS */
+ bcm_mkiovar("allmulti", (char *)&allmulti, 4,
+ iovbuf, sizeof(iovbuf));
+ for (i = 0; i < DHD_MAX_IFS; i++) {
+ if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net)
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, i);
+ }
+#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */
-#if !defined(CUSTOMER_HW4)
/* restore pre-suspend setting for dtim_skip */
- bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip,
+ bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif
-#ifndef DISABLE_FW_ROAM_SUSPEND
+#ifndef ENABLE_FW_ROAM_SUSPEND
roamvar = dhd_roam_disable;
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf,
sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
+#endif /* ENABLE_FW_ROAM_SUSPEND */
+#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP)
bcn_li_bcn = 1;
bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn,
4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-
+#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */
}
}
-
dhd_suspend_unlock(dhd);
+
return 0;
}
@@ -800,7 +911,7 @@ static void dhd_late_resume(struct early_suspend *h)
if (dhd)
dhd_suspend_resume_helper(dhd, 0, 0);
}
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
/*
* Generalized timeout mechanism. Uses spin sleep with exponential back-off until
@@ -967,33 +1078,37 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
for (i = 0; i < DHD_MAX_IFS; i++) {
if (dhd->iflist[i]) {
dev = dhd->iflist[i]->net;
+ if (!dev)
+ continue;
#else
- ASSERT(dhd && dhd->iflist[ifidx]);
- dev = dhd->iflist[ifidx]->net;
+ ASSERT(dhd && dhd->iflist[ifidx]);
+ dev = dhd->iflist[ifidx]->net;
+ if (!dev)
+ return;
#endif /* MCAST_LIST_ACCUMULATION */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- netif_addr_lock_bh(dev);
+ netif_addr_lock_bh(dev);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
#ifdef MCAST_LIST_ACCUMULATION
cnt_iface[i] = netdev_mc_count(dev);
cnt += cnt_iface[i];
#else
- cnt = netdev_mc_count(dev);
+ cnt = netdev_mc_count(dev);
#endif /* MCAST_LIST_ACCUMULATION */
#else
#ifdef MCAST_LIST_ACCUMULATION
cnt += dev->mc_count;
#else
- cnt = dev->mc_count;
+ cnt = dev->mc_count;
#endif /* MCAST_LIST_ACCUMULATION */
#endif /* LINUX_VERSION_CODE */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- netif_addr_unlock_bh(dev);
+ netif_addr_unlock_bh(dev);
#endif
- /* Determine initial value of allmulti flag */
+ /* Determine initial value of allmulti flag */
#ifdef MCAST_LIST_ACCUMULATION
allmulti |= (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
}
@@ -1001,13 +1116,12 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
#else
allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
#endif /* MCAST_LIST_ACCUMULATION */
-
-#ifdef PASS_ALL_MCAST_PKTS
+#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4)
#ifdef PKT_FILTER_SUPPORT
if (!dhd->pub.early_suspended)
#endif /* PKT_FILTER_SUPPORT */
allmulti = TRUE;
-#endif /* PASS_ALL_MCAST_PKTS */
+#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */
/* Send down the multicast list first. */
@@ -1035,25 +1149,25 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
#endif /* MCAST_LIST_ACCUMULATION */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- netif_addr_lock_bh(dev);
+ netif_addr_lock_bh(dev);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
- netdev_for_each_mc_addr(ha, dev) {
+ netdev_for_each_mc_addr(ha, dev) {
#ifdef MCAST_LIST_ACCUMULATION
if (!cnt_iface[i])
#else
- if (!cnt)
+ if (!cnt)
#endif /* MCAST_LIST_ACCUMULATION */
- break;
- memcpy(bufp, ha->addr, ETHER_ADDR_LEN);
- bufp += ETHER_ADDR_LEN;
+ break;
+ memcpy(bufp, ha->addr, ETHER_ADDR_LEN);
+ bufp += ETHER_ADDR_LEN;
#ifdef MCAST_LIST_ACCUMULATION
DHD_TRACE(("_dhd_set_multicast_list: cnt "
"%d " MACDBG "\n",
cnt_iface[i], MAC2STRDBG(ha->addr)));
cnt_iface[i]--;
#else
- cnt--;
+ cnt--;
#endif /* MCAST_LIST_ACCUMULATION */
}
#else
@@ -1064,13 +1178,13 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
for (mclist = dev->mc_list; (mclist && (cnt > 0));
cnt--, mclist = mclist->next) {
#endif /* MCAST_LIST_ACCUMULATION */
- memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
- bufp += ETHER_ADDR_LEN;
- }
+ memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
+ bufp += ETHER_ADDR_LEN;
+ }
#endif /* LINUX_VERSION_CODE */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
- netif_addr_unlock_bh(dev);
+ netif_addr_unlock_bh(dev);
#endif
#ifdef MCAST_LIST_ACCUMULATION
}
@@ -1224,7 +1338,7 @@ dhd_op_if(dhd_if_t *ifp)
}
/* Allocate etherdev, including space for private structure */
if (!(ifp->net = alloc_etherdev(sizeof(dhd)))) {
- DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__));
+ DHD_ERROR(("%s: OOM - alloc_etherdev(%d)\n", __FUNCTION__, sizeof(dhd)));
ret = -ENOMEM;
}
if (ret == 0) {
@@ -1309,6 +1423,13 @@ dhd_op_if(dhd_if_t *ifp)
}
}
+
+#ifdef DHDTCPACK_SUPPRESS
+uint dhd_use_tcpack_suppress = TRUE;
+module_param(dhd_use_tcpack_suppress, uint, FALSE);
+extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt);
+#endif /* DHDTCPACK_SUPPRESS */
+
static int
_dhd_sysioc_thread(void *data)
{
@@ -1321,6 +1442,7 @@ _dhd_sysioc_thread(void *data)
bool in_ap = FALSE;
unsigned long flags;
#endif
+
#ifndef USE_KTHREAD_API
DAEMONIZE("dhd_sysioc");
@@ -1386,10 +1508,12 @@ _dhd_sysioc_thread(void *data)
dhd->set_macaddress = 0;
if (_dhd_set_mac_address(dhd, i, &dhd->macvalue) == 0) {
DHD_INFO((
- "dhd_sysioc_thread: MACID is overwritten\n"));
+ "%s: MACID is overwritten\n",
+ __FUNCTION__));
} else {
DHD_ERROR((
- "dhd_sysioc_thread: _dhd_set_mac_address() failed\n"));
+ "%s: _dhd_set_mac_address() failed\n",
+ __FUNCTION__));
}
}
}
@@ -1470,7 +1594,7 @@ uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
int
dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
{
- int ret;
+ int ret = BCME_OK;
dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
struct ether_header *eh = NULL;
@@ -1496,7 +1620,9 @@ 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 /* !CUSTOMER_HW4 */
pktsetprio(pktbuf, FALSE);
#ifdef PROP_TXSTATUS
@@ -1522,22 +1648,30 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
#ifdef WLMEDIA_HTSF
dhd_htsf_addtxts(dhdp, pktbuf);
#endif
+#ifdef DHDTCPACK_SUPPRESS
+ if (dhd_use_tcpack_suppress && dhd_tcpack_suppress(dhdp, pktbuf))
+ ret = BCME_OK;
+ else
+#endif /* DHDTCPACK_SUPPRESS */
#ifdef PROP_TXSTATUS
- if (dhdp->wlfc_state && ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode
- != WLFC_FCMODE_NONE) {
+ {
dhd_os_wlfc_block(dhdp);
- ret = dhd_wlfc_enque_sendq(dhdp->wlfc_state, DHD_PKTTAG_FIFO(PKTTAG(pktbuf)),
- pktbuf);
- dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata,
- dhdp->bus);
- if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) {
- ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0;
+ if (dhdp->wlfc_state &&
+ ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode
+ != WLFC_FCMODE_NONE) {
+ dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata,
+ dhdp->bus, pktbuf);
+ if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) {
+ ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0;
+ }
+ dhd_os_wlfc_unblock(dhdp);
+ }
+ else {
+ dhd_os_wlfc_unblock(dhdp);
+ /* non-proptxstatus way */
+ ret = dhd_bus_txdata(dhdp->bus, pktbuf);
}
- dhd_os_wlfc_unblock(dhdp);
}
- else
- /* non-proptxstatus way */
- ret = dhd_bus_txdata(dhdp->bus, pktbuf);
#else
ret = dhd_bus_txdata(dhdp->bus, pktbuf);
#endif /* PROP_TXSTATUS */
@@ -1716,11 +1850,6 @@ static const char *_get_packet_type_str(uint16 type)
}
#endif /* DHD_RX_DUMP */
-#ifdef CUSTOMER_HW4
-extern int pkt_free;
-extern int caller;
-extern void *free_ptr;
-#endif
void
dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
{
@@ -1734,7 +1863,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
wl_event_msg_t event;
int tout_rx = 0;
int tout_ctrl = 0;
-
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+ void *skbhead = NULL;
+ void *skbprev = NULL;
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
#ifdef DHD_RX_DUMP
#ifdef DHD_RX_FULL_DUMP
int k;
@@ -1751,6 +1883,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
struct dot11_llc_snap_header *lsh;
#endif
+ pnext = PKTNEXT(dhdp->osh, pktbuf);
+ PKTSETNEXT(wl->sh.osh, pktbuf, NULL);
+
ifp = dhd->iflist[ifidx];
if (ifp == NULL) {
DHD_ERROR(("%s: ifp is NULL. drop packet\n",
@@ -1772,9 +1907,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
- pnext = PKTNEXT(dhdp->osh, pktbuf);
- PKTSETNEXT(wl->sh.osh, pktbuf, NULL);
-
#ifdef WLBTAMP
eh = (struct ether_header *)PKTDATA(wl->sh.osh, pktbuf);
lsh = (struct dot11_llc_snap_header *)&eh[1];
@@ -1796,16 +1928,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
piggy-back on
*/
((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++;
-#ifdef CUSTOMER_HW4
- /*if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) {
- DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n",
- pkt_free, caller, free_ptr));
- }*/
-#endif
PKTFREE(dhdp->osh, pktbuf, TRUE);
continue;
}
-#endif /* PROP_TXSTATUS */
+#endif
skb = PKTTONATIVE(dhdp->osh, pktbuf);
@@ -1886,29 +2012,33 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) {
dhd_wl_host_event(dhd, &ifidx,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
- skb->mac_header,
+ skb_mac_header(skb),
#else
skb->mac.raw,
#endif
&event,
&data);
+#if defined(WLBTAMP) || defined(PNO_SUPPORT)
wl_event_to_host_order(&event);
-
if (!tout_ctrl)
tout_ctrl = DHD_PACKET_TIMEOUT_MS;
-
#ifdef WLBTAMP
if (event.event_type == WLC_E_BTA_HCI_EVENT) {
dhd_bta_doevt(dhdp, data, event.datalen);
}
#endif /* WLBTAMP */
-#if defined(PNO_SUPPORT)
+#ifdef PNO_SUPPORT
if (event.event_type == WLC_E_PFN_NET_FOUND) {
+#ifdef CUSTOMER_HW4
+ tout_ctrl = DHD_PNO_TIMEOUT_MS;
+#else
tout_ctrl *= 2;
+#endif
}
#endif /* PNO_SUPPORT */
+#endif /* defined(WLBTAMP) || defined(PNO_SUPPORT) */
} else {
tout_rx = DHD_PACKET_TIMEOUT_MS;
}
@@ -1923,6 +2053,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
dhdp->dstats.rx_bytes += skb->len;
dhdp->rx_packets++; /* Local count */
+
if (in_interrupt()) {
netif_rx(skb);
} else {
@@ -1932,6 +2063,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
* by netif_rx_ni(), but in earlier kernels, we need
* to do it manually.
*/
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+ if (!skbhead)
+ skbhead = skb;
+ else
+ PKTSETNEXT(wl->sh.osh, skbprev, skb);
+ skbprev = skb;
+#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
netif_rx_ni(skb);
#else
@@ -1941,9 +2079,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
RAISE_RX_SOFTIRQ();
local_irq_restore(flags);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
}
}
-
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+ if (skbhead)
+ dhd_sched_rxf(dhdp, skbhead);
+#endif
DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx);
DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl);
}
@@ -1958,7 +2100,6 @@ dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx)
void
dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
{
- uint ifidx;
dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
struct ether_header *eh;
uint16 type;
@@ -1966,7 +2107,7 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
uint len;
#endif
- dhd_prot_hdrpull(dhdp, &ifidx, txp, NULL, NULL);
+ dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL);
eh = (struct ether_header *)PKTDATA(dhdp->osh, txp);
type = ntoh16(eh->ether_type);
@@ -2055,6 +2196,8 @@ dhd_watchdog_thread(void *data)
while (1)
if (down_interruptible (&tsk->sema) == 0) {
unsigned long flags;
+ unsigned long jiffies_at_start = jiffies;
+ unsigned long time_lapse;
SMP_RD_BARRIER_DEPENDS();
if (tsk->terminated) {
@@ -2065,20 +2208,24 @@ dhd_watchdog_thread(void *data)
if (dhd->pub.dongle_reset == FALSE) {
DHD_TIMER(("%s:\n", __FUNCTION__));
+
/* Call the bus module watchdog */
dhd_bus_watchdog(&dhd->pub);
flags = dhd_os_spin_lock(&dhd->pub);
/* Count the tick for reference */
dhd->pub.tickcnt++;
+ time_lapse = jiffies - jiffies_at_start;
+
/* Reschedule the watchdog */
if (dhd->wd_timer_valid)
mod_timer(&dhd->timer,
- jiffies + msecs_to_jiffies(dhd_watchdog_ms));
+ jiffies +
+ msecs_to_jiffies(dhd_watchdog_ms) -
+ min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse));
dhd_os_spin_unlock(&dhd->pub, flags);
}
dhd_os_sdunlock(&dhd->pub);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
} else {
break;
}
@@ -2092,9 +2239,7 @@ static void dhd_watchdog(ulong data)
dhd_info_t *dhd = (dhd_info_t *)data;
unsigned long flags;
- DHD_OS_WAKE_LOCK(&dhd->pub);
if (dhd->pub.dongle_reset) {
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
return;
}
@@ -2118,7 +2263,6 @@ static void dhd_watchdog(ulong data)
mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
dhd_os_spin_unlock(&dhd->pub, flags);
dhd_os_sdunlock(&dhd->pub);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
}
#ifdef DHDTHREAD
@@ -2145,10 +2289,13 @@ dhd_dpc_thread(void *data)
complete(&tsk->completed);
#endif
+#ifdef CUSTOM_DPC_CPUCORE
+ set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE));
+#endif
+
/* Run until signal received */
while (1) {
if (down_interruptible(&tsk->sema) == 0) {
-
SMP_RD_BARRIER_DEPENDS();
if (tsk->terminated) {
break;
@@ -2174,6 +2321,75 @@ dhd_dpc_thread(void *data)
complete_and_exit(&tsk->completed, 0);
}
+
+#ifdef RXFRAME_THREAD
+static int
+dhd_rxf_thread(void *data)
+{
+ tsk_ctl_t *tsk = (tsk_ctl_t *)data;
+ dhd_info_t *dhd = (dhd_info_t *)tsk->parent;
+ dhd_pub_t *pub = &dhd->pub;
+
+ /* This thread doesn't need any user-level access,
+ * so get rid of all our resources
+ */
+ if (dhd_rxf_prio > 0)
+ {
+ struct sched_param param;
+ param.sched_priority = (dhd_rxf_prio < MAX_RT_PRIO)?dhd_rxf_prio:(MAX_RT_PRIO-1);
+ setScheduler(current, SCHED_FIFO, &param);
+ }
+
+ DAEMONIZE("dhd_rxf");
+ /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */
+
+ /* signal: thread has started */
+ complete(&tsk->completed);
+
+ /* Run until signal received */
+ while (1) {
+ if (down_interruptible(&tsk->sema) == 0) {
+ void *skb;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
+ ulong flags;
+#endif
+
+ SMP_RD_BARRIER_DEPENDS();
+
+ if (tsk->terminated) {
+ break;
+ }
+ skb = dhd_rxf_dequeue(pub);
+
+ if (skb == NULL) {
+ continue;
+ }
+
+ while (skb) {
+ void *skbnext = PKTNEXT(pub->osh, skb);
+ PKTSETNEXT(pub->osh, skb, NULL);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+ netif_rx_ni(skb);
+#else
+ netif_rx(skb);
+ local_irq_save(flags);
+ RAISE_RX_SOFTIRQ();
+ local_irq_restore(flags);
+
+#endif
+ skb = skbnext;
+ }
+
+ DHD_OS_WAKE_UNLOCK(pub);
+ }
+ else
+ break;
+ }
+
+ complete_and_exit(&tsk->completed, 0);
+}
+#endif /* RXFRAME_THREAD */
#endif /* DHDTHREAD */
static void
@@ -2216,6 +2432,27 @@ dhd_sched_dpc(dhd_pub_t *dhdp)
tasklet_schedule(&dhd->tasklet);
}
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+static void
+dhd_sched_rxf(dhd_pub_t *dhdp, void *skb)
+{
+ dhd_info_t *dhd = (dhd_info_t *)dhdp->info;
+
+ DHD_OS_WAKE_LOCK(dhdp);
+
+ DHD_TRACE(("dhd_sched_rxf: Enter\n"));
+
+ do {
+ if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK)
+ break;
+ } while (1);
+ if (dhd->thr_rxf_ctl.thr_pid >= 0) {
+ up(&dhd->thr_rxf_ctl.sema);
+ }
+ return;
+}
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
+
#ifdef TOE
/* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */
static int
@@ -2423,7 +2660,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
{
- dhd_info_t * dhd;
+ dhd_info_t *dhd;
if (!dhdp)
return FALSE;
@@ -2444,128 +2681,60 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
return FALSE;
}
-static int
-dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc)
{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
- dhd_ioctl_t ioc;
- int bcmerror = 0;
+ int bcmerror = BCME_OK;
int buflen = 0;
void *buf = NULL;
- uint driver = 0;
- int ifidx;
- int ret;
-
- DHD_OS_WAKE_LOCK(&dhd->pub);
-
- /* send to dongle only if we are not waiting for reload already */
- if (dhd->pub.hang_was_sent) {
- DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__));
- DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return OSL_ERROR(BCME_DONGLE_DOWN);
- }
-
- ifidx = dhd_net2idx(dhd, net);
- DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
-
- if (ifidx == DHD_BAD_IF) {
- DHD_ERROR(("%s: BAD IF\n", __FUNCTION__));
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return -1;
- }
-
-#if defined(CONFIG_WIRELESS_EXT)
- /* linux wireless extensions */
- if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
- /* may recurse, do NOT lock */
- ret = wl_iw_ioctl(net, ifr, cmd);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return ret;
- }
-#endif /* defined(CONFIG_WIRELESS_EXT) */
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
- if (cmd == SIOCETHTOOL) {
- ret = dhd_ethtool(dhd, (void*)ifr->ifr_data);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return ret;
- }
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
-
- if (cmd == SIOCDEVPRIVATE+1) {
- ret = wl_android_priv_cmd(net, ifr, cmd);
- dhd_check_hang(net, &dhd->pub, ret);
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return ret;
- }
-
- if (cmd != SIOCDEVPRIVATE) {
- DHD_OS_WAKE_UNLOCK(&dhd->pub);
- return -EOPNOTSUPP;
- }
-
- memset(&ioc, 0, sizeof(ioc));
+ struct net_device *net;
- /* Copy the ioc control structure part of ioctl request */
- if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
- bcmerror = BCME_BADADDR;
+ net = dhd_idx2net(pub, ifidx);
+ if (!net) {
+ bcmerror = BCME_BADARG;
goto done;
}
/* Copy out any buffer passed */
- if (ioc.buf) {
- if (ioc.len == 0) {
- DHD_TRACE(("%s: ioc.len=0, returns BCME_BADARG \n", __FUNCTION__));
+ if (ioc->buf) {
+ if (ioc->len == 0) {
+ DHD_TRACE(("%s: ioc->len=0, returns BCME_BADARG \n", __FUNCTION__));
bcmerror = BCME_BADARG;
goto done;
}
- buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN);
+ buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN);
/* optimization for direct ioctl calls from kernel */
/*
if (segment_eq(get_fs(), KERNEL_DS)) {
- buf = ioc.buf;
+ buf = ioc->buf;
} else {
*/
{
- if (!(buf = (char*)MALLOC(dhd->pub.osh, buflen))) {
+ if (!(buf = (char*)MALLOC(pub->osh, buflen))) {
bcmerror = BCME_NOMEM;
goto done;
}
- if (copy_from_user(buf, ioc.buf, buflen)) {
+ if (copy_from_user(buf, ioc->buf, buflen)) {
bcmerror = BCME_BADADDR;
goto done;
}
}
}
- /* To differentiate between wl and dhd read 4 more byes */
- if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
- sizeof(uint)) != 0)) {
- bcmerror = BCME_BADADDR;
- goto done;
- }
-
- if (!capable(CAP_NET_ADMIN)) {
- bcmerror = BCME_EPERM;
- goto done;
- }
-
/* check for local dhd ioctl and handle it */
- if (driver == DHD_IOCTL_MAGIC) {
- bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen);
+ if (ioc->driver == DHD_IOCTL_MAGIC) {
+ bcmerror = dhd_ioctl((void *)pub, ioc, buf, buflen);
if (bcmerror)
- dhd->pub.bcmerror = bcmerror;
+ pub->bcmerror = bcmerror;
goto done;
}
/* send to dongle (must be up, and wl). */
- if (dhd->pub.busstate != DHD_BUS_DATA) {
+ if (pub->busstate != DHD_BUS_DATA) {
bcmerror = BCME_DONGLE_DOWN;
goto done;
}
- if (!dhd->pub.iswl) {
+ if (!pub->iswl) {
bcmerror = BCME_DONGLE_DOWN;
goto done;
}
@@ -2577,24 +2746,24 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
* intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to
* prevent disassoc frame being sent before WPS-DONE frame.
*/
- if (ioc.cmd == WLC_SET_KEY ||
- (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL &&
- strncmp("wsec_key", ioc.buf, 9) == 0) ||
- (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL &&
- strncmp("bsscfg:wsec_key", ioc.buf, 15) == 0) ||
- ioc.cmd == WLC_DISASSOC)
+ if (ioc->cmd == WLC_SET_KEY ||
+ (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL &&
+ strncmp("wsec_key", ioc->buf, 9) == 0) ||
+ (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL &&
+ strncmp("bsscfg:wsec_key", ioc->buf, 15) == 0) ||
+ ioc->cmd == WLC_DISASSOC)
dhd_wait_pend8021x(net);
#ifdef WLMEDIA_HTSF
- if (ioc.buf) {
+ if (ioc->buf) {
/* short cut wl ioctl calls here */
- if (strcmp("htsf", ioc.buf) == 0) {
+ if (strcmp("htsf", ioc->buf) == 0) {
dhd_ioctl_htsf_get(dhd, 0);
return BCME_OK;
}
- if (strcmp("htsflate", ioc.buf) == 0) {
- if (ioc.set) {
+ if (strcmp("htsflate", ioc->buf) == 0) {
+ if (ioc->set) {
memset(ts, 0, sizeof(tstamp_t)*TSMAX);
memset(&maxdelayts, 0, sizeof(tstamp_t));
maxdelay = 0;
@@ -2609,7 +2778,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
}
return BCME_OK;
}
- if (strcmp("htsfclear", ioc.buf) == 0) {
+ if (strcmp("htsfclear", ioc->buf) == 0) {
memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN);
memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN);
memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN);
@@ -2617,16 +2786,16 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
htsf_seqnum = 0;
return BCME_OK;
}
- if (strcmp("htsfhis", ioc.buf) == 0) {
+ if (strcmp("htsfhis", ioc->buf) == 0) {
dhd_dump_htsfhisto(&vi_d1, "H to D");
dhd_dump_htsfhisto(&vi_d2, "D to D");
dhd_dump_htsfhisto(&vi_d3, "D to H");
dhd_dump_htsfhisto(&vi_d4, "H to H");
return BCME_OK;
}
- if (strcmp("tsport", ioc.buf) == 0) {
- if (ioc.set) {
- memcpy(&tsport, ioc.buf + 7, 4);
+ if (strcmp("tsport", ioc->buf) == 0) {
+ if (ioc->set) {
+ memcpy(&tsport, ioc->buf + 7, 4);
} else {
DHD_ERROR(("current timestamp port: %d \n", tsport));
}
@@ -2635,52 +2804,182 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
}
#endif /* WLMEDIA_HTSF */
- if ((ioc.cmd == WLC_SET_VAR || ioc.cmd == WLC_GET_VAR) &&
- ioc.buf != NULL && strncmp("rpc_", ioc.buf, 4) == 0) {
+ if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) &&
+ ioc->buf != NULL && strncmp("rpc_", ioc->buf, 4) == 0) {
#ifdef BCM_FD_AGGR
- bcmerror = dhd_fdaggr_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+ bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen);
#else
bcmerror = BCME_UNSUPPORTED;
#endif
goto done;
}
- bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
+ bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen);
done:
- dhd_check_hang(net, &dhd->pub, bcmerror);
+ dhd_check_hang(net, pub, bcmerror);
- if (!bcmerror && buf && ioc.buf) {
- if (copy_to_user(ioc.buf, buf, buflen))
+ if (!bcmerror && buf && ioc->buf) {
+ if (copy_to_user(ioc->buf, buf, buflen))
bcmerror = -EFAULT;
}
if (buf)
- MFREE(dhd->pub.osh, buf, buflen);
+ MFREE(pub->osh, buf, buflen);
+ return bcmerror;
+}
+
+static int
+dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net);
+ dhd_ioctl_t ioc;
+ int bcmerror = 0;
+ int ifidx;
+ int ret;
+
+ DHD_OS_WAKE_LOCK(&dhd->pub);
+
+ /* send to dongle only if we are not waiting for reload already */
+ if (dhd->pub.hang_was_sent) {
+ DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__));
+ DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return OSL_ERROR(BCME_DONGLE_DOWN);
+ }
+
+ ifidx = dhd_net2idx(dhd, net);
+ DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd));
+
+ if (ifidx == DHD_BAD_IF) {
+ DHD_ERROR(("%s: BAD IF\n", __FUNCTION__));
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return -1;
+ }
+
+#if defined(CONFIG_WIRELESS_EXT)
+ /* linux wireless extensions */
+ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) {
+ /* may recurse, do NOT lock */
+ ret = wl_iw_ioctl(net, ifr, cmd);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+#endif /* defined(CONFIG_WIRELESS_EXT) */
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2)
+ if (cmd == SIOCETHTOOL) {
+ ret = dhd_ethtool(dhd, (void*)ifr->ifr_data);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
+
+ if (cmd == SIOCDEVPRIVATE+1) {
+ ret = wl_android_priv_cmd(net, ifr, cmd);
+ dhd_check_hang(net, &dhd->pub, ret);
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return ret;
+ }
+
+ if (cmd != SIOCDEVPRIVATE) {
+ DHD_OS_WAKE_UNLOCK(&dhd->pub);
+ return -EOPNOTSUPP;
+ }
+
+ memset(&ioc, 0, sizeof(ioc));
+
+ /* Copy the ioc control structure part of ioctl request */
+ if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+
+ /* To differentiate between wl and dhd read 4 more byes */
+ if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t),
+ sizeof(uint)) != 0)) {
+ bcmerror = BCME_BADADDR;
+ goto done;
+ }
+
+ if (!capable(CAP_NET_ADMIN)) {
+ bcmerror = BCME_EPERM;
+ goto done;
+ }
+
+ bcmerror = dhd_ioctl_process(&dhd->pub, ifidx, &ioc);
+
+done:
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return OSL_ERROR(bcmerror);
}
#ifdef WL_CFG80211
+static void
+dhd_delete_virt_iface(dhd_if_t *ifp)
+{
+ dhd_info_t *dhd;
+#ifdef SOFTAP
+ unsigned long flags;
+#endif
+
+ if (!ifp || !ifp->info || !ifp->idx)
+ return;
+ ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */
+ dhd = ifp->info;
+
+ DHD_TRACE(("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state));
+
+ if (wl_cfg80211_is_progress_ifchange())
+ return;
+
+ /* Make sure that we don't enter again here if .. */
+ /* dhd_op_if is called again from some other context */
+ ifp->state = DHD_IF_DELETING;
+ if (ifp->net != NULL) {
+ DHD_ERROR(("\n%s: got 'DHD_IF_DEL' state\n", __FUNCTION__));
+
+ ASSERT_RTNL();
+
+ netif_stop_queue(ifp->net);
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+ wl_cfg80211_ifdel_ops(ifp->net);
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
+ if (rtnl_is_locked())
+ unregister_netdevice_queue(ifp->net, NULL);
+ else
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) */
+ unregister_netdev(ifp->net);
+
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+ wl_cfg80211_notify_ifdel();
+ }
+
+ free_netdev(ifp->net);
+ ifp->net = NULL;
+ }
+
+ ifp->set_multicast = FALSE;
+ dhd->iflist[ifp->idx] = NULL;
+#ifdef SOFTAP
+ flags = dhd_os_spin_lock(&dhd->pub);
+ if (ifp->net == ap_net_dev)
+ ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */
+ dhd_os_spin_unlock(&dhd->pub, flags);
+#endif /* SOFTAP */
+ MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
+}
+
static int
dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
{
int i = 1; /* Leave ifidx 0 [Primary Interface] */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- int rollback_lock = FALSE;
-#endif
DHD_TRACE(("%s: Enter \n", __func__));
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- /* release lock for unregister_netdev */
- if (rtnl_is_locked()) {
- rtnl_unlock();
- rollback_lock = TRUE;
- }
-#endif
-
for (i = 1; i < DHD_MAX_IFS; i++) {
dhd_net_if_lock_local(dhd);
if (dhd->iflist[i]) {
@@ -2689,17 +2988,12 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
(dhd->iflist[i]->state != DHD_IF_DELETING)) {
dhd->iflist[i]->state = DHD_IF_DEL;
dhd->iflist[i]->idx = i;
- dhd_op_if(dhd->iflist[i]);
+ dhd_delete_virt_iface(dhd->iflist[i]);
}
}
dhd_net_if_unlock_local(dhd);
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- if (rollback_lock)
- rtnl_lock();
-#endif
-
return 0;
}
#endif /* WL_CFG80211 */
@@ -2708,8 +3002,8 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd)
/* Flags to indicate if we distingish power off policy when
* user set the memu "Keep Wi-Fi on during sleep" to "Never"
*/
-int sleep_never = 0;
-#endif
+int trigger_deep_sleep = 0;
+#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */
static int
dhd_stop(struct net_device *net)
@@ -2744,33 +3038,28 @@ dhd_stop(struct net_device *net)
#endif
#ifdef PROP_TXSTATUS
- dhd_os_wlfc_block(&dhd->pub);
- dhd_wlfc_cleanup(&dhd->pub);
- dhd_os_wlfc_unblock(&dhd->pub);
+ dhd_wlfc_cleanup(&dhd->pub, NULL, 0);
#endif
-
/* Stop the protocol module */
dhd_prot_stop(&dhd->pub);
OLD_MOD_DEC_USE_COUNT;
exit:
#if defined(WL_CFG80211)
- if (ifidx == 0) {
- if (!dhd_download_fw_on_driverload)
- wl_android_wifi_off(net);
+ if (ifidx == 0 && !dhd_download_fw_on_driverload)
+ wl_android_wifi_off(net);
#ifdef SUPPORT_DEEP_SLEEP
- else {
- /* CSP#505233: Flags to indicate if we distingish
- * power off policy when user set the memu
- * "Keep Wi-Fi on during sleep" to "Never"
- */
- if (sleep_never) {
- dhd_deepsleep(net, 1);
- sleep_never = 0;
- }
+ else {
+ /* CSP#505233: Flags to indicate if we distingish
+ * power off policy when user set the memu
+ * "Keep Wi-Fi on during sleep" to "Never"
+ */
+ if (trigger_deep_sleep) {
+ dhd_deepsleep(net, 1);
+ trigger_deep_sleep = 0;
}
-#endif /* SUPPORT_DEEP_SLEEP */
}
+#endif /* SUPPORT_DEEP_SLEEP */
#endif
dhd->pub.rxcnt_timeout = 0;
dhd->pub.txcnt_timeout = 0;
@@ -2789,31 +3078,49 @@ dhd_open(struct net_device *net)
int ifidx;
int32 ret = 0;
+ /* WAR : to prevent calling dhd_open abnormally in quick succession after hang event */
+ if (dhd->pub.hang_was_sent == 1) {
+ DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__));
+ return -1;
+ }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1
+ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
+ DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__));
+ }
+ mutex_lock(&_dhd_sdio_mutex_lock_);
+#endif
+
DHD_OS_WAKE_LOCK(&dhd->pub);
- DHD_ERROR(("%s: Enter, net[%p]\n", __FUNCTION__, net));
/* Update FW path if it was changed */
if (strlen(firmware_path) != 0) {
if (firmware_path[strlen(firmware_path)-1] == '\n')
firmware_path[strlen(firmware_path)-1] = '\0';
+ bzero(fw_path, MOD_PARAM_PATHLEN);
strncpy(fw_path, firmware_path, sizeof(fw_path)-1);
- fw_path[sizeof(fw_path)-1] = '\0';
-#if defined(SUPPORT_MULTIPLE_REVISION)
- ret = concate_revision(dhd->pub.bus, fw_path, MOD_PARAM_PATHLEN);
- if (ret != 0) {
- DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__));
- goto exit;
- }
-#endif
firmware_path[0] = '\0';
}
+#ifdef CUSTOMER_HW4
/* Update NVRAM path if it was changed */
if (!dhd_download_fw_on_driverload && (strlen(nvram_path) != 0)) {
if (nvram_path[strlen(nvram_path)-1] == '\n')
nvram_path[strlen(nvram_path)-1] = '\0';
- strcpy(nv_path, nvram_path);
- nvram_path[0] = '\0';
+ bzero(nv_path, MOD_PARAM_PATHLEN);
+ strncpy(nv_path, nvram_path, sizeof(nv_path)-1);
+ }
+#endif /* CUSTOMER_HW4 */
+
+#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION)
+ /* dhd_open() can be call several times when loading failed */
+ if (strlen(firmware_path) != 0) {
+ ret = concate_revision(dhd->pub.bus, fw_path, MOD_PARAM_PATHLEN,
+ nv_path, MOD_PARAM_PATHLEN);
+ if (ret != 0) {
+ DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__));
+ goto exit;
+ }
}
+#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */
dhd->pub.dongle_trap_occured = 0;
dhd->pub.hang_was_sent = 0;
@@ -2854,52 +3161,34 @@ dhd_open(struct net_device *net)
if (!dhd_download_fw_on_driverload) {
ret = wl_android_wifi_on(net);
if (ret != 0) {
- DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n",
+ __FUNCTION__, ret));
ret = -1;
goto exit;
}
- } else {
+ }
#ifdef SUPPORT_DEEP_SLEEP
+ else {
/* Flags to indicate if we distingish
* power off policy when user set the memu
* "Keep Wi-Fi on during sleep" to "Never"
*/
- if (sleep_never) {
+ if (trigger_deep_sleep) {
dhd_deepsleep(net, 0);
- sleep_never = 0;
+ trigger_deep_sleep = 0;
}
-#endif /* SUPPORT_DEEP_SLEEP */
}
+#endif /* SUPPORT_DEEP_SLEEP */
#endif
if (dhd->pub.busstate != DHD_BUS_DATA) {
-#if defined(CUSTOMER_HW4)
-#define WAIT_DHDBUS_READY 5
- /* Delay ifup until insmod completed in case of module type */
- if (dhd_download_fw_on_driverload) {
- uint retry = 0;
-
- do {
- OSL_DELAY(100*1000);
- } while ((dhd->pub.busstate != DHD_BUS_DATA) &&
- (retry++ < WAIT_DHDBUS_READY));
-
- if (dhd->pub.busstate != DHD_BUS_DATA) {
- DHD_ERROR(("%s: call dev open before insmod complete!\n",
- __FUNCTION__));
- ret = -1;
- goto exit;
- }
+ /* try to bring up bus */
+ if ((ret = dhd_bus_start(&dhd->pub)) != 0) {
+ DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+ ret = -1;
+ goto exit;
}
- else
-#endif /* CUSTOMER_HW4 */
- /* try to bring up bus */
- if ((ret = dhd_bus_start(&dhd->pub)) != 0) {
- DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
- ret = -1;
- goto exit;
- }
}
@@ -2937,6 +3226,11 @@ exit:
dhd_stop(net);
DHD_OS_WAKE_UNLOCK(&dhd->pub);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1
+ mutex_unlock(&_dhd_sdio_mutex_lock_);
+#endif
+
return ret;
}
@@ -2949,6 +3243,15 @@ int dhd_do_driver_init(struct net_device *net)
return -EINVAL;
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1
+#ifdef MULTIPLE_SUPPLICANT
+ if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
+ DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__));
+ return 0;
+ }
+#endif
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
+ /* && defined(OEM_ANDROID) && defined(BCMSDIO) */
dhd = *(dhd_info_t **)netdev_priv(net);
/* If driver is already initialized, do nothing
@@ -2957,7 +3260,7 @@ int dhd_do_driver_init(struct net_device *net)
DHD_TRACE(("Driver already Inititalized. Nothing to do"));
return 0;
}
- DHD_ERROR(("%s: call dhd_open\n", __FUNCTION__));
+
if (dhd_open(net) < 0) {
DHD_ERROR(("Driver Init Failed \n"));
return -1;
@@ -3007,7 +3310,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
}
} else
if ((ifp = MALLOC(dhd->pub.osh, sizeof(dhd_if_t))) == NULL) {
- DHD_ERROR(("%s: OOM - dhd_if_t\n", __FUNCTION__));
+ DHD_ERROR(("%s: OOM - dhd_if_t(%d)\n", __FUNCTION__, sizeof(dhd_if_t)));
return -ENOMEM;
}
@@ -3095,20 +3398,21 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
/* updates firmware nvram path if it was provided as module parameters */
if (strlen(firmware_path) != 0) {
+ bzero(fw_path, MOD_PARAM_PATHLEN);
strncpy(fw_path, firmware_path, sizeof(fw_path) - 1);
- fw_path[sizeof(fw_path) - 1] = '\0';
}
if (strlen(nvram_path) != 0) {
+ bzero(nv_path, MOD_PARAM_PATHLEN);
strncpy(nv_path, nvram_path, sizeof(nv_path) -1);
- nv_path[sizeof(nv_path) -1] = '\0';
}
-#if defined(SUPPORT_MULTIPLE_REVISION)
+#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION)
if (strlen(fw_path) != 0 &&
- concate_revision(bus, fw_path, MOD_PARAM_PATHLEN) != 0) {
+ concate_revision(bus, fw_path, MOD_PARAM_PATHLEN,
+ nv_path, MOD_PARAM_PATHLEN) != 0) {
DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__));
goto fail;
}
-#endif
+#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */
/* Allocate etherdev, including space for private structure */
if (!(net = alloc_etherdev(sizeof(dhd)))) {
@@ -3118,10 +3422,18 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd_state |= DHD_ATTACH_STATE_NET_ALLOC;
/* Allocate primary dhd_info */
- if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) {
- DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
- goto fail;
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ dhd = (void *)dhd_os_prealloc(osh, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t));
+ if (!dhd) {
+ DHD_INFO(("%s: OOM - Pre-alloc dhd_info\n", __FUNCTION__));
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+ if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) {
+ DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__));
+ goto fail;
+ }
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
}
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
memset(dhd, 0, sizeof(dhd_info_t));
#ifdef DHDTHREAD
@@ -3185,20 +3497,33 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
spin_lock_init(&dhd->sdlock);
spin_lock_init(&dhd->txqlock);
spin_lock_init(&dhd->dhd_lock);
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+ spin_lock_init(&dhd->rxf_lock);
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
+#ifdef DHDTCPACK_SUPPRESS
+ spin_lock_init(&dhd->tcpack_lock);
+#endif /* DHDTCPACK_SUPPRESS */
/* Initialize Wakelock stuff */
spin_lock_init(&dhd->wakelock_spinlock);
dhd->wakelock_counter = 0;
+ dhd->wakelock_wd_counter = 0;
dhd->wakelock_rx_timeout_enable = 0;
dhd->wakelock_ctrl_timeout_enable = 0;
#ifdef CONFIG_HAS_WAKELOCK
- wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
- wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
- wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
-#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT)
- wake_lock_init(&dhd->pub.pno_wakelock, WAKE_LOCK_SUSPEND, "pno_wake_lock");
-#endif
-#endif
+ dhd->wl_wifi = MALLOC(osh, sizeof(struct wake_lock));
+ dhd->wl_rxwake = MALLOC(osh, sizeof(struct wake_lock));
+ dhd->wl_ctrlwake = MALLOC(osh, sizeof(struct wake_lock));
+ dhd->wl_wdwake = MALLOC(osh, sizeof(struct wake_lock));
+ if (!dhd->wl_wifi || !dhd->wl_rxwake || !dhd->wl_ctrlwake || !dhd->wl_wdwake) {
+ DHD_ERROR(("%s: mem alloc for wake lock failed\n", __FUNCTION__));
+ goto fail;
+ }
+ wake_lock_init(dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
+ wake_lock_init(dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
+ wake_lock_init(dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
+ wake_lock_init(dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake");
+#endif /* CONFIG_HAS_WAKELOCK */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
mutex_init(&dhd->dhd_net_if_mutex);
mutex_init(&dhd->dhd_suspend_mutex);
@@ -3249,13 +3574,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd->threads_only = FALSE;
}
- if (dhd_dpc_prio >= 0) {
+ if (dhd_watchdog_prio >= 0) {
/* Initialize watchdog thread */
-#ifdef USE_KTHREAD_API
- PROC_START2(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread");
-#else
- PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0);
-#endif
+ PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread");
+
} else {
dhd->thr_wdt_ctl.thr_pid = -1;
}
@@ -3263,16 +3585,17 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
/* Set up the bottom half handler */
if (dhd_dpc_prio >= 0) {
/* Initialize DPC thread */
-#ifdef USE_KTHREAD_API
- PROC_START2(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc");
-#else
- PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0);
-#endif
+ PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc");
} else {
/* use tasklet for dpc */
tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd);
dhd->thr_dpc_ctl.thr_pid = -1;
}
+#ifdef RXFRAME_THREAD
+ bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND);
+ /* Initialize RXF thread */
+ PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf");
+#endif
#else
/* Set up the bottom half handler */
tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd);
@@ -3280,18 +3603,16 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#endif /* DHDTHREAD */
if (dhd_sysioc) {
-#ifdef USE_KTHREAD_API
- PROC_START2(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc");
-#else
- PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0);
-#endif
+ PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc");
} else {
dhd->thr_sysioc_ctl.thr_pid = -1;
}
dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1)
INIT_WORK(&dhd->work_hang, dhd_hang_process);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
+
/*
* Save the dhd_info into the priv
*/
@@ -3307,13 +3628,18 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd->early_suspend.resume = dhd_late_resume;
register_early_suspend(&dhd->early_suspend);
dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE;
-#endif
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
#ifdef ARP_OFFLOAD_SUPPORT
dhd->pend_ipaddr = 0;
register_inetaddr_notifier(&dhd_notifier);
#endif /* ARP_OFFLOAD_SUPPORT */
+#ifdef DHDTCPACK_SUPPRESS
+ dhd->pub.tcp_ack_info_cnt = 0;
+ bzero(dhd->pub.tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS);
+#endif /* DHDTCPACK_SUPPRESS */
+
dhd_state |= DHD_ATTACH_STATE_DONE;
dhd->dhd_state = dhd_state;
return &dhd->pub;
@@ -3351,13 +3677,31 @@ dhd_bus_start(dhd_pub_t *dhdp)
/* try to download image and nvram to the dongle */
if ((dhd->pub.busstate == DHD_BUS_DOWN) &&
- (fw_path != NULL) && (fw_path[0] != '\0') &&
- (nv_path != NULL) && (nv_path[0] != '\0')) {
+ (fw_path[0] != '\0') &&
+ (nv_path[0] != '\0')) {
+#ifdef SHOW_NVRAM_TYPE
+ { /* Show nvram type in the kernel log */
+ int i;
+ for (i = 0; nv_path[i] != '\0'; ++i) {
+ if (nv_path[i] == '.') {
+ ++i;
+ break;
+ }
+ }
+ DHD_ERROR(("%s: nvram_type = [%s]\n", __FUNCTION__, &nv_path[i]));
+ }
+#endif /* SHOW_NVRAM_TYPE */
/* wake lock moved to dhdsdio_download_firmware */
if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
- fw_path, nv_path))) {
- DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware or nvram path is wrong\n",
- __FUNCTION__));
+ fw_path, nv_path))) {
+#ifdef CUSTOMER_HW4
+ DHD_ERROR(("%s: dhdsdio_probe_download failed. "
+ "firmware or nvram wrong\n",
+ __FUNCTION__));
+#else
+ DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
+ __FUNCTION__, fw_path, nv_path));
+#endif /* CUSTOMER_HW4 */
#ifdef DHDTHREAD
if (dhd->threads_only)
dhd_os_sdunlock(dhdp);
@@ -3402,6 +3746,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
if (dhd->threads_only)
dhd_os_sdunlock(dhdp);
#endif /* DHDTHREAD */
+ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
return -ENODEV;
}
@@ -3422,6 +3767,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
if (dhd->threads_only)
dhd_os_sdunlock(dhdp);
#endif /* DHDTHREAD */
+ DHD_OS_WD_WAKE_UNLOCK(&dhd->pub);
return -ENODEV;
}
@@ -3478,7 +3824,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
#ifdef ARP_OFFLOAD_SUPPORT
if (dhd->pend_ipaddr) {
#ifdef AOE_IP_ALIAS_SUPPORT
- aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE);
+ aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE, 0);
#endif /* AOE_IP_ALIAS_SUPPORT */
dhd->pend_ipaddr = 0;
}
@@ -3500,7 +3846,6 @@ bool dhd_is_concurrent_mode(dhd_pub_t *dhd)
else
return FALSE;
}
-
#if !defined(AP) && defined(WLP2P)
/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware
* name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA
@@ -3550,7 +3895,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd)
ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE;
if (mchan_supported)
ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE;
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_ENABLE_P2P_IF) || defined(CUSTOMER_HW4)
/* For customer_hw4, although ICS,
* we still support concurrent mode
*/
@@ -3570,26 +3915,35 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
int ret = 0;
char eventmask[WL_EVENTING_MASK_LEN];
char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */
-
-#if !defined(WL_CFG80211)
- uint up = 0;
-#endif /* !defined(WL_CFG80211) */
+ uint32 buf_key_b4_m4 = 1;
+#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
+ uint32 sup_wpa = 0;
+#endif
+#ifdef CUSTOM_AMPDU_BA_WSIZE
+ uint32 ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE;
+#endif /* CUSTOM_AMPDU_BA_WSIZE */
+ uint32 lpc = 1;
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
uint32 glom = CUSTOM_GLOM_SETTING;
-#if defined(VSDB) || defined(ROAM_ENABLE)
+#if (defined(CUSTOMER_HW4) || defined(BOARD_PANDA)) && (defined(VSDB) || \
+ defined(ROAM_ENABLE))
uint bcn_timeout = 8;
#else
uint bcn_timeout = 4;
-#endif
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
+#endif /* CUSTOMER_HW4 && (VSDB || ROAM_ENABLE) */
+#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP)
uint32 bcn_li_bcn = 1;
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
+#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */
uint retry_max = 3;
#if defined(ARP_OFFLOAD_SUPPORT)
int arpoe = 1;
#endif
+#if defined(CUSTOMER_HW4)
+ int scan_assoc_time = 80;
+#else
int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
+#endif
int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME;
int scan_passive_time = DHD_SCAN_PASSIVE_TIME;
char buf[WLC_IOCTL_SMLEN];
@@ -3599,10 +3953,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint roamvar = 0;
int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL};
int roam_scan_period[2] = {10, WLC_BAND_ALL};
+ int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL};
#ifdef ROAM_AP_ENV_DETECTION
int roam_env_mode = AP_ENV_INDETERMINATE;
#endif /* ROAM_AP_ENV_DETECTION */
- int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL};
#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
int roam_fullscan_period = 60;
#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
@@ -3631,24 +3985,48 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#ifdef OKC_SUPPORT
uint32 okc = 1;
#endif
+#ifdef WLTDLS
+ uint32 tdls = 1;
+#ifdef CUSTOMER_HW4
+ uint32 tdls_idle_time = 10000; /* 10sec */
+ uint32 tdls_auto_op = 1;
+ int32 tdls_rssi_high = -80;
+ int32 tdls_rssi_low = -85;
+#endif
+#endif /* WLTDLS */
+
#ifdef DISABLE_11N
uint32 nmode = 0;
-#else
-#ifdef AMPDU_HOSTREORDER
- uint32 hostreorder = 1;
-#endif
#endif /* DISABLE_11N */
+
+#ifdef DISABLE_11AC
+ uint32 vhtmode = 0;
+#endif /* DISABLE_11AC */
+
#if defined(VSDB) && defined(CUSTOMER_HW4)
int interference_mode = 3;
#endif
+#ifdef USE_WL_TXBF
+ uint32 txbf = 1;
+#endif /* USE_WL_TXBF */
+#ifdef USE_WL_FRAMEBURST
+ uint32 frameburst = 1;
+#endif /* USE_WL_FRAMEBURST */
+#ifdef DHD_SET_FW_HIGHSPEED
+ uint32 ack_ratio = 250;
+ uint32 ack_ratio_depth = 64;
+#endif /* DHD_SET_FW_HIGHSPEED */
#ifdef PROP_TXSTATUS
#ifdef PROP_TXSTATUS_VSDB
+ /* In case the host does not support proptxstatus, hostreorder in dongle should be off */
+ uint32 hostreorder = 0;
dhd->wlfc_enabled = FALSE;
/* enable WLFC only if the firmware is VSDB */
#else
dhd->wlfc_enabled = TRUE;
#endif /* PROP_TXSTATUS_VSDB */
#endif /* PROP_TXSTATUS */
+ dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM;
DHD_TRACE(("Enter %s\n", __FUNCTION__));
dhd->op_mode = 0;
#ifdef GET_CUSTOM_MAC_ENABLE
@@ -3679,6 +4057,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
#endif /* GET_CUSTOM_MAC_ENABLE */
+ DHD_TRACE(("Firmware = %s\n", fw_path));
if ((!op_mode && strstr(fw_path, "_apsta") != NULL) ||
(op_mode == DHD_FLAG_HOSTAP_MODE)) {
@@ -3717,7 +4096,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret));
}
#endif
-
}
else {
uint32 concurrent_mode = 0;
@@ -3776,6 +4154,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
}
+#ifdef DISABLE_11AC
+ bcm_mkiovar("vhtmode", (char *)&vhtmode, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif
/* Set Listen Interval */
bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf));
@@ -3787,7 +4169,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */
-#ifdef ROAM_ENABLE
+#if defined(ROAM_ENABLE)
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger,
sizeof(roam_trigger), TRUE, 0)) < 0)
DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret));
@@ -3806,8 +4188,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
4, iovbuf, sizeof(iovbuf));
if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) == BCME_OK)
dhd->roam_env_detection = TRUE;
- else
+ else {
dhd->roam_env_detection = FALSE;
+ }
}
#endif /* ROAM_AP_ENV_DETECTION */
#endif /* ROAM_ENABLE */
@@ -3816,13 +4199,37 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
bcm_mkiovar("okc_enable", (char *)&okc, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif
+#ifdef WLTDLS
+ bcm_mkiovar("tdls_enable", (char *)&tdls, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#ifdef CUSTOMER_HW4
+ bcm_mkiovar("tdls_auto_op", (char *)&tdls_auto_op, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+ bcm_mkiovar("tdls_idle_time", (char *)&tdls_idle_time, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#ifdef CONFIG_CONTROL_PM
+ bcm_mkiovar("tdls_rssi_high", (char *)&tdls_rssi_high, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
+ bcm_mkiovar("tdls_rssi_low", (char *)&tdls_rssi_low, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#endif
+#endif /* WLTDLS */
+
+ /* Set lpc 1 */
+ bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set lpc failed %d\n", __FUNCTION__, ret));
+ }
+
+#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM)
sec_control_pm(dhd, &power_mode);
#else
/* Set PowerSave mode */
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
-#endif
+#endif /* CUSTOMER_HW4 && CONFIG_CONTROL_PM */
/* Match Host and Dongle rx alignment */
bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf));
@@ -3873,6 +4280,60 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
}
#endif /* defined(KEEP_ALIVE) */
+#ifdef USE_WL_TXBF
+ bcm_mkiovar("txbf", (char *)&txbf, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret));
+ }
+#endif /* USE_WL_TXBF */
+
+#ifdef USE_WL_FRAMEBURST
+#if defined(CUSTOMER_HW4)
+ frameburst = sec_control_frameburst();
+#endif /* CUSTOMER_HW4 */
+ /* Set frameburst to value */
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst,
+ sizeof(frameburst), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set frameburst failed %d\n", __FUNCTION__, ret));
+ }
+#endif /* USE_WL_FRAMEBURST */
+#ifdef DHD_SET_FW_HIGHSPEED
+ /* Set ack_ratio */
+ bcm_mkiovar("ack_ratio", (char *)&ack_ratio, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set ack_ratio failed %d\n", __FUNCTION__, ret));
+ }
+
+ /* Set ack_ratio_depth */
+ bcm_mkiovar("ack_ratio_depth", (char *)&ack_ratio_depth, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set ack_ratio_depth failed %d\n", __FUNCTION__, ret));
+ }
+#endif /* DHD_SET_FW_HIGHSPEED */
+#ifdef CUSTOM_AMPDU_BA_WSIZE
+ /* Set ampdu ba wsize to 64 */
+ bcm_mkiovar("ampdu_ba_wsize", (char *)&ampdu_ba_wsize, 4, iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0)) < 0) {
+ DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed %d\n",
+ __FUNCTION__, CUSTOM_AMPDU_BA_WSIZE, ret));
+ }
+#endif /* CUSTOM_AMPDU_BA_WSIZE */
+#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
+ /* Read 4-way handshake requirements. */
+ bcm_mkiovar("sup_wpa", (char *)&sup_wpa, 4,
+ iovbuf, sizeof(iovbuf));
+ ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+ if (ret >= 0)
+ dhd->fw_4way_handshake = TRUE;
+ DHD_TRACE(("4-way handshake mode is: %d\n", dhd->fw_4way_handshake));
+#endif /* BCMSUP_4WAY_HANDSHAKE && WLAN_AKM_SUITE_FT_8021X */
+
+ bcm_mkiovar("buf_key_b4_m4", (char *)&buf_key_b4_m4, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
/* Read event_msgs mask */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
@@ -3919,6 +4380,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
setbit(eventmask, WLC_E_ADDTS_IND);
setbit(eventmask, WLC_E_DELTS_IND);
#endif /* BCMCCX */
+#ifdef WLTDLS
+ setbit(eventmask, WLC_E_TDLS_PEER_EVENT);
+#endif /* WLTDLS */
#ifdef WL_CFG80211
setbit(eventmask, WLC_E_ESCAN_RESULT);
if (dhd->op_mode & DHD_FLAG_P2P_MODE) {
@@ -3961,21 +4425,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_arp_offload_enable(dhd, FALSE);
dhd_arp_offload_set(dhd, 0);
}
+ dhd_arp_enable = arpoe;
#endif /* ARP_OFFLOAD_SUPPORT */
#ifdef PKT_FILTER_SUPPORT
/* Setup default defintions for pktfilter , enable in suspend */
dhd->pktfilter_count = 5;
- /* Setup filter to allow only unicast */
- dhd->pktfilter[0] = "100 0 0 0 0x01 0x00";
dhd->pktfilter[1] = NULL;
dhd->pktfilter[2] = NULL;
dhd->pktfilter[3] = NULL;
/* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */
dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB";
-#ifdef CUSTOMER_HW4
-#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER
+#if defined(CUSTOMER_HW4) && defined(GAN_LITE_NAT_KEEPALIVE_FILTER)
dhd->pktfilter_count = 4;
/* Setup filter to block broadcast and NAT Keepalive packets */
dhd->pktfilter[0] = "100 0 0 0 0xffffff 0xffffff"; /* discard all broadcast packets */
@@ -3984,23 +4446,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd->pktfilter[3] = NULL;
#else
/* Setup filter to allow only unicast */
-#if defined(BLOCK_IPV6_PACKET)
+#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4)
dhd->pktfilter[0] = "100 0 0 0 "
HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR
" "
HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR;
#else
dhd->pktfilter[0] = "100 0 0 0 0x01 0x00";
-#endif /* BLOCK_IPV6_PACKET */
-#if defined(PASS_IPV4_SUSPEND)
+#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */
+#if defined(PASS_IPV4_SUSPEND) && defined(CUSTOMER_HW4)
dhd->pktfilter_count = 5;
dhd->pktfilter[4] = "104 0 0 0 0xFFFFFF 0x01005E";
-#endif
-#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
-#ifdef PASS_ARP_PACKET
- dhd->pktfilter[dhd->pktfilter_count++] = "105 0 0 12 0xFFFF 0x0806";
-#endif
-#endif /* CUSTOMER_HW4 */
+#endif /* PASS_IPV4_SUSPEND && CUSTOMER_HW4 */
+#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER && CUSTOMER_HW4 */
#if defined(SOFTAP)
if (ap_fw_loaded) {
@@ -4014,30 +4472,21 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)
DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret));
#else
-#ifdef AMPDU_HOSTREORDER
+#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 /* AMPDU_HOSTREORDER */
+#endif
#endif /* DISABLE_11N */
-#if !defined(WL_CFG80211)
- /* Force STA UP */
- if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) {
- DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret));
- goto done;
- }
-#endif
-
#if defined(VSDB) && defined(CUSTOMER_HW4)
dhd_wl_ioctl_cmd(dhd, WLC_SET_INTERFERENCE_MODE,
(int *)&interference_mode, sizeof(int), TRUE, 0);
#endif
-#ifdef ENABLE_BCN_LI_BCN_WAKEUP
+#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP)
bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-#endif /* ENABLE_BCN_LI_BCN_WAKEUP */
-
+#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
ptr = buf;
@@ -4049,14 +4498,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
/* Print fw version info */
DHD_ERROR(("Firmware version = %s\n", buf));
- dhd_set_version_info(dhd, buf);
-
- DHD_BLOG(buf, strlen(buf) + 1);
- DHD_BLOG(dhd_version, strlen(dhd_version) + 1);
-
/* Check and adjust IOCTL response timeout for Manufactring firmware */
if (strstr(buf, MANUFACTRING_FW) != NULL) {
- dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT * 10);
+ dhd_os_set_ioctl_resp_timeout(20000);
DHD_ERROR(("%s : adjust IOCTL response time for Manufactring Firmware\n",
__FUNCTION__));
}
@@ -4120,7 +4564,7 @@ int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx)
#ifdef ARP_OFFLOAD_SUPPORT
/* add or remove AOE host ip(s) (up to 8 IPs on the interface) */
void
-aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
+aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx)
{
u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */
int i;
@@ -4129,13 +4573,13 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
bzero(ipv4_buf, sizeof(ipv4_buf));
/* display what we've got */
- ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf));
+ ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
DHD_ARPOE(("%s: hostip table read from Dongle:\n", __FUNCTION__));
#ifdef AOE_DBG
dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
#endif
/* now we saved hoste_ip table, clr it in the dongle AOE */
- dhd_aoe_hostip_clr(dhd_pub);
+ dhd_aoe_hostip_clr(dhd_pub, idx);
if (ret) {
DHD_ERROR(("%s failed\n", __FUNCTION__));
@@ -4156,19 +4600,24 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add)
if (ipv4_buf[i] != 0) {
/* add back host_ip entries from our local cache */
- dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i]);
+ dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i], idx);
DHD_ARPOE(("%s: added IP:%x to dongle arp_hostip[%d]\n\n",
__FUNCTION__, ipv4_buf[i], i));
}
}
#ifdef AOE_DBG
/* see the resulting hostip table */
- dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf));
+ dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx);
DHD_ARPOE(("%s: read back arp_hostip table:\n", __FUNCTION__));
dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */
#endif
}
+/*
+ * Notification mechanism from kernel to our driver. This function is called by the Linux kernel
+ * whenever there is an event related to an IP address.
+ * ptr : kernel provided pointer to IP address that has changed
+ */
static int dhd_device_event(struct notifier_block *this,
unsigned long event,
void *ptr)
@@ -4177,19 +4626,48 @@ static int dhd_device_event(struct notifier_block *this,
dhd_info_t *dhd;
dhd_pub_t *dhd_pub;
+ int idx;
- if (!ifa)
+ if (!dhd_arp_enable)
return NOTIFY_DONE;
+ if (!ifa || !(ifa->ifa_dev->dev))
+ return NOTIFY_DONE;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
+ /* Filter notifications meant for non Broadcom devices */
+ if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) &&
+ (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) {
+#ifdef WLP2P
+ if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops))
+#endif
+ return NOTIFY_DONE;
+ }
+#endif /* LINUX_VERSION_CODE */
dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev);
+ if (!dhd)
+ return NOTIFY_DONE;
+
dhd_pub = &dhd->pub;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
- if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) {
-#else
- if (ifa->ifa_dev->dev) {
-#endif
- switch (event) {
+ if (dhd_pub->arp_version == 1) {
+ idx = 0;
+ }
+ else {
+ for (idx = 0; idx < DHD_MAX_IFS; idx++) {
+ if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev)
+ break;
+ }
+ if (idx < DHD_MAX_IFS)
+ DHD_TRACE(("ifidx : %p %s %d\n", dhd->iflist[idx]->net,
+ dhd->iflist[idx]->name, dhd->iflist[idx]->idx));
+ else {
+ DHD_ERROR(("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label));
+ idx = 0;
+ }
+ }
+
+ switch (event) {
case NETDEV_UP:
DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n",
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
@@ -4205,17 +4683,10 @@ static int dhd_device_event(struct notifier_block *this,
}
#ifdef AOE_IP_ALIAS_SUPPORT
- if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) {
- if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) {
- /* 0x3a = ':' */
- DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
- __FUNCTION__));
- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
- }
- else
- aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
- }
-#endif
+ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n",
+ __FUNCTION__));
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx);
+#endif /* AOE_IP_ALIAS_SUPPORT */
break;
case NETDEV_DOWN:
@@ -4223,20 +4694,12 @@ static int dhd_device_event(struct notifier_block *this,
__FUNCTION__, ifa->ifa_label, ifa->ifa_address));
dhd->pend_ipaddr = 0;
#ifdef AOE_IP_ALIAS_SUPPORT
- if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) {
- if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) {
- /* 0x3a = ':' */
- DHD_ARPOE(("%s: primary interface is down,"
- " AOE clr all\n", __FUNCTION__));
- dhd_aoe_hostip_clr(&dhd->pub);
- dhd_aoe_arp_clr(&dhd->pub);
- } else
- aoe_update_host_ipv4_table(dhd_pub,
- ifa->ifa_address, FALSE);
- }
+ DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n",
+ __FUNCTION__));
+ aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx);
#else
- dhd_aoe_hostip_clr(&dhd->pub);
- dhd_aoe_arp_clr(&dhd->pub);
+ dhd_aoe_hostip_clr(&dhd->pub, idx);
+ dhd_aoe_arp_clr(&dhd->pub, idx);
#endif /* AOE_IP_ALIAS_SUPPORT */
break;
@@ -4244,7 +4707,6 @@ static int dhd_device_event(struct notifier_block *this,
DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n",
__func__, ifa->ifa_label, event));
break;
- }
}
return NOTIFY_DONE;
}
@@ -4258,7 +4720,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
int err = 0;
uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 };
- DHD_ERROR(("%s: ifidx %d\n", __FUNCTION__, ifidx));
+ DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
ASSERT(dhd && dhd->iflist[ifidx]);
@@ -4431,7 +4893,7 @@ void dhd_detach(dhd_pub_t *dhdp)
if (dhd->early_suspend.suspend)
unregister_early_suspend(&dhd->early_suspend);
}
-#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */
+#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
cancel_work_sync(&dhd->work_hang);
@@ -4501,11 +4963,15 @@ void dhd_detach(dhd_pub_t *dhdp)
if (dhd->thr_dpc_ctl.thr_pid >= 0) {
PROC_STOP(&dhd->thr_dpc_ctl);
}
+#ifdef RXFRAME_THREAD
+ if (dhd->thr_rxf_ctl.thr_pid >= 0) {
+ PROC_STOP(&dhd->thr_rxf_ctl);
+ }
+#endif
else
#endif /* DHDTHREAD */
tasklet_kill(&dhd->tasklet);
}
-
#ifdef WL_CFG80211
if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
wl_cfg80211_detach(NULL);
@@ -4520,16 +4986,32 @@ void dhd_detach(dhd_pub_t *dhdp)
/* && defined(CONFIG_PM_SLEEP) */
if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) {
+ printk("wd wakelock count:%d\n", dhd->wakelock_wd_counter);
#ifdef CONFIG_HAS_WAKELOCK
dhd->wakelock_counter = 0;
+ dhd->wakelock_wd_counter = 0;
dhd->wakelock_rx_timeout_enable = 0;
dhd->wakelock_ctrl_timeout_enable = 0;
- wake_lock_destroy(&dhd->wl_wifi);
- wake_lock_destroy(&dhd->wl_rxwake);
- wake_lock_destroy(&dhd->wl_ctrlwake);
-#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT)
- wake_lock_destroy(&dhdp->pno_wakelock);
-#endif
+ if (dhd->wl_wifi) {
+ wake_lock_destroy(dhd->wl_wifi);
+ MFREE(dhd->pub.osh, dhd->wl_wifi, sizeof(struct wake_lock));
+ dhd->wl_wifi = NULL;
+ }
+ if (dhd->wl_rxwake) {
+ wake_lock_destroy(dhd->wl_rxwake);
+ MFREE(dhd->pub.osh, dhd->wl_rxwake, sizeof(struct wake_lock));
+ dhd->wl_rxwake = NULL;
+ }
+ if (dhd->wl_ctrlwake) {
+ wake_lock_destroy(dhd->wl_ctrlwake);
+ MFREE(dhd->pub.osh, dhd->wl_ctrlwake, sizeof(struct wake_lock));
+ dhd->wl_ctrlwake = NULL;
+ }
+ if (dhd->wl_wdwake) {
+ wake_lock_destroy(dhd->wl_wdwake);
+ MFREE(dhd->pub.osh, dhd->wl_wdwake, sizeof(struct wake_lock));
+ dhd->wl_wdwake = NULL;
+ }
#endif /* CONFIG_HAS_WAKELOCK */
}
}
@@ -4559,8 +5041,19 @@ dhd_free(dhd_pub_t *dhdp)
}
}
dhd = (dhd_info_t *)dhdp->info;
- if (dhd)
- MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */
+ if (dhd != (dhd_info_t *)dhd_os_prealloc(NULL, DHD_PREALLOC_DHD_INFO, 0)) {
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+ if (dhd)
+ MFREE(dhd->pub.osh, dhd, sizeof(*dhd));
+#if defined(CONFIG_DHD_USE_STATIC_BUF)
+ }
+ else {
+ if (dhd)
+ dhd = NULL;
+ }
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
}
}
@@ -4581,6 +5074,10 @@ dhd_module_cleanup(void)
}
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+extern bool g_wifi_poweron;
+#endif /* CONFIG_WIFI_CONTROL_FUNC */
+
static int __init
dhd_module_init(void)
{
@@ -4650,6 +5147,17 @@ dhd_module_init(void)
#endif
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+ /* If the wifi_set_power() is failed,
+ * we need to jump error handling routines.
+ */
+ if (!g_wifi_poweron) {
+ printk("%s: wifi_set_power() failed\n", __FUNCTION__);
+ error = -ENODEV;
+ goto fail_1;
+ }
+#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */
+
#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
sema_init(&dhd_registration_sem, 0);
#endif
@@ -4788,18 +5296,23 @@ dhd_os_wd_timer(void *bus, uint wdtick)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
- if (!dhd)
+ if (!dhd) {
+ DHD_ERROR(("%s: dhd NULL\n", __FUNCTION__));
return;
+ }
+ if (wdtick)
+ DHD_OS_WD_WAKE_LOCK(pub);
flags = dhd_os_spin_lock(pub);
/* don't start the wd until fw is loaded */
if (pub->busstate == DHD_BUS_DOWN) {
dhd_os_spin_unlock(pub, flags);
+ DHD_OS_WD_WAKE_UNLOCK(pub);
return;
}
- /* totally stop the timer */
+ /* Totally stop the timer */
if (!wdtick && dhd->wd_timer_valid == TRUE) {
dhd->wd_timer_valid = FALSE;
dhd_os_spin_unlock(pub, flags);
@@ -4808,6 +5321,7 @@ dhd_os_wd_timer(void *bus, uint wdtick)
#else
del_timer(&dhd->timer);
#endif /* DHDTHREAD */
+ DHD_OS_WD_WAKE_UNLOCK(pub);
return;
}
@@ -4932,6 +5446,48 @@ dhd_os_sdtxunlock(dhd_pub_t *pub)
dhd_os_sdunlock(pub);
}
+#if defined(DHDTHREAD) && defined(RXFRAME_THREAD)
+static void
+dhd_os_rxflock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_lock_bh(&dhd->rxf_lock);
+
+}
+
+static void
+dhd_os_rxfunlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_unlock_bh(&dhd->rxf_lock);
+}
+#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */
+
+#ifdef DHDTCPACK_SUPPRESS
+void
+dhd_os_tcpacklock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_lock_bh(&dhd->tcpack_lock);
+
+}
+
+void
+dhd_os_tcpackunlock(dhd_pub_t *pub)
+{
+ dhd_info_t *dhd;
+
+ dhd = (dhd_info_t *)(pub->info);
+ spin_unlock_bh(&dhd->tcpack_lock);
+}
+#endif /* DHDTCPACK_SUPPRESS */
+
#if defined(CONFIG_DHD_USE_STATIC_BUF)
uint8* dhd_os_prealloc(void *osh, int section, uint size)
{
@@ -5129,9 +5685,9 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
struct dhd_info *dhdinfo = dhd->info;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- int timeout = msecs_to_jiffies(2000);
+ int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT);
#else
- int timeout = 2 * HZ;
+ int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ;
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
dhd_os_sdunlock(dhd);
@@ -5197,19 +5753,16 @@ int net_os_set_suspend(struct net_device *dev, int val, int force)
#else
ret = dhd_suspend_resume_helper(dhd, val, force);
#endif
-#ifdef WL_CFG80211
- wl_cfg80211_update_power_mode(dev);
-#endif
}
return ret;
}
-int net_os_set_dtim_skip(struct net_device *dev, int val)
+int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
if (dhd)
- dhd->pub.dtim_skip = val;
+ dhd->pub.suspend_bcn_li_dtim = val;
return 0;
}
@@ -5236,10 +5789,10 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
filterp = "102 0 0 0 0xFFFFFF 0x01005E";
break;
case DHD_MULTICAST6_FILTER_NUM:
-#if defined(BLOCK_IPV6_PACKET)
+#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4)
/* customer want to use NO IPV6 packets only */
return ret;
-#endif
+#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */
filterp = "103 0 0 0 0xFFFF 0x3333";
break;
default:
@@ -5254,9 +5807,9 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */
}
-int net_os_enable_packet_filter(struct net_device *dev, int val)
+int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val)
+
{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
int ret = 0;
/* Packet filtering is set only if we still in early-suspend and
@@ -5264,26 +5817,35 @@ int net_os_enable_packet_filter(struct net_device *dev, int val)
* We can always turn it OFF in case of early-suspend, but we turn it
* back ON only if suspend_disable_flag was not set
*/
- if (dhd && dhd->pub.up) {
- if (dhd->pub.in_suspend) {
- if (!val || (val && !dhd->pub.suspend_disable_flag)) {
- dhd_enable_packet_filter(val, &dhd->pub);
- }
+ if (dhdp && dhdp->up) {
+ if (dhdp->in_suspend) {
+ if (!val || (val && !dhdp->suspend_disable_flag))
+ dhd_enable_packet_filter(val, dhdp);
}
}
return ret;
}
+
+/* function to enable/disable packet for Network device */
+int net_os_enable_packet_filter(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return dhd_os_enable_packet_filter(&dhd->pub, val);
+}
#endif /* PKT_FILTER_SUPPORT */
int
dhd_dev_init_ioctl(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-#if defined(USE_STAMAC_4SOFTAP)
+
+#if defined(CUSTOMER_HW4) && defined(USE_STAMAC_4SOFTAP)
/* Writing STA's MAC ID to the Dongle for SOFTAP */
if (_dhd_set_mac_address(dhd, 0, &dhd->pub.mac) == 0)
DHD_INFO(("dhd_bus_start: MAC ID is overwritten\n"));
-#endif
+#endif /* CUSTOMER_HW4 && USE_STAMAC_4SOFTAP */
+
return dhd_preinit_ioctls(&dhd->pub);
}
@@ -5354,12 +5916,20 @@ static void dhd_hang_process(struct work_struct *work)
int dhd_os_send_hang_message(dhd_pub_t *dhdp)
{
int ret = 0;
+ DHD_ERROR(("%s : Enter \n",__FUNCTION__));
+
if (dhdp) {
if (!dhdp->hang_was_sent) {
dhdp->hang_was_sent = 1;
- schedule_work(&dhdp->info->work_hang);
+ ret = schedule_work(&dhdp->info->work_hang);
+ if(!ret)
+ DHD_ERROR(("%s : schedule_task fail \n",__FUNCTION__));
+ else
+ DHD_ERROR(("%s : schedule_task success \n",__FUNCTION__));
}
}
+ else
+ DHD_ERROR(("%s : dhdp is null \n",__FUNCTION__));
return ret;
}
@@ -5376,7 +5946,7 @@ int net_os_send_hang_message(struct net_device *dev)
#endif
return ret;
}
-#endif /* (OEM_ANDROID) */
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */
void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
{
@@ -5388,6 +5958,7 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
#endif
}
}
+
void dhd_bus_band_set(struct net_device *dev, uint band)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
@@ -5398,7 +5969,6 @@ void dhd_bus_band_set(struct net_device *dev, uint band)
}
}
-
void dhd_net_if_lock(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
@@ -5470,7 +6040,7 @@ dhd_get_pend_8021x_cnt(dhd_info_t *dhd)
return (atomic_read(&dhd->pend_8021x_cnt));
}
-#define MAX_WAIT_FOR_8021X_TX 25
+#define MAX_WAIT_FOR_8021X_TX 50
int
dhd_wait_pend8021x(struct net_device *dev)
@@ -5490,7 +6060,10 @@ dhd_wait_pend8021x(struct net_device *dev)
pend = dhd_get_pend_8021x_cnt(dhd);
}
if (ntimes == 0)
+ {
+ atomic_set(&dhd->pend_8021x_cnt, 0);
DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__));
+ }
return pend;
}
@@ -5543,10 +6116,10 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub)
dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable;
#ifdef CONFIG_HAS_WAKELOCK
if (dhd->wakelock_rx_timeout_enable)
- wake_lock_timeout(&dhd->wl_rxwake,
+ wake_lock_timeout(dhd->wl_rxwake,
msecs_to_jiffies(dhd->wakelock_rx_timeout_enable));
if (dhd->wakelock_ctrl_timeout_enable)
- wake_lock_timeout(&dhd->wl_ctrlwake,
+ wake_lock_timeout(dhd->wl_ctrlwake,
msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable));
#endif
dhd->wakelock_rx_timeout_enable = 0;
@@ -5566,22 +6139,6 @@ int net_os_wake_lock_timeout(struct net_device *dev)
return ret;
}
-#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK)
-int net_os_wake_lock_timeout_for_pno(struct net_device *dev, int sec)
-{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int ret = 0;
- unsigned long flags;
-
- if (dhd) {
- spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
- wake_lock_timeout(&dhd->pub.pno_wakelock, HZ * sec);
- spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
- }
- return ret;
-}
-#endif
-
int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val)
{
dhd_info_t *dhd = (dhd_info_t *)(pub->info);
@@ -5640,11 +6197,11 @@ int dhd_os_wake_lock(dhd_pub_t *pub)
spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
#ifdef CONFIG_HAS_WAKELOCK
if (!dhd->wakelock_counter)
- wake_lock(&dhd->wl_wifi);
-#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP)
- /* SLP_wakelock_alternative_code */
- pm_stay_awake(pm_dev);
-#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */
+ wake_lock(dhd->wl_wifi);
+#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (pm_dev)
+ pm_stay_awake(pm_dev);
+#endif
dhd->wakelock_counter++;
ret = dhd->wakelock_counter;
spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
@@ -5675,11 +6232,11 @@ int dhd_os_wake_unlock(dhd_pub_t *pub)
dhd->wakelock_counter--;
#ifdef CONFIG_HAS_WAKELOCK
if (!dhd->wakelock_counter)
- wake_unlock(&dhd->wl_wifi);
-#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP)
- /* SLP_wakelock_alternative_code */
- pm_relax(pm_dev);
-#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */
+ wake_unlock(dhd->wl_wifi);
+#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (pm_dev)
+ pm_relax(pm_dev);
+#endif
ret = dhd->wakelock_counter;
}
spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
@@ -5689,30 +6246,23 @@ int dhd_os_wake_unlock(dhd_pub_t *pub)
int dhd_os_check_wakelock(void *dhdp)
{
-#ifdef CONFIG_HAS_WAKELOCK
+#if defined(CONFIG_HAS_WAKELOCK) || (1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, \
+ 36)))
dhd_pub_t *pub = (dhd_pub_t *)dhdp;
dhd_info_t *dhd;
if (!pub)
return 0;
dhd = (dhd_info_t *)(pub->info);
+#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */
- if (dhd && wake_lock_active(&dhd->wl_wifi))
+#ifdef CONFIG_HAS_WAKELOCK
+ if (dhd && wake_lock_active(dhd->wl_wifi))
return 1;
-#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP)
- /* SLP_wakelock_alternative_code */
- dhd_pub_t *pub = (dhd_pub_t *)dhdp;
- dhd_info_t *dhd;
-
- if (!pub)
- return 0;
- dhd = (dhd_info_t *)(pub->info);
-
- DHD_ERROR(("%s : wakelock_count = %d\n", __func__, dhd->wakelock_counter));
-
- if (dhd && (dhd->wakelock_counter > 0))
+#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36))
+ if (dhd && (dhd->wakelock_counter > 0) && pm_dev)
return 1;
-#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */
+#endif
return 0;
}
int net_os_wake_unlock(struct net_device *dev)
@@ -5725,31 +6275,58 @@ int net_os_wake_unlock(struct net_device *dev)
return ret;
}
-int dhd_os_check_if_up(void *dhdp)
+int dhd_os_wd_wake_lock(dhd_pub_t *pub)
{
- dhd_pub_t *pub = (dhd_pub_t *)dhdp;
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
- if (!pub)
- return 0;
- return pub->up;
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+#ifdef CONFIG_HAS_WAKELOCK
+ /* if wakelock_wd_counter was never used : lock it at once */
+ if (!dhd->wakelock_wd_counter) {
+ if (dhd->wl_wdwake)
+ wake_lock(dhd->wl_wdwake);
+ else {
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ return 0;
+ }
+ }
+#endif
+ dhd->wakelock_wd_counter++;
+ ret = dhd->wakelock_wd_counter;
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
}
-/* function to collect firmware, chip id and chip version info */
-void dhd_set_version_info(dhd_pub_t *dhdp, char *fw)
+int dhd_os_wd_wake_unlock(dhd_pub_t *pub)
{
- int i;
-
- i = snprintf(info_string, sizeof(info_string),
- " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw);
-
- if (!dhdp)
- return;
+ dhd_info_t *dhd = (dhd_info_t *)(pub->info);
+ unsigned long flags;
+ int ret = 0;
- i = snprintf(&info_string[i], sizeof(info_string) - i,
- "\n Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp),
- dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp));
+ if (dhd) {
+ spin_lock_irqsave(&dhd->wakelock_spinlock, flags);
+ if (dhd->wakelock_wd_counter) {
+ dhd->wakelock_wd_counter = 0;
+#ifdef CONFIG_HAS_WAKELOCK
+ wake_unlock(dhd->wl_wdwake);
+#endif
+ }
+ spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags);
+ }
+ return ret;
}
+int dhd_os_check_if_up(void *dhdp)
+{
+ dhd_pub_t *pub = (dhd_pub_t *)dhdp;
+ if (!pub)
+ return 0;
+ return pub->up;
+}
int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
{
int ifidx;
@@ -5762,6 +6339,9 @@ int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
}
dhd = *(dhd_info_t **)netdev_priv(net);
+ if (!dhd)
+ return -EINVAL;
+
ifidx = dhd_net2idx(dhd, net);
if (ifidx == DHD_BAD_IF) {
DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
@@ -5785,7 +6365,7 @@ bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret)
}
#if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP)
-#define MAX_TRY_CNT 5 /* Number of tries to disable deepsleep */
+#define MAX_TRY_CNT 5 /* Number of tries to disable deepsleep */
int dhd_deepsleep(struct net_device *dev, int flag)
{
char iovbuf[20];
@@ -5799,62 +6379,67 @@ int dhd_deepsleep(struct net_device *dev, int flag)
dhdp = &dhd->pub;
switch (flag) {
- case 1 : /* Deepsleep on */
- DHD_ERROR(("[WiFi] Deepsleep On\n"));
- /* give some time to _dhd_sysioc_thread() before deepsleep */
- msleep(200);
+ case 1 : /* Deepsleep on */
+ DHD_ERROR(("[WiFi] Deepsleep On\n"));
+ /* give some time to _dhd_sysioc_thread() before deepsleep */
+ msleep(200);
#ifdef PKT_FILTER_SUPPORT
/* disable pkt filter */
dhd_enable_packet_filter(0, dhdp);
#endif /* PKT_FILTER_SUPPORT */
- /* Disable MPC */
- powervar = 0;
- memset(iovbuf, 0, sizeof(iovbuf));
- bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
-
- /* Enable Deepsleep */
- powervar = 1;
- memset(iovbuf, 0, sizeof(iovbuf));
- bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- break;
-
- case 0: /* Deepsleep Off */
- DHD_ERROR(("[WiFi] Deepsleep Off\n"));
-
- /* Disable Deepsleep */
- for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) {
+ /* Disable MPC */
powervar = 0;
memset(iovbuf, 0, sizeof(iovbuf));
- bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
+ bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ /* Enable Deepsleep */
+ powervar = 1;
memset(iovbuf, 0, sizeof(iovbuf));
bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
- if ((ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, sizeof(iovbuf),
- FALSE, 0)) < 0) {
- DHD_ERROR(("the error of dhd deepsleep status ret value :%d\n",
- ret));
- } else {
- if (!(*(int *)iovbuf)) {
- DHD_ERROR(("deepsleep mode is 0, ok , count : %d\n", cnt));
- break;
+ dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ break;
+
+ case 0: /* Deepsleep Off */
+ DHD_ERROR(("[WiFi] Deepsleep Off\n"));
+
+ /* Disable Deepsleep */
+ for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) {
+ powervar = 0;
+ memset(iovbuf, 0, sizeof(iovbuf));
+ bcm_mkiovar("deepsleep", (char *)&powervar, 4,
+ iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf,
+ sizeof(iovbuf), TRUE, 0);
+
+
+ memset(iovbuf, 0, sizeof(iovbuf));
+ bcm_mkiovar("deepsleep", (char *)&powervar, 4,
+ iovbuf, sizeof(iovbuf));
+ if ((ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf,
+ sizeof(iovbuf), FALSE, 0)) < 0) {
+ DHD_ERROR(("the error of dhd deepsleep status"
+ " ret value :%d\n", ret));
+ } else {
+ if (!(*(int *)iovbuf)) {
+ DHD_ERROR(("deepsleep mode is 0,"
+ " count: %d\n", cnt));
+ break;
+ }
}
}
- }
- /* Enable MPC */
- powervar = 1;
- memset(iovbuf, 0, sizeof(iovbuf));
- bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- break;
+ /* Enable MPC */
+ powervar = 1;
+ memset(iovbuf, 0, sizeof(iovbuf));
+ bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf));
+ dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+ break;
}
return 0;
}
-#endif /* SUPPORT_DEEP_SLEEP */
+#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */
#ifdef PROP_TXSTATUS
extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t action, uint8 ifid,
@@ -5864,34 +6449,23 @@ extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits);
int dhd_wlfc_interface_event(struct dhd_info *dhd,
ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea)
{
- int ret = BCME_OK;
+ if (dhd->pub.wlfc_state == NULL)
+ return BCME_OK;
- dhd_os_wlfc_block(&dhd->pub);
- if (dhd->pub.wlfc_state != NULL)
- ret = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea);
- dhd_os_wlfc_unblock(&dhd->pub);
- return ret;
+ return dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea);
}
int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data)
{
- int ret = BCME_OK;
+ if (dhd->pub.wlfc_state == NULL)
+ return BCME_OK;
- dhd_os_wlfc_block(&dhd->pub);
- if (dhd->pub.wlfc_state != NULL)
- ret = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data);
- dhd_os_wlfc_unblock(&dhd->pub);
- return ret;
+ return dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data);
}
int dhd_wlfc_event(struct dhd_info *dhd)
{
- int ret;
-
- dhd_os_wlfc_block(&dhd->pub);
- ret = dhd_wlfc_enable(&dhd->pub);
- dhd_os_wlfc_unblock(&dhd->pub);
- return ret;
+ return dhd_wlfc_enable(&dhd->pub);
}
#endif /* PROP_TXSTATUS */