summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/bcmdhd/dhd_linux.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/dhd_linux.c')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c277
1 files changed, 185 insertions, 92 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index fcf8f0a45413..0f419a5e1cbc 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 325862 2012-04-04 22:59:48Z $
+ * $Id: dhd_linux.c 352789 2012-08-24 00:01:33Z $
*/
#include <typedefs.h>
@@ -295,10 +295,16 @@ typedef struct dhd_info {
char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
+/* load firmware and/or nvram values from the filesystem */
+module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
+module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
+
+char info_string[MOD_PARAM_INFOLEN];
+module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444);
+
int op_mode = 0;
module_param(op_mode, int, 0644);
extern int wl_control_wl_start(struct net_device *dev);
-extern int net_os_send_hang_message(struct net_device *dev);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
struct semaphore dhd_registration_sem;
#define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */
@@ -311,10 +317,6 @@ module_param(dhd_sysioc, uint, 0);
/* Error bits */
module_param(dhd_msg_level, int, 0);
-/* load firmware and/or nvram values from the filesystem */
-module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
-module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0);
-
/* Watchdog interval */
uint dhd_watchdog_ms = 10;
module_param(dhd_watchdog_ms, uint, 0);
@@ -325,8 +327,8 @@ uint dhd_console_ms = 0;
module_param(dhd_console_ms, uint, 0644);
#endif /* defined(DHD_DEBUG) */
-/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */
-uint dhd_arp_mode = 0xb;
+/* ARP offload agent mode : enable ARP Peer Auto-Reply */
+uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY;
module_param(dhd_arp_mode, uint, 0);
/* ARP offload enable */
@@ -347,14 +349,13 @@ module_param(dhd_master_mode, uint, 0);
#ifdef DHDTHREAD
/* Watchdog thread priority, -1 to use kernel timer */
-int dhd_watchdog_prio = 97;
+int dhd_watchdog_prio = 0;
module_param(dhd_watchdog_prio, int, 0);
/* DPC thread priority, -1 to use tasklet */
-int dhd_dpc_prio = 98;
+int dhd_dpc_prio = 1;
module_param(dhd_dpc_prio, int, 0);
-/* DPC thread priority, -1 to use tasklet */
extern int dhd_dongle_memsize;
module_param(dhd_dongle_memsize, int, 0);
#endif /* DHDTHREAD */
@@ -512,7 +513,8 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
DHD_TRACE(("%s: %d\n", __FUNCTION__, value));
/* 1 - Enable packet filter, only allow unicast packet to send up */
/* 0 - Disable packet filter */
- if (dhd_pkt_filter_enable) {
+ if (dhd_pkt_filter_enable && (!value ||
+ (dhd_check_ap_wfd_mode_set(dhd) == FALSE))) {
int i;
for (i = 0; i < dhd->pktfilter_count; i++) {
@@ -540,7 +542,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
if (value && dhd->in_suspend) {
/* Kernel suspended */
- DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__));
+ DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__));
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
sizeof(power_mode), TRUE, 0);
@@ -564,7 +566,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
} else {
/* Kernel resumed */
- DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__));
+ DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__));
power_mode = PM_FAST;
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
@@ -644,7 +646,7 @@ dhd_timeout_start(dhd_timeout_t *tmo, uint usec)
tmo->limit = usec;
tmo->increment = 0;
tmo->elapsed = 0;
- tmo->tick = 1000000 / HZ;
+ tmo->tick = jiffies_to_usecs(1);
}
int
@@ -670,16 +672,12 @@ dhd_timeout_expired(dhd_timeout_t *tmo)
} else {
wait_queue_head_t delay_wait;
DECLARE_WAITQUEUE(wait, current);
- int pending;
init_waitqueue_head(&delay_wait);
add_wait_queue(&delay_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
- pending = signal_pending(current);
remove_wait_queue(&delay_wait, &wait);
set_current_state(TASK_RUNNING);
- if (pending)
- return 1; /* Interrupted */
}
return 0;
@@ -1028,7 +1026,7 @@ dhd_op_if(dhd_if_t *ifp)
#endif
netif_stop_queue(ifp->net);
unregister_netdev(ifp->net);
- ret = DHD_DEL_IF;
+ ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */
#ifdef WL_CFG80211
if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
@@ -1363,10 +1361,11 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
done:
- if (ret)
+ if (ret) {
dhd->pub.dstats.tx_dropped++;
- else
+ } else {
dhd->pub.tx_packets++;
+ }
DHD_OS_WAKE_UNLOCK(&dhd->pub);
@@ -1472,6 +1471,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
*/
((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++;
PKTFREE(dhdp->osh, pktbuf, TRUE);
+ DHD_TRACE(("RX: wlfc header \n"));
continue;
}
#endif
@@ -1527,9 +1527,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
tout_ctrl = DHD_PACKET_TIMEOUT_MS;
if (event.event_type == WLC_E_BTA_HCI_EVENT) {
dhd_bta_doevt(dhdp, data, event.datalen);
- } else if (event.event_type == WLC_E_PFN_NET_FOUND) {
+ }
+#ifdef PNO_SUPPORT
+ if (event.event_type == WLC_E_PFN_NET_FOUND) {
tout_ctrl *= 2;
}
+#endif /* PNO_SUPPORT */
} else {
tout_rx = DHD_PACKET_TIMEOUT_MS;
}
@@ -1564,6 +1567,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */
}
}
+
DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx);
DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl);
}
@@ -1689,7 +1693,7 @@ dhd_watchdog_thread(void *data)
/* Reschedule the watchdog */
if (dhd->wd_timer_valid)
mod_timer(&dhd->timer,
- jiffies + dhd_watchdog_ms * HZ / 1000);
+ jiffies + msecs_to_jiffies(dhd_watchdog_ms));
dhd_os_spin_unlock(&dhd->pub, flags);
}
dhd_os_sdunlock(&dhd->pub);
@@ -1730,7 +1734,7 @@ static void dhd_watchdog(ulong data)
/* Reschedule the watchdog */
if (dhd->wd_timer_valid)
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ 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);
@@ -2448,6 +2452,9 @@ dhd_open(struct net_device *net)
OLD_MOD_INC_USE_COUNT;
exit:
+ if (ret)
+ dhd_stop(net);
+
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return ret;
}
@@ -2641,17 +2648,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
strcat(net->name, "%d");
}
- if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF)
- goto fail;
- dhd_state |= DHD_ATTACH_STATE_ADD_IF;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
- net->open = NULL;
-#else
- net->netdev_ops = NULL;
-#endif
-
sema_init(&dhd->proto_sem, 1);
+#ifdef DHDTHREAD
+ sema_init(&dhd->sdsem, 1);
+#endif
#ifdef PROP_TXSTATUS
spin_lock_init(&dhd->wlfc_spinlock);
@@ -2667,6 +2667,17 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
spin_lock_init(&dhd->txqlock);
spin_lock_init(&dhd->dhd_lock);
+
+ if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF)
+ goto fail;
+ dhd_state |= DHD_ATTACH_STATE_ADD_IF;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31))
+ net->open = NULL;
+#else
+ net->netdev_ops = NULL;
+#endif
+
/* Initialize Wakelock stuff */
spin_lock_init(&dhd->wakelock_spinlock);
dhd->wakelock_counter = 0;
@@ -2719,7 +2730,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
#ifdef DHDTHREAD
/* Initialize thread based operation and lock */
- sema_init(&dhd->sdsem, 1);
if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)) {
dhd->threads_only = TRUE;
}
@@ -2938,28 +2948,34 @@ dhd_concurrent_fw(dhd_pub_t *dhd)
bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
FALSE, 0)) < 0) {
- DHD_TRACE(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret));
} else if (buf[0] == 1) {
DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__));
return 1;
}
}
- return 0;
+ return ret;
}
#endif
+/*
+ * dhd_preinit_ioctls makes special pre-setting in the firmware before radio turns on
+ * returns : 0 if all settings passed or negative value if anything failed
+*/
int
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) */
uint power_mode = PM_FAST;
uint32 dongle_align = DHD_SDALIGN;
uint32 glom = 0;
- uint bcn_timeout = 10;
+ uint bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL;
+
uint retry_max = 3;
#if defined(ARP_OFFLOAD_SUPPORT)
int arpoe = 1;
@@ -2974,6 +2990,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
char *ptr;
uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
uint16 chipID;
+ int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL};
+ int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL};
#if defined(SOFTAP)
uint dtim = 1;
#endif
@@ -3038,20 +3056,31 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* SET_RANDOM_MAC_SOFTAP */
DHD_TRACE(("Firmware = %s\n", fw_path));
+
#if !defined(AP) && defined(WLP2P)
/* Check if firmware with WFD support used */
+#if defined(WL_ENABLE_P2P_IF)
+ if ((ret = dhd_concurrent_fw(dhd)) < 0) {
+ DHD_ERROR(("%s error : firmware can't support p2p mode\n", __FUNCTION__));
+ goto done;
+ }
+#endif /* (WL_ENABLE_P2P_IF) */
+
if ((!op_mode && strstr(fw_path, "_p2p") != NULL)
#if defined(WL_ENABLE_P2P_IF)
- || (op_mode == 0x04) ||(dhd_concurrent_fw(dhd))
+ || (op_mode == WFD_MASK) || (dhd_concurrent_fw(dhd) == 1)
#endif
) {
bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR,
iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
- DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret));
+ DHD_ERROR(("%s APSTA setting failed ret= %d\n", __FUNCTION__, ret));
} else {
dhd->op_mode |= WFD_MASK;
+#if !defined(WL_ENABLE_P2P_IF)
+ /* ICS back capability : disable any packet filtering for p2p only mode */
dhd_pkt_filter_enable = FALSE;
+#endif /*!defined(WL_ENABLE_P2P_IF) */
}
}
#endif
@@ -3096,16 +3125,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#if defined(ARP_OFFLOAD_SUPPORT)
arpoe = 0;
#endif /* (ARP_OFFLOAD_SUPPORT) */
+ /* disable any filtering for SoftAP mode */
dhd_pkt_filter_enable = FALSE;
}
}
#endif
+#if !defined(WL_ENABLE_P2P_IF)
+ /* ICS mode setting for sta */
if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) {
/* STA only operation mode */
dhd->op_mode |= STA_MASK;
dhd_pkt_filter_enable = TRUE;
}
+#endif /* !defined(WL_ENABLE_P2P_IF) */
DHD_ERROR(("Firmware up: op_mode=%d, "
"Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
@@ -3126,6 +3159,14 @@ 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 assoc_listen failed %d\n", __FUNCTION__, ret));
+ /* custom romaing setting */
+ 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));
+ if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta,
+ sizeof(roam_delta), TRUE, 0)) < 0)
+ DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret));
+
/* Set PowerSave mode */
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
@@ -3184,6 +3225,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
setbit(eventmask, WLC_E_SET_SSID);
setbit(eventmask, WLC_E_PRUNE);
setbit(eventmask, WLC_E_AUTH);
+ setbit(eventmask, WLC_E_ASSOC);
setbit(eventmask, WLC_E_REASSOC);
setbit(eventmask, WLC_E_REASSOC_IND);
setbit(eventmask, WLC_E_DEAUTH);
@@ -3198,8 +3240,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
setbit(eventmask, WLC_E_MIC_ERROR);
setbit(eventmask, WLC_E_ASSOC_REQ_IE);
setbit(eventmask, WLC_E_ASSOC_RESP_IE);
+#ifndef WL_CFG80211
setbit(eventmask, WLC_E_PMKID_CACHE);
setbit(eventmask, WLC_E_TXFAIL);
+#endif
setbit(eventmask, WLC_E_JOIN_START);
setbit(eventmask, WLC_E_SCAN_COMPLETE);
#ifdef WLMEDIA_HTSF
@@ -3258,6 +3302,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
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";
#if defined(SOFTAP)
if (ap_fw_loaded) {
@@ -3270,12 +3315,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* defined(SOFTAP) */
#endif /* PKT_FILTER_SUPPORT */
+#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
/* query for 'ver' to get version info from firmware */
memset(buf, 0, sizeof(buf));
ptr = buf;
@@ -3287,6 +3333,8 @@ 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);
@@ -3905,36 +3953,12 @@ int
dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending)
{
dhd_info_t * dhd = (dhd_info_t *)(pub->info);
- DECLARE_WAITQUEUE(wait, current);
- int timeout = dhd_ioctl_timeout_msec;
+ int timeout;
/* Convert timeout in millsecond to jiffies */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
- timeout = msecs_to_jiffies(timeout);
-#else
- timeout = timeout * HZ / 1000;
-#endif
-
- /* Wait until control frame is available */
- add_wait_queue(&dhd->ioctl_resp_wait, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- /* Memory barrier to support multi-processing
- * As the variable "condition", which points to dhd->rxlen (dhd_bus_rxctl[dhd_sdio.c])
- * Can be changed by another processor.
- */
- smp_mb();
- while (!(*condition) && (!signal_pending(current) && timeout)) {
- timeout = schedule_timeout(timeout);
- smp_mb();
- }
-
- if (signal_pending(current))
- *pending = TRUE;
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&dhd->ioctl_resp_wait, &wait);
+ timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec);
+ timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout);
return timeout;
}
@@ -3944,7 +3968,7 @@ dhd_os_ioctl_resp_wake(dhd_pub_t *pub)
dhd_info_t *dhd = (dhd_info_t *)(pub->info);
if (waitqueue_active(&dhd->ioctl_resp_wait)) {
- wake_up_interruptible(&dhd->ioctl_resp_wait);
+ wake_up(&dhd->ioctl_resp_wait);
}
return 0;
@@ -3982,7 +4006,7 @@ dhd_os_wd_timer(void *bus, uint wdtick)
if (wdtick) {
dhd_watchdog_ms = (uint)wdtick;
/* Re arm the timer, at last watchdog period */
- mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000);
+ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms));
dhd->wd_timer_valid = TRUE;
}
dhd_os_spin_unlock(pub, flags);
@@ -4293,8 +4317,9 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
struct dhd_info *dhdinfo = dhd->info;
+ int timeout = msecs_to_jiffies(2000);
dhd_os_sdunlock(dhd);
- wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 2);
+ wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout);
dhd_os_sdlock(dhd);
#endif
return;
@@ -4305,7 +4330,7 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
struct dhd_info *dhdinfo = dhd->info;
if (waitqueue_active(&dhdinfo->ctrl_wait))
- wake_up_interruptible(&dhdinfo->ctrl_wait);
+ wake_up(&dhdinfo->ctrl_wait);
#endif
return;
}
@@ -4317,6 +4342,13 @@ dhd_dev_reset(struct net_device *dev, uint8 flag)
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ if (flag == TRUE) {
+ /* Issue wl down command before resetting the chip */
+ if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) {
+ DHD_TRACE(("%s: wl down failed\n", __FUNCTION__));
+ }
+ }
+
ret = dhd_bus_devreset(&dhd->pub, flag);
if (ret) {
DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret));
@@ -4349,6 +4381,9 @@ 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;
}
@@ -4393,9 +4428,8 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
return ret;
}
-int net_os_set_packet_filter(struct net_device *dev, int val)
+int dhd_os_set_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
@@ -4403,22 +4437,29 @@ int net_os_set_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_set_packet_filter(val, &dhd->pub);
+ if (dhdp && dhdp->up) {
+ if (dhdp->in_suspend) {
+ if (!val || (val && !dhdp->suspend_disable_flag))
+ dhd_set_packet_filter(val, dhdp);
}
}
return ret;
+
}
+int net_os_set_packet_filter(struct net_device *dev, int val)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return dhd_os_set_packet_filter(&dhd->pub, val);
+}
-void
+int
dhd_dev_init_ioctl(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- dhd_preinit_ioctls(&dhd->pub);
+ return dhd_preinit_ioctls(&dhd->pub);
}
#ifdef PNO_SUPPORT
@@ -4452,6 +4493,17 @@ dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max));
}
+/* Linux wrapper to call common dhd_pno_set_ex */
+int
+dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid,
+ ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ return (dhd_pno_set_ex(&dhd->pub, ssidnet, nssid,
+ pno_interval, pno_repeat, pno_expo_max, pno_lost_time));
+}
+
/* Linux wrapper to get pno status */
int
dhd_dev_get_pno_status(struct net_device *dev)
@@ -4480,32 +4532,59 @@ static void dhd_hang_process(struct work_struct *work)
wl_iw_send_priv_event(dev, "HANG");
#endif
#if defined(WL_CFG80211)
- wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED);
+ wl_cfg80211_hang(dev, WLAN_REASON_DRIVER_ERROR);
#endif
}
}
+#endif
-int net_os_send_hang_message(struct net_device *dev)
+int dhd_os_send_hang_message(dhd_pub_t *dhdp)
{
- dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
int ret = 0;
- if (dhd) {
- if (!dhd->pub.hang_was_sent) {
- dhd->pub.hang_was_sent = 1;
- schedule_work(&dhd->work_hang);
+ if (dhdp) {
+ if (!dhdp->hang_was_sent) {
+ dhdp->hang_was_sent = 1;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
+ schedule_work(&dhdp->info->work_hang);
+#endif
}
}
return ret;
}
-#endif
+
+int net_os_send_hang_message(struct net_device *dev)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+ int ret = 0;
+
+ if (dhd)
+ ret = dhd_os_send_hang_message(&dhd->pub);
+
+ return ret;
+}
void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- if (dhd && dhd->pub.up)
+ if (dhd && dhd->pub.up) {
memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
+#ifdef WL_CFG80211
+ wl_update_wiphybands(NULL);
+#endif
+ }
+}
+
+void dhd_bus_band_set(struct net_device *dev, uint band)
+{
+ dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
+
+ if (dhd && dhd->pub.up) {
+#ifdef WL_CFG80211
+ wl_update_wiphybands(NULL);
+#endif
+ }
}
void dhd_net_if_lock(struct net_device *dev)
@@ -4585,7 +4664,7 @@ int
dhd_wait_pend8021x(struct net_device *dev)
{
dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
- int timeout = 10 * HZ / 1000;
+ int timeout = msecs_to_jiffies(10);
int ntimes = MAX_WAIT_FOR_8021X_TX;
int pend = dhd_get_pend_8021x_cnt(dhd);
@@ -4807,6 +4886,20 @@ int dhd_os_check_if_up(void *dhdp)
return pub->up;
}
+void dhd_set_version_info(dhd_pub_t *dhdp, char *fw)
+{
+ int i;
+
+ i = snprintf(info_string, sizeof(info_string),
+ " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw);
+
+ if (!dhdp)
+ return;
+ 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));
+}
+
int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
{
int ifidx;