diff options
author | Dmitry Shmidt <dimitrysh@google.com> | 2013-05-10 12:20:18 -0700 |
---|---|---|
committer | Ziyan <jaraidaniel@gmail.com> | 2016-05-01 23:35:18 +0200 |
commit | 627a4c370d44dfa61eaf7c851603e4aea12cddea (patch) | |
tree | c19473ec5925a89c861bba260b7b325df57366b2 /drivers | |
parent | 5be65b955278956db4cb99f58b5a3309864480f1 (diff) | |
download | kernel_samsung_tuna-627a4c370d44dfa61eaf7c851603e4aea12cddea.zip kernel_samsung_tuna-627a4c370d44dfa61eaf7c851603e4aea12cddea.tar.gz kernel_samsung_tuna-627a4c370d44dfa61eaf7c851603e4aea12cddea.tar.bz2 |
net: wireless: bcmdhd: Update to version 1.88.16
- Change the logic to enable Power save mode for STA or P2P GC
- Fix protxstatus bug for corner case
- Reset uninitialized value for mac entry
- Remove dhd_wlfc_init/deinit in wl_android.c
- Fix IBSS mode
Change-Id: I4589e87eda456798eae48548261a1f7cb9542660
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_cdc.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_linux.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_sdio.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/dhd_wlfc.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/include/epivers.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_android.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.c | 185 | ||||
-rw-r--r-- | drivers/net/wireless/bcmdhd/wl_cfg80211.h | 6 |
9 files changed, 196 insertions, 65 deletions
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 290fc31..9249f0b 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,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.h 393288 2013-03-27 01:02:25Z $ + * $Id: dhd.h 397286 2013-04-18 01:42:19Z $ */ /**************** @@ -478,6 +478,9 @@ extern void dhd_free(dhd_pub_t *dhdp); /* Indication from bus module to change flow-control state */ extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on); +/* Store the status of a connection attempt for later retrieval by an iovar */ +extern void dhd_store_conn_status(uint32 event, uint32 status, uint32 reason); + extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); /* Receive frame for delivery to OS. Callee disposes of rxp. */ @@ -588,6 +591,7 @@ extern int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void * extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uint8 set, int ifindex); extern void dhd_common_init(osl_t *osh); +extern void dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn); extern int dhd_do_driver_init(struct net_device *net); extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index dc7a668..f341a1f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.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: dhd_cdc.c 393623 2013-03-28 06:27:09Z $ + * $Id: dhd_cdc.c 401089 2013-05-08 18:17:31Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -558,11 +558,6 @@ dhd_prot_init(dhd_pub_t *dhd) if (dhd_download_fw_on_driverload) #endif /* defined(WL_CFG80211) */ ret = dhd_preinit_ioctls(dhd); - -#ifdef PROP_TXSTATUS - ret = dhd_wlfc_init(dhd); -#endif - /* Always assumes wl for now */ dhd->iswl = TRUE; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index b47ff7e..f5506a4 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 397043 2013-04-17 02:56:29Z $ + * $Id: dhd_linux.c 401270 2013-05-09 11:58:40Z $ */ #include <typedefs.h> @@ -3825,6 +3825,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_DISASSOC_IND); setbit(eventmask, WLC_E_DISASSOC); setbit(eventmask, WLC_E_JOIN); + setbit(eventmask, WLC_E_START); setbit(eventmask, WLC_E_ASSOC_IND); setbit(eventmask, WLC_E_PSK_SUP); setbit(eventmask, WLC_E_LINK); @@ -3918,6 +3919,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DISABLE_11N */ +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_init(dhd); +#endif /* PROP_TXSTATUS && !PROP_TXSTATUS_VSDB */ + /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); ptr = buf; @@ -5022,6 +5027,9 @@ dhd_dev_reset(struct net_device *dev, uint8 flag) if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) { DHD_TRACE(("%s: wl down failed\n", __FUNCTION__)); } +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_deinit(&dhd->pub); +#endif /* PROP_TXSTATUS && !PROP_TXSTATUS_VSDB */ } ret = dhd_bus_devreset(&dhd->pub, flag); diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 64c8dfe..ad3ee95 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.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: dhd_sdio.c 392661 2013-03-22 23:17:02Z $ + * $Id: dhd_sdio.c 399337 2013-04-29 23:39:03Z $ */ #include <typedefs.h> @@ -5797,7 +5797,7 @@ dhdsdio_isr(void *arg) #if defined(SDIO_ISR_THREAD) DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); DHD_OS_WAKE_LOCK(bus->dhd); - while (dhdsdio_dpc(bus)); + dhdsdio_dpc(bus); DHD_OS_WAKE_UNLOCK(bus->dhd); #else diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.c b/drivers/net/wireless/bcmdhd/dhd_wlfc.c index 540b8d8..9533856 100644 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.c +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.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: dhd_wlfc.c 395161 2013-04-05 13:19:38Z $ + * $Id: dhd_wlfc.c 400998 2013-05-08 09:04:02Z $ * */ @@ -1186,6 +1186,10 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* entry->suppressed = 0; entry->state = WLFC_STATE_CLOSE; entry->requested_credit = 0; + entry->transit_count = 0; + entry->suppr_transit_count = 0; + entry->suppress_count = 0; + memset(&entry->ea[0], 0, ETHER_ADDR_LEN); /* enable after packets are queued-deqeued properly. pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); @@ -1304,7 +1308,6 @@ _dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, return rc; } - int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf) { @@ -1375,7 +1378,7 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, vo for (ac = AC_COUNT; ac >= 0; ac--) { - int initial_credit_count = ctx->FIFO_credit[ac]; + bool bQueueIdle = TRUE; /* packets from delayQ with less priority are fresh and they'd need header and * have no MAC entry @@ -1393,6 +1396,8 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, vo if (commit_info.p == NULL) break; + bQueueIdle = FALSE; + commit_info.pkt_type = (commit_info.needs_hdr) ? eWLFC_PKTTYPE_DELAYED : eWLFC_PKTTYPE_SUPPRESSED; @@ -1418,10 +1423,8 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, vo ctx->FIFO_credit[ac] -= credit; - /* If no credits were used, the queue is idle and can be re-used - Note that resv credits cannot be borrowed - */ - if (initial_credit_count == ctx->FIFO_credit[ac]) { + /* If no pkts can be dequed, the credit can be borrowed */ + if (bQueueIdle) { ac_available |= (1 << ac); credit_count += ctx->FIFO_credit[ac]; } diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 7e96ec8..d2c5388 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -30,26 +30,26 @@ #define EPI_MINOR_VERSION 88 -#define EPI_RC_NUMBER 11 +#define EPI_RC_NUMBER 16 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 88, 11, 0 +#define EPI_VERSION 1, 88, 16, 0 -#define EPI_VERSION_NUM 0x01580b00 +#define EPI_VERSION_NUM 0x01581000 -#define EPI_VERSION_DEV 1.88.11 +#define EPI_VERSION_DEV 1.88.16 /* Driver Version String, ASCII, 32 chars max */ #ifdef BCMINTERNAL -#define EPI_VERSION_STR "1.88.11 (r BCMINT)" +#define EPI_VERSION_STR "1.88.16 (r BCMINT)" #else #ifdef WLTEST -#define EPI_VERSION_STR "1.88.11 (r WLTEST)" +#define EPI_VERSION_STR "1.88.16 (r WLTEST)" #else -#define EPI_VERSION_STR "1.88.11 (r)" +#define EPI_VERSION_STR "1.88.16 (r)" #endif #endif /* BCMINTERNAL */ diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 935397f..68fb212 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.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_android.c 397123 2013-04-17 08:59:26Z $ + * $Id: wl_android.c 399333 2013-04-29 23:26:59Z $ */ #include <linux/module.h> @@ -168,10 +168,6 @@ extern int dhd_os_check_if_up(void *dhdp); #ifdef BCMLXSDMMC extern void *bcmsdh_get_drvdata(void); #endif /* BCMLXSDMMC */ -#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) -extern int dhd_wlfc_init(dhd_pub_t *dhd); -extern void dhd_wlfc_deinit(dhd_pub_t *dhd); -#endif #ifdef ENABLE_4335BT_WAR @@ -455,9 +451,6 @@ int wl_android_wifi_on(struct net_device *dev) if (dhd_dev_init_ioctl(dev) < 0) ret = -EFAULT; } -#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) && defined(BCMLXSDMMC) - dhd_wlfc_init(bcmsdh_get_drvdata()); -#endif g_wifi_on = TRUE; } @@ -479,9 +472,6 @@ int wl_android_wifi_off(struct net_device *dev) dhd_net_if_lock(dev); if (g_wifi_on) { -#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) && defined(BCMLXSDMMC) - dhd_wlfc_deinit(bcmsdh_get_drvdata()); -#endif ret = dhd_dev_reset(dev, TRUE); sdioh_stop(NULL); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index e4c5259..47751c0 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.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_cfg80211.c 396645 2013-04-15 06:51:13Z $ + * $Id: wl_cfg80211.c 401050 2013-05-08 13:36:28Z $ */ #include <typedefs.h> #include <linuxver.h> @@ -202,8 +202,7 @@ static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code); static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, - enum nl80211_tx_power_setting type, - s32 dbm); + enum nl80211_tx_power_setting type, s32 dbm); static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm); static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, @@ -361,6 +360,7 @@ static void wl_cfg80211_work_handler(struct work_struct *work); static void wl_cfg80211_scan_supp_timerfunc(ulong data); #endif /* DHCP_SCAN_SUPPRESS */ +static void wl_cfg80211_work_handler(struct work_struct *work); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, struct key_params *params); @@ -1229,6 +1229,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) } wldev_iovar_setint(dev, "mpc", 1); + if (wl->pm_enable_work_on) { + cancel_delayed_work_sync(&wl->pm_enable_work); + wl->pm_enable_work_on = false; + } + /* for GC */ if (wl_get_drv_status(wl, DISCONNECTING, dev) && (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) { @@ -1297,8 +1302,10 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, { s32 ap = 0; s32 infra = 0; + s32 ibss = 0; s32 wlif_type; s32 mode = 0; + s32 err = BCME_OK; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); @@ -1313,6 +1320,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, break; case NL80211_IFTYPE_ADHOC: mode = WL_MODE_IBSS; + ibss = 1; break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: @@ -1376,6 +1384,16 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA")); } + if (ibss) { + infra = 0; + wl_set_mode_by_netdev(wl, ndev, mode); + err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true); + if (err < 0) { + WL_ERR(("SET Adhoc error %d\n", err)); + return -EINVAL; + } + } + ndev->ieee80211_ptr->iftype = type; return 0; } @@ -3029,7 +3047,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy, u16 txpwrmw; s32 err = 0; s32 disable = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS) dbm = MBM_TO_DBM(dbm); #endif @@ -3570,12 +3588,24 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); #endif RETURN_EIO_IF_NOT_UP(wl); - - if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode) { + WL_DBG(("Enter\n")); +#if defined(WL_ENABLE_P2P_IF) + if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode || + !wl_get_drv_status(wl, CONNECTED, dev)) { +#else + if (_net_info == NULL || wl->vsdb_mode || + !wl_get_drv_status(wl, CONNECTED, dev)) { +#endif /* WL_ENABLE_P2P_IF */ return err; } WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled)); + /* Delete pm_enable_work */ + if (wl->pm_enable_work_on) { + cancel_delayed_work_sync(&wl->pm_enable_work); + wl->pm_enable_work_on = false; + } + #if !defined(SUPPORT_PM2_ONLY) /* android has special hooks to change pm when kernel suspended */ pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; @@ -3583,9 +3613,8 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, pm = enabled ? PM_FAST : PM_OFF; #endif /* SUPPORT_PM2_ONLY */ if (_net_info->pm_block) { - /* Do not enable the power save if it is p2p interface or vsdb mode is set */ - WL_DBG(("%s:Do not enable the power save for pm_block %d or vsdb_mode %d\n", - dev->name, _net_info->pm_block, wl->vsdb_mode)); + WL_ERR(("%s:Do not enable the power save for pm_block %d\n", + dev->name, _net_info->pm_block)); pm = PM_OFF; } pm = htod32(pm); @@ -6053,6 +6082,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev #endif /* WL_SCHED_SCAN */ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC) #if !defined(WL_ENABLE_P2P_IF) | BIT(NL80211_IFTYPE_MONITOR) #endif /* !WL_ENABLE_P2P_IF */ @@ -6245,7 +6275,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 i offsetof(struct wl_cfg80211_bss_info, frame_buf)); notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.beacon.variable) + wl_get_ielen(wl); -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) freq = ieee80211_channel_to_frequency(notif_bss_info->channel); (void)band->band; #else @@ -6552,7 +6582,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { wl_notify_connect_status_ap(wl, ndev, e, data); - } else { + } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", ntoh32(e->event_type), ntoh32(e->status), ndev)); if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { @@ -6562,20 +6592,13 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; - if (wl_is_ibssmode(wl, ndev)) { - printk("cfg80211_ibss_joined\n"); - cfg80211_ibss_joined(ndev, (s8 *)&e->addr, - GFP_KERNEL); - WL_DBG(("joined in IBSS network\n")); - } else { - if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { + if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { printk("wl_bss_connect_done succeeded with " MACDBG "\n", MAC2STRDBG((u8*)(&e->addr))); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); - } } wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); @@ -6659,7 +6682,38 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_get_drv_status(wl, CONNECTING, ndev)) wl_bss_connect_done(wl, ndev, e, data, false); } else { - printk("%s nothing\n", __FUNCTION__); + WL_DBG(("%s nothing\n", __FUNCTION__)); + } + } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) { + u16 flags = ntoh16(e->flags); + u32 status = ntoh32(e->status); + struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); + + if (event == WLC_E_JOIN) { + WL_DBG(("joined in IBSS network\n")); + } + if (event == WLC_E_START) { + WL_DBG(("started IBSS network\n")); + } + if (event == WLC_E_JOIN || event == WLC_E_START) { + wl_link_up(wl); + wl_get_assoc_ies(wl, ndev); + wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); + wl_update_bss_info(wl, ndev, 1); + cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL); + wl_set_drv_status(wl, CONNECTED, ndev); + profile->active = true; + } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) || + event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) { + wl_clr_drv_status(wl, CONNECTED, ndev); + wl_link_down(wl); + wl_init_prof(wl, ndev); + } + else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) { + WL_DBG(("no action - join fail (IBSS mode)\n")); + } + else { + WL_DBG(("no action (IBSS mode)\n")); } } return err; @@ -6805,9 +6859,6 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is wiphy = wl_to_wiphy(wl); - if (wl_is_ibssmode(wl, ndev)) - return err; - ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); bss = cfg80211_get_bss(wiphy, NULL, curbssid, @@ -7216,7 +7267,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, WL_ERR(("No valid band")); return -EINVAL; } -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) freq = ieee80211_channel_to_frequency(channel); (void)band->band; #else @@ -7502,6 +7553,8 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; + wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status; + wl->evt_handler[WLC_E_START] = wl_notify_connect_status; #ifdef PNO_SUPPORT wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; #endif /* PNO_SUPPORT */ @@ -8397,11 +8450,13 @@ static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl) } return; } + static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, enum wl_status state, bool set) { s32 pm = PM_FAST; s32 err = BCME_OK; + u32 mode; u32 chan = 0; struct net_info *iter, *next; struct net_device *primary_dev = wl_to_prmry_ndev(wl); @@ -8410,17 +8465,28 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in if (state != WL_STATUS_CONNECTED) return 0; - + mode = wl_get_mode_by_netdev(wl, _net_info->ndev); if (set) { wl_cfg80211_concurrent_roam(wl, 1); - if (wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) { + if (mode == WL_MODE_AP) { if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false)) WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); } wl_cfg80211_determine_vsdb_mode(wl); if (wl->vsdb_mode || _net_info->pm_block) { + if (wl->pm_enable_work_on) { + cancel_delayed_work_sync(&wl->pm_enable_work); + wl->pm_enable_work_on = false; + } + /* save PM_FAST in _net_info to restore this + * if _net_info->pm_block is false + */ + if (!_net_info->pm_block && (mode == WL_MODE_BSS)) { + _net_info->pm = PM_FAST; + _net_info->pm_restore = true; + } pm = PM_OFF; for_each_ndev(wl, iter, next) { if (iter->pm_restore) @@ -8442,9 +8508,33 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); else WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); + } else iter->ndev->ieee80211_ptr->ps = false; + } + } else { + /* add PM Enable timer to go to power save mode + * if supplicant control pm mode, it will be cleared or + * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P, + * PM will be configured when timer expired + */ + + /* + * before calling pm_enable_timer, we need to set PM -1 for all ndev + */ + pm = PM_OFF; + + for_each_ndev(wl, iter, next) { + if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, + sizeof(pm), true)) != 0) { + if (err == -ENODEV) + WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); + else + WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); } } + wl->pm_enable_work_on = true; + schedule_delayed_work(&wl->pm_enable_work, + msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT)); } } else { /* clear */ @@ -9194,7 +9284,7 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) else index = *n_cnt; if (index < array_size) { -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) band_chan_arr[index].center_freq = ieee80211_channel_to_frequency(channel); #else @@ -9391,7 +9481,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) wl->scan_supp_timer.function = wl_cfg80211_scan_supp_timerfunc; INIT_WORK(&wl->wlan_work, wl_cfg80211_work_handler); #endif /* DHCP_SCAN_SUPPRESS */ - + INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler); wl_set_drv_status(wl, READY, ndev); return err; } @@ -9404,6 +9494,10 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) struct net_device *ndev = wl_to_prmry_ndev(wl); u32 bssidx = 0; WL_DBG(("In\n")); + if (wl->pm_enable_work_on) { + cancel_delayed_work_sync(&wl->pm_enable_work); + wl->pm_enable_work_on = false; + } #if defined(DHCP_SCAN_SUPPRESS) /* Force clear of scan_suppress */ @@ -9781,7 +9875,7 @@ s32 wl_cfg80211_channel_to_freq(u32 channel) { int freq = 0; -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) freq = ieee80211_channel_to_frequency(channel); #else { @@ -10544,3 +10638,36 @@ int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress) return ret; } #endif /* DHCP_SCAN_SUPPRESS */ + +static void wl_cfg80211_work_handler(struct work_struct * work) +{ + struct wl_priv *wl = NULL; + struct net_info *iter, *next; + s32 err = BCME_OK; + s32 pm = PM_FAST; + + wl = container_of(work, struct wl_priv, pm_enable_work.work); + WL_DBG(("Enter \n")); + if (!wl) { + WL_ERR(("wl_priv ptr NULL")); + return; + } + if (wl->pm_enable_work_on) { + wl->pm_enable_work_on = false; + for_each_ndev(wl, iter, next) { + if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) || + (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS)) + continue; + if (iter->ndev) { + if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, + &pm, sizeof(pm), true)) != 0) { + if (err == -ENODEV) + WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); + else + WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); + } else + iter->ndev->ieee80211_ptr->ps = true; + } + } + } +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 8840b20..61e1c09 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -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_cfg80211.h 389705 2013-03-07 20:04:22Z $ + * $Id: wl_cfg80211.h 401050 2013-05-08 13:36:28Z $ */ #ifndef _wl_cfg80211_h_ @@ -172,6 +172,8 @@ do { \ #define WL_SCAN_SUPPRESS_TIMEOUT 31000 /* default Framwork DHCP timeout is 30 sec */ #define WL_SCAN_SUPPRESS_RETRY 3000 +#define WL_PM_ENABLE_TIMEOUT 3000 + /* driver status */ enum wl_status { WL_STATUS_READY = 0, @@ -578,6 +580,8 @@ struct wl_priv { struct timer_list scan_supp_timer; struct work_struct wlan_work; struct mutex event_sync; /* maily for up/down synchronization */ + bool pm_enable_work_on; + struct delayed_work pm_enable_work; }; |