aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcmdhd/dhd_cfg80211.c')
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.c611
1 files changed, 89 insertions, 522 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
index 781a78b..987912f 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c
@@ -1,7 +1,7 @@
/*
* Linux cfg80211 driver - Dongle Host Driver (DHD) related
*
- * Copyright (C) 1999-2012, Broadcom Corporation
+ * Copyright (C) 1999-2014, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
@@ -24,11 +24,13 @@
* $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $
*/
+#include <linux/vmalloc.h>
#include <net/rtnetlink.h>
#include <bcmutils.h>
#include <wldev_common.h>
#include <wl_cfg80211.h>
+#include <brcm_nl80211.h>
#include <dhd_cfg80211.h>
#ifdef PKT_FILTER_SUPPORT
@@ -36,7 +38,7 @@
#include <dhd.h>
#endif
-extern struct wl_priv *wlcfg_drv_priv;
+extern struct bcm_cfg80211 *g_bcm_cfg;
#ifdef PKT_FILTER_SUPPORT
extern uint dhd_pkt_filter_enable;
@@ -58,27 +60,27 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up);
* Function implementations
*/
-s32 dhd_cfg80211_init(struct wl_priv *wl)
+s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg)
{
dhd_dongle_up = FALSE;
return 0;
}
-s32 dhd_cfg80211_deinit(struct wl_priv *wl)
+s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg)
{
dhd_dongle_up = FALSE;
return 0;
}
-s32 dhd_cfg80211_down(struct wl_priv *wl)
+s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg)
{
dhd_dongle_up = FALSE;
return 0;
}
-s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
+s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val)
{
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
dhd->op_mode |= val;
WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode));
#ifdef ARP_OFFLOAD_SUPPORT
@@ -92,9 +94,9 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val)
return 0;
}
-s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
+s32 dhd_cfg80211_clean_p2p_info(struct bcm_cfg80211 *cfg)
{
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+ dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE);
WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode));
@@ -109,6 +111,22 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl)
return 0;
}
+struct net_device* wl_cfg80211_allocate_if(struct bcm_cfg80211 *cfg, int ifidx, char *name,
+ uint8 *mac, uint8 bssidx)
+{
+ return dhd_allocate_if(cfg->pub, ifidx, name, mac, bssidx, FALSE);
+}
+
+int wl_cfg80211_register_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
+{
+ return dhd_register_if(cfg->pub, ifidx, FALSE);
+}
+
+int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, int ifidx, struct net_device* ndev)
+{
+ return dhd_remove_if(cfg->pub, ifidx, FALSE);
+}
+
static s32 wl_dongle_up(struct net_device *ndev, u32 up)
{
s32 err = 0;
@@ -119,7 +137,8 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
}
return err;
}
-s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
+
+s32 dhd_config_dongle(struct bcm_cfg80211 *cfg)
{
#ifndef DHD_SDALIGN
#define DHD_SDALIGN 32
@@ -133,10 +152,7 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
return err;
}
- ndev = wl_to_prmry_ndev(wl);
-
- if (need_lock)
- rtnl_lock();
+ ndev = bcmcfg_to_prmry_ndev(cfg);
err = wl_dongle_up(ndev, 0);
if (unlikely(err)) {
@@ -146,8 +162,7 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
dhd_dongle_up = true;
default_conf_out:
- if (need_lock)
- rtnl_unlock();
+
return err;
}
@@ -156,14 +171,19 @@ default_conf_out:
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
{
struct sk_buff *reply;
- struct wl_priv *wl;
+ struct bcm_cfg80211 *cfg;
dhd_pub_t *dhd;
- dhd_ioctl_t *ioc = data;
+ struct bcm_nlmsg_hdr *nlioc = data;
+ dhd_ioctl_t ioc = { 0 };
int err = 0;
+ void *buf = NULL, *cur;
+ u16 buflen;
+ u16 maxmsglen = PAGE_SIZE - 0x100;
+ bool newbuf = false;
- WL_TRACE(("entry: cmd = %d\n", ioc->cmd));
- wl = wiphy_priv(wiphy);
- dhd = wl->pub;
+ WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
+ cfg = wiphy_priv(wiphy);
+ dhd = cfg->pub;
DHD_OS_WAKE_LOCK(dhd);
@@ -175,520 +195,67 @@ int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
return OSL_ERROR(BCME_DONGLE_DOWN);
}
- /* currently there is only one wiphy for ifidx 0 */
- err = dhd_ioctl_process(dhd, 0, ioc);
- if (err)
- goto done;
-
- /* response data is in ioc->buf so return ioc here */
- reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc));
- nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc);
- err = cfg80211_testmode_reply(reply);
-done:
- DHD_OS_WAKE_UNLOCK(dhd);
- return err;
-}
-#endif /* CONFIG_NL80211_TESTMODE */
-
-/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */
-#define COEX_DHCP
-
-#if defined(COEX_DHCP)
-
-/* use New SCO/eSCO smart YG suppression */
-#define BT_DHCP_eSCO_FIX
-/* this flag boost wifi pkt priority to max, caution: -not fair to sco */
-#define BT_DHCP_USE_FLAGS
-/* T1 start SCO/ESCo priority suppression */
-#define BT_DHCP_OPPR_WIN_TIME 2500
-/* T2 turn off SCO/SCO supperesion is (timeout) */
-#define BT_DHCP_FLAG_FORCE_TIME 5500
+ len -= sizeof(struct bcm_nlmsg_hdr);
-enum wl_cfg80211_btcoex_status {
- BT_DHCP_IDLE,
- BT_DHCP_START,
- BT_DHCP_OPPR_WIN,
- BT_DHCP_FLAG_FORCE_TIMEOUT
-};
-
-/*
- * get named driver variable to uint register value and return error indication
- * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, &reg_value)
- */
-static int
-dev_wlc_intvar_get_reg(struct net_device *dev, char *name,
- uint reg, int *retval)
-{
- union {
- char buf[WLC_IOCTL_SMLEN];
- int val;
- } var;
- int error;
-
- bcm_mkiovar(name, (char *)(&reg), sizeof(reg),
- (char *)(&var), sizeof(var.buf));
- error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false);
-
- *retval = dtoh32(var.val);
- return (error);
-}
-
-static int
-dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
- char ioctlbuf_local[1024];
-#else
- static char ioctlbuf_local[1024];
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-
- bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local));
-
- return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true));
-}
-/*
-get named driver variable to uint register value and return error indication
-calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value)
-*/
-static int
-dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val)
-{
- char reg_addr[8];
-
- memset(reg_addr, 0, sizeof(reg_addr));
- memcpy((char *)&reg_addr[0], (char *)addr, 4);
- memcpy((char *)&reg_addr[4], (char *)val, 4);
-
- return (dev_wlc_bufvar_set(dev, name, (char *)&reg_addr[0], sizeof(reg_addr)));
-}
-
-static bool btcoex_is_sco_active(struct net_device *dev)
-{
- int ioc_res = 0;
- bool res = FALSE;
- int sco_id_cnt = 0;
- int param27;
- int i;
-
- for (i = 0; i < 12; i++) {
-
- ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
-
- WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27));
-
- if (ioc_res < 0) {
- WL_ERR(("ioc read btc params error\n"));
- break;
- }
-
- if ((param27 & 0x6) == 2) { /* count both sco & esco */
- sco_id_cnt++;
- }
-
- if (sco_id_cnt > 2) {
- WL_TRACE(("sco/esco detected, pkt id_cnt:%d samples:%d\n", sco_id_cnt, i));
- res = TRUE;
- break;
- }
-
- msleep(5);
- }
-
- return res;
-}
-
-#if defined(BT_DHCP_eSCO_FIX)
-/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */
-static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
-{
- static bool saved_status = FALSE;
-
- char buf_reg50va_dhcp_on[8] =
- { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
- char buf_reg51va_dhcp_on[8] =
- { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
- char buf_reg64va_dhcp_on[8] =
- { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
- char buf_reg65va_dhcp_on[8] =
- { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
- char buf_reg71va_dhcp_on[8] =
- { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
- uint32 regaddr;
- static uint32 saved_reg50;
- static uint32 saved_reg51;
- static uint32 saved_reg64;
- static uint32 saved_reg65;
- static uint32 saved_reg71;
-
- if (trump_sco) {
- /* this should reduce eSCO agressive retransmit
- * w/o breaking it
- */
-
- /* 1st save current */
- WL_TRACE(("Do new SCO/eSCO coex algo {save &"
- "override}\n"));
- if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) {
- saved_status = TRUE;
- WL_TRACE(("saved bt_params[50,51,64,65,71]:"
- "0x%x 0x%x 0x%x 0x%x 0x%x\n",
- saved_reg50, saved_reg51,
- saved_reg64, saved_reg65, saved_reg71));
+ if (nlioc->len > 0) {
+ if (nlioc->len <= len) {
+ buf = (void *)nlioc + nlioc->offset;
+ *(char *)(buf + nlioc->len) = '\0';
} else {
- WL_ERR((":%s: save btc_params failed\n",
- __FUNCTION__));
- saved_status = FALSE;
- return -1;
+ if (nlioc->len > DHD_IOCTL_MAXLEN)
+ nlioc->len = DHD_IOCTL_MAXLEN;
+ buf = vzalloc(nlioc->len);
+ if (!buf)
+ return -ENOMEM;
+ newbuf = true;
+ memcpy(buf, (void *)nlioc + nlioc->offset, len);
+ *(char *)(buf + len) = '\0';
}
-
- WL_TRACE(("override with [50,51,64,65,71]:"
- "0x%x 0x%x 0x%x 0x%x 0x%x\n",
- *(u32 *)(buf_reg50va_dhcp_on+4),
- *(u32 *)(buf_reg51va_dhcp_on+4),
- *(u32 *)(buf_reg64va_dhcp_on+4),
- *(u32 *)(buf_reg65va_dhcp_on+4),
- *(u32 *)(buf_reg71va_dhcp_on+4)));
-
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg50va_dhcp_on[0], 8);
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg51va_dhcp_on[0], 8);
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg64va_dhcp_on[0], 8);
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg65va_dhcp_on[0], 8);
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg71va_dhcp_on[0], 8);
-
- saved_status = TRUE;
- } else if (saved_status) {
- /* restore previously saved bt params */
- WL_TRACE(("Do new SCO/eSCO coex algo {save &"
- "override}\n"));
-
- regaddr = 50;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg50);
- regaddr = 51;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg51);
- regaddr = 64;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg64);
- regaddr = 65;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg65);
- regaddr = 71;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg71);
-
- WL_TRACE(("restore bt_params[50,51,64,65,71]:"
- "0x%x 0x%x 0x%x 0x%x 0x%x\n",
- saved_reg50, saved_reg51, saved_reg64,
- saved_reg65, saved_reg71));
-
- saved_status = FALSE;
- } else {
- WL_ERR((":%s att to restore not saved BTCOEX params\n",
- __FUNCTION__));
- return -1;
}
- return 0;
-}
-#endif /* BT_DHCP_eSCO_FIX */
-static void
-wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
-{
-#if defined(BT_DHCP_USE_FLAGS)
- char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 };
- char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
-#endif
-
-
-#if defined(BT_DHCP_eSCO_FIX)
- /* set = 1, save & turn on 0 - off & restore prev settings */
- set_btc_esco_params(dev, set);
-#endif
-
-#if defined(BT_DHCP_USE_FLAGS)
- WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set));
- if (set == TRUE)
- /* Forcing bt_flag7 */
- dev_wlc_bufvar_set(dev, "btc_flags",
- (char *)&buf_flag7_dhcp_on[0],
- sizeof(buf_flag7_dhcp_on));
- else
- /* Restoring default bt flag7 */
- dev_wlc_bufvar_set(dev, "btc_flags",
- (char *)&buf_flag7_default[0],
- sizeof(buf_flag7_default));
-#endif
-}
-
-static void wl_cfg80211_bt_timerfunc(ulong data)
-{
- struct btcoex_info *bt_local = (struct btcoex_info *)data;
- WL_TRACE(("Enter\n"));
- bt_local->timer_on = 0;
- schedule_work(&bt_local->work);
-}
-
-static void wl_cfg80211_bt_handler(struct work_struct *work)
-{
- struct btcoex_info *btcx_inf;
-
- btcx_inf = container_of(work, struct btcoex_info, work);
-
- if (btcx_inf->timer_on) {
- btcx_inf->timer_on = 0;
- del_timer_sync(&btcx_inf->timer);
+ ioc.cmd = nlioc->cmd;
+ ioc.len = nlioc->len;
+ ioc.set = nlioc->set;
+ ioc.driver = nlioc->magic;
+ err = dhd_ioctl_process(dhd, 0, &ioc, buf);
+ if (err) {
+ WL_TRACE(("dhd_ioctl_process return err %d\n", err));
+ err = OSL_ERROR(err);
+ goto done;
}
- switch (btcx_inf->bt_state) {
- case BT_DHCP_START:
- /* DHCP started
- * provide OPPORTUNITY window to get DHCP address
- */
- WL_TRACE(("bt_dhcp stm: started \n"));
- btcx_inf->bt_state = BT_DHCP_OPPR_WIN;
- mod_timer(&btcx_inf->timer,
- jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME));
- btcx_inf->timer_on = 1;
+ cur = buf;
+ while (nlioc->len > 0) {
+ buflen = nlioc->len > maxmsglen ? maxmsglen : nlioc->len;
+ nlioc->len -= buflen;
+ reply = cfg80211_testmode_alloc_reply_skb(wiphy, buflen+4);
+ if (!reply) {
+ WL_ERR(("Failed to allocate reply msg\n"));
+ err = -ENOMEM;
break;
-
- case BT_DHCP_OPPR_WIN:
- if (btcx_inf->dhcp_done) {
- WL_TRACE(("DHCP Done before T1 expiration\n"));
- goto btc_coex_idle;
- }
-
- /* DHCP is not over yet, start lowering BT priority
- * enforce btc_params + flags if necessary
- */
- WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME));
- if (btcx_inf->dev)
- wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE);
- btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT;
- mod_timer(&btcx_inf->timer,
- jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME));
- btcx_inf->timer_on = 1;
- break;
-
- case BT_DHCP_FLAG_FORCE_TIMEOUT:
- if (btcx_inf->dhcp_done) {
- WL_TRACE(("DHCP Done before T2 expiration\n"));
- } else {
- /* Noo dhcp during T1+T2, restore BT priority */
- WL_TRACE(("DHCP wait interval T2:%d msec expired\n",
- BT_DHCP_FLAG_FORCE_TIME));
- }
-
- /* Restoring default bt priority */
- if (btcx_inf->dev)
- wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
-btc_coex_idle:
- btcx_inf->bt_state = BT_DHCP_IDLE;
- btcx_inf->timer_on = 0;
- break;
-
- default:
- WL_ERR(("error g_status=%d !!!\n", btcx_inf->bt_state));
- if (btcx_inf->dev)
- wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE);
- btcx_inf->bt_state = BT_DHCP_IDLE;
- btcx_inf->timer_on = 0;
- break;
- }
-
- net_os_wake_unlock(btcx_inf->dev);
-}
-
-int wl_cfg80211_btcoex_init(struct wl_priv *wl)
-{
- struct btcoex_info *btco_inf = NULL;
-
- btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL);
- if (!btco_inf)
- return -ENOMEM;
-
- btco_inf->bt_state = BT_DHCP_IDLE;
- btco_inf->ts_dhcp_start = 0;
- btco_inf->ts_dhcp_ok = 0;
- /* Set up timer for BT */
- btco_inf->timer_ms = 10;
- init_timer(&btco_inf->timer);
- btco_inf->timer.data = (ulong)btco_inf;
- btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
-
- btco_inf->dev = wl->wdev->netdev;
-
- INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler);
-
- wl->btcoex_info = btco_inf;
- return 0;
-}
-
-void wl_cfg80211_btcoex_deinit(struct wl_priv *wl)
-{
- if (!wl->btcoex_info)
- return;
-
- if (wl->btcoex_info->timer_on) {
- wl->btcoex_info->timer_on = 0;
- del_timer_sync(&wl->btcoex_info->timer);
- }
-
- cancel_work_sync(&wl->btcoex_info->work);
-
- kfree(wl->btcoex_info);
- wl->btcoex_info = NULL;
-}
-
-int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command)
-{
-
- struct wl_priv *wl = wlcfg_drv_priv;
- char powermode_val = 0;
- char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 };
- char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 };
- char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 };
-
- uint32 regaddr;
- static uint32 saved_reg66;
- static uint32 saved_reg41;
- static uint32 saved_reg68;
- static bool saved_status = FALSE;
-
-#ifdef COEX_DHCP
- char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00};
- struct btcoex_info *btco_inf = wl->btcoex_info;
-#endif /* COEX_DHCP */
-
-#ifdef PKT_FILTER_SUPPORT
- dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
-#endif
-
- /* Figure out powermode 1 or o command */
- strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1);
-
- if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) {
- WL_TRACE_HW4(("DHCP session starts\n"));
-
-#ifdef PKT_FILTER_SUPPORT
- dhd->dhcp_in_progress = 1;
-
- if (dhd->early_suspended) {
- WL_TRACE_HW4(("DHCP in progressing , disable packet filter!!!\n"));
- dhd_enable_packet_filter(0, dhd);
}
-#endif
- /* Retrieve and saved orig regs value */
- if ((saved_status == FALSE) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) &&
- (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) {
- saved_status = TRUE;
- WL_TRACE(("Saved 0x%x 0x%x 0x%x\n",
- saved_reg66, saved_reg41, saved_reg68));
-
- /* Disable PM mode during dhpc session */
-
- /* Disable PM mode during dhpc session */
-#ifdef COEX_DHCP
- /* Start BT timer only for SCO connection */
- if (btcoex_is_sco_active(dev)) {
- /* btc_params 66 */
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg66va_dhcp_on[0],
- sizeof(buf_reg66va_dhcp_on));
- /* btc_params 41 0x33 */
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg41va_dhcp_on[0],
- sizeof(buf_reg41va_dhcp_on));
- /* btc_params 68 0x190 */
- dev_wlc_bufvar_set(dev, "btc_params",
- (char *)&buf_reg68va_dhcp_on[0],
- sizeof(buf_reg68va_dhcp_on));
- saved_status = TRUE;
-
- btco_inf->bt_state = BT_DHCP_START;
- btco_inf->timer_on = 1;
- mod_timer(&btco_inf->timer, btco_inf->timer.expires);
- WL_TRACE(("enable BT DHCP Timer\n"));
- }
-#endif /* COEX_DHCP */
- }
- else if (saved_status == TRUE) {
- WL_ERR(("was called w/o DHCP OFF. Continue\n"));
- }
- }
- else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) {
-
-
-#ifdef PKT_FILTER_SUPPORT
- dhd->dhcp_in_progress = 0;
- WL_TRACE_HW4(("DHCP is complete \n"));
-
- /* Enable packet filtering */
- if (dhd->early_suspended) {
- WL_TRACE_HW4(("DHCP is complete , enable packet filter!!!\n"));
- dhd_enable_packet_filter(1, dhd);
- }
-#endif
-
- /* Restoring PM mode */
-
-#ifdef COEX_DHCP
- /* Stop any bt timer because DHCP session is done */
- WL_TRACE(("disable BT DHCP Timer\n"));
- if (btco_inf->timer_on) {
- btco_inf->timer_on = 0;
- del_timer_sync(&btco_inf->timer);
-
- if (btco_inf->bt_state != BT_DHCP_IDLE) {
- /* need to restore original btc flags & extra btc params */
- WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state));
- /* wake up btcoex thread to restore btlags+params */
- schedule_work(&btco_inf->work);
- }
+ if (nla_put(reply, BCM_NLATTR_DATA, buflen, cur) ||
+ nla_put_u16(reply, BCM_NLATTR_LEN, buflen)) {
+ kfree_skb(reply);
+ err = -ENOBUFS;
+ break;
}
- /* Restoring btc_flag paramter anyway */
- if (saved_status == TRUE)
- dev_wlc_bufvar_set(dev, "btc_flags",
- (char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
-#endif /* COEX_DHCP */
-
- /* Restore original values */
- if (saved_status == TRUE) {
- regaddr = 66;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg66);
- regaddr = 41;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg41);
- regaddr = 68;
- dev_wlc_intvar_set_reg(dev, "btc_params",
- (char *)&regaddr, (char *)&saved_reg68);
-
- WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n",
- saved_reg66, saved_reg41, saved_reg68));
+ do {
+ err = cfg80211_testmode_reply(reply);
+ } while (err == -EAGAIN);
+ if (err) {
+ WL_ERR(("testmode reply failed:%d\n", err));
+ break;
}
- saved_status = FALSE;
-
+ cur += buflen;
}
- else {
- WL_ERR(("Unkwown yet power setting, ignored\n"));
- }
-
- snprintf(command, 3, "OK");
- return (strlen("OK"));
+done:
+ if (newbuf)
+ vfree(buf);
+ DHD_OS_WAKE_UNLOCK(dhd);
+ return err;
}
-#endif
+#endif /* CONFIG_NL80211_TESTMODE */