diff options
author | Greg Goldman <ggoldman@broadcom.com> | 2010-10-21 14:04:41 -0700 |
---|---|---|
committer | Dmitry Shmidt <dimitrysh@google.com> | 2010-10-22 10:44:23 -0700 |
commit | 5f986025ba0b705731b36facc639d7e7957b0a09 (patch) | |
tree | 5a65383f754f943343942ca2e7a297323a76d0ea | |
parent | 5ff1b9cdb1791cab2759a2a073f0ba6b24579bc3 (diff) |
net: wireless: bcm4329: Improve BT-coex for eSCO
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
-rw-r--r-- | drivers/net/wireless/bcm4329/dhd_linux.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/bcm4329/wl_iw.c | 180 |
2 files changed, 158 insertions, 24 deletions
diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index fe7cbf116372..d7e72c8d12d2 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -305,7 +305,7 @@ char nvram_path[MOD_PARAM_PATHLEN]; #if defined(CONFIG_HAS_EARLYSUSPEND) #define KEEP_ALIVE -#define KEEP_ALIVE_PERIOD 60000 +#define KEEP_ALIVE_PERIOD 55000 #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index a9f3ee31f1dc..82164edc6534 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -21,7 +21,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: wl_iw.c,v 1.51.4.9.2.6.4.142.4.13 2010/09/15 03:34:56 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.28 2010/10/19 22:55:15 Exp $ */ @@ -54,6 +54,7 @@ typedef const struct si_pub si_t; #define WL_INFORM(x) #define WL_WSEC(x) #define WL_SCAN(x) +#define WL_TRACE_COEX(x) #include <wl_iw.h> @@ -219,6 +220,11 @@ typedef struct iscan_info { int iscan_ex_param_size; } iscan_info_t; #define COEX_DHCP 1 + +#define BT_DHCP_eSCO_FIX +#define BT_DHCP_USE_FLAGS +#define BT_DHCP_OPPORTUNITY_WINDOW_TIME 2500 +#define BT_DHCP_FLAG_FORCE_TIME 5500 static void wl_iw_bt_flag_set(struct net_device *dev, bool set); static void wl_iw_bt_release(void); @@ -228,18 +234,16 @@ typedef enum bt_coex_status { BT_DHCP_OPPORTUNITY_WINDOW, BT_DHCP_FLAG_FORCE_TIMEOUT } coex_status_t; -#define BT_DHCP_OPPORTUNITY_WINDOW_TIEM 2500 -#define BT_DHCP_FLAG_FORCE_TIME 5500 typedef struct bt_info { struct net_device *dev; struct timer_list timer; uint32 timer_ms; uint32 timer_on; - int bt_state; + bool dhcp_done; + int bt_state; - - long bt_pid; + long bt_pid; struct semaphore bt_sem; struct completion bt_exited; } bt_info_t; @@ -664,29 +668,34 @@ wl_iw_set_power_mode( int pm_local = PM_OFF; char powermode_val = 0; + WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra)); + strncpy((char *)&powermode_val, extra + strlen("POWERMODE") + 1, 1); if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)); dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); /* Disable packet filtering if necessary */ net_os_set_packet_filter(dev, 0); - } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { + g_bt->dhcp_done = false; + WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n", + __FUNCTION__, pm, pm_local)); - WL_TRACE(("%s: DHCP session done\n", __FUNCTION__)); + } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); /* Enable packet filtering if was turned off */ net_os_set_packet_filter(dev, 1); + g_bt->dhcp_done = true; + } else { - WL_ERROR(("Unkwown yet power setting, ignored\n")); + WL_ERROR(("%s Unkwown yet power setting, ignored\n", + __FUNCTION__)); } p += snprintf(p, MAX_WX_STRING, "OK"); @@ -697,6 +706,99 @@ wl_iw_set_power_mode( } #endif + +#if defined(BT_DHCP_eSCO_FIX) + +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) { + + WL_TRACE_COEX(("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_COEX(("%s saved bt_params[50,51,64,65,71]:" + " 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __FUNCTION__, saved_reg50, saved_reg51, + saved_reg64, saved_reg65, saved_reg71)); + + } else { + WL_ERROR((":%s: save btc_params failed\n", + __FUNCTION__)); + saved_status = false; + return -1; + } + + WL_TRACE_COEX(("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) { + + WL_TRACE_COEX(("Do new SCO/eSCO coex algo {save & override} \n")); + + regaddr = 50; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg50); + regaddr = 51; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg51); + regaddr = 64; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg64); + regaddr = 65; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg65); + regaddr = 71; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg71); + + WL_TRACE_COEX(("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_ERROR((":%s att to restore not saved BTCOEX params\n", + __FUNCTION__)); + return -1; + } + return 0; +} +#endif + static int wl_iw_get_power_mode( struct net_device *dev, @@ -764,7 +866,7 @@ wl_iw_set_btcoex_dhcp( if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); + WL_TRACE_COEX(("%s: DHCP session start, cmd:%s\n", __FUNCTION__, extra)); if ((saved_status == FALSE) && #ifndef CUSTOMER_HW2 @@ -774,7 +876,7 @@ wl_iw_set_btcoex_dhcp( (!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", \ + WL_TRACE_COEX(("save regs {66,41,68} ->: 0x%x 0x%x 0x%x\n", \ saved_reg66, saved_reg41, saved_reg68)); #ifndef CUSTOMER_HW2 @@ -796,7 +898,7 @@ wl_iw_set_btcoex_dhcp( g_bt->bt_state = BT_DHCP_START; g_bt->timer_on = 1; mod_timer(&g_bt->timer, g_bt->timer.expires); - WL_TRACE(("%s enable BT DHCP Timer\n", \ + WL_TRACE_COEX(("%s enable BT DHCP Timer\n", \ __FUNCTION__)); #ifndef CUSTOMER_HW2 } @@ -812,16 +914,22 @@ wl_iw_set_btcoex_dhcp( #else else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { #endif - WL_TRACE(("%s: DHCP session done\n", __FUNCTION__)); #ifndef CUSTOMER_HW2 dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); #endif - WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); + WL_TRACE_COEX(("%s disable BT DHCP Timer\n", __FUNCTION__)); if (g_bt->timer_on) { g_bt->timer_on = 0; del_timer_sync(&g_bt->timer); + + if (g_bt->bt_state != BT_DHCP_IDLE) { + WL_TRACE_COEX(("%s bt->bt_state:%d\n", + __FUNCTION__, g_bt->bt_state)); + + up(&g_bt->bt_sem); + } } dev_wlc_bufvar_set(dev, "btc_flags", \ @@ -837,11 +945,15 @@ wl_iw_set_btcoex_dhcp( regaddr = 68; dev_wlc_intvar_set_reg(dev, "btc_params", \ (char *)®addr, (char *)&saved_reg68); + + WL_TRACE_COEX(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", \ + saved_reg66, saved_reg41, saved_reg68)); } saved_status = FALSE; } else { - WL_ERROR(("Unkwown yet power setting, ignored\n")); + WL_ERROR(("%s Unkwown yet power setting, ignored\n", + __FUNCTION__)); } p += snprintf(p, MAX_WX_STRING, "OK"); @@ -1063,7 +1175,6 @@ wl_iw_set_band( if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { - if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND, &band, sizeof(band))) >= 0) { p += snprintf(p, MAX_WX_STRING, "OK"); @@ -7611,13 +7722,21 @@ wl_iw_bt_flag_set( 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 (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_lock(); #endif +#if defined(BT_DHCP_eSCO_FIX) + set_btc_esco_params(dev, set); +#endif + +#if defined(BT_DHCP_USE_FLAGS) + WL_TRACE_COEX(("WI-FI priority boost via bt flags, set:%d\n", set)); if (set == TRUE) { dev_wlc_bufvar_set(dev, "btc_flags", (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on)); @@ -7626,6 +7745,7 @@ wl_iw_bt_flag_set( dev_wlc_bufvar_set(dev, "btc_flags", (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); } +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) rtnl_unlock(); @@ -7658,14 +7778,23 @@ _bt_dhcp_sysioc_thread(void *data) switch (g_bt->bt_state) { case BT_DHCP_START: + WL_TRACE_COEX(("%s bt_dhcp stm: started \n", __FUNCTION__)); g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW; - mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000); + mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIME*HZ/1000); g_bt->timer_on = 1; break; case BT_DHCP_OPPORTUNITY_WINDOW: - WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \ - __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM)); + if (g_bt->dhcp_done) { + WL_TRACE_COEX(("%s DHCP Done before T1 expiration\n", \ + __FUNCTION__)); + g_bt->bt_state = BT_DHCP_IDLE; + g_bt->timer_on = 0; + break; + } + + WL_TRACE_COEX(("%s DHCP T1:%d expired\n", \ + __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIME)); if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE); g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); @@ -7673,9 +7802,14 @@ _bt_dhcp_sysioc_thread(void *data) break; case BT_DHCP_FLAG_FORCE_TIMEOUT: - WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \ + if (g_bt->dhcp_done) { + WL_TRACE_COEX(("%s DHCP Done before T2 expiration\n", \ + __FUNCTION__)); + } else { + WL_TRACE_COEX(("%s DHCP wait interval T2:%d msec expired\n", __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME)); - + } + if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE); g_bt->bt_state = BT_DHCP_IDLE; g_bt->timer_on = 0; |