From 9e9fc857c69f3777276420a2d5d747bfa2c3693f Mon Sep 17 00:00:00 2001 From: Greg Goldman Date: Sun, 9 Oct 2011 02:32:48 +0100 Subject: net: wireless: bcmdhd: Update to 5.90.125.69 Change-Id: I25a516ca4d8f5edc72a2a54e420f5e1b4fe3aa16 Signed-off-by: Howard M. Harte Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 2 +- drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 9 --- drivers/net/wireless/bcmdhd/dhd.h | 1 + drivers/net/wireless/bcmdhd/dhd_bus.h | 5 ++ drivers/net/wireless/bcmdhd/dhd_cdc.c | 50 ++----------- drivers/net/wireless/bcmdhd/dhd_common.c | 38 +++++++++- drivers/net/wireless/bcmdhd/dhd_linux.c | 7 +- drivers/net/wireless/bcmdhd/dhd_linux_mon.c | 4 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 6 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +-- drivers/net/wireless/bcmdhd/include/sdio.h | 5 ++ drivers/net/wireless/bcmdhd/include/wlioctl.h | 5 ++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 83 ++++++++++++++------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 1 + drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 14 ++-- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 1 + drivers/net/wireless/bcmdhd/wl_iw.c | 100 ++++++++++++++++---------- 17 files changed, 203 insertions(+), 136 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 56500b7220c..e82c9856f00 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -1,5 +1,5 @@ # bcmdhd -DHDCFLAGS = -Wall -Wstrict-prototypes -Werror -Dlinux -DBCMDRIVER \ +DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DWLBTAMP -DBCMFILEIMAGE \ -DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DDHD_DEBUG -DSDTEST -DBDC -DTOE \ -DDHD_BCMEVENTS -DSHOW_EVENTS -DDONGLEOVERLAYS -DBCMDBG \ diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index 6fa47378cfe..a4dc6ff4042 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -48,15 +48,6 @@ extern void dhdsdio_isr(void * args); #include #include #endif /* defined(OOB_INTR_ONLY) */ -#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270) -#if !defined(BCMPLATFORM_BUS) -#define BCMPLATFORM_BUS -#endif /* !defined(BCMPLATFORM_BUS) */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) -#include -#endif /* KERNEL_VERSION(2, 6, 19) */ -#endif /* CONFIG_MACH_SANDGATE2G || CONFIG_MACH_LOGICPD_PXA270 */ /** * SDIO Host Controller info diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index b0df6c77200..281e047af85 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -430,6 +430,7 @@ extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); extern int dhd_timeout_expired(dhd_timeout_t *tmo); extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); +extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); extern struct net_device * dhd_idx2net(struct dhd_pub *dhd_pub, int ifidx); extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, wl_event_msg_t *, void **data_ptr); diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h index 294322026e9..bccb8b6603f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bus.h +++ b/drivers/net/wireless/bcmdhd/dhd_bus.h @@ -48,6 +48,11 @@ extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex); /* Initialize bus module: prepare for communication w/dongle */ extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex); +/* Get the Bus Idle Time */ +extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime); + +/* Set the Bus Idle Time*/ +extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time); /* Send a data frame to the dongle. Callee disposes of txp. */ extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp); diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index fde8a35f289..0f9893a1537 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -916,7 +916,10 @@ _dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descript #ifdef PROP_TXSTATUS_DEBUG ctx->stats.signal_only_pkts_sent++; #endif - dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p); + rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p); + if (rc != BCME_OK) { + PKTFREE(ctx->osh, p, TRUE); + } } else { DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n", @@ -2236,49 +2239,6 @@ dhd_prot_dstats(dhd_pub_t *dhd) return; } -int dhd_set_suspend(int value, dhd_pub_t *dhd) -{ - int power_mode = PM_MAX; - wl_pkt_filter_enable_t enable_parm; - char iovbuf[32]; - int bcn_li_dtim = 3; - -#define htod32(i) i - - if (dhd && dhd->up) { - if (value) { - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, - (char *)&power_mode, sizeof(power_mode), TRUE, 0); - /* Enable packet filter, only allow unicast packet to send up */ - enable_parm.id = htod32(100); - enable_parm.enable = htod32(1); - bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, - sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* set bcn_li_dtim */ - 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); - } else { - power_mode = PM_FAST; - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); - /* disable pkt filter */ - enable_parm.id = htod32(100); - enable_parm.enable = htod32(0); - bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, - sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* set bcn_li_dtim */ - bcn_li_dtim = 0; - 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); - } - } - - return 0; -} int dhd_prot_init(dhd_pub_t *dhd) @@ -2300,7 +2260,9 @@ dhd_prot_init(dhd_pub_t *dhd) ret = dhd_wlfc_init(dhd); #endif +#ifndef WL_CFG80211 ret = dhd_preinit_ioctls(dhd); +#endif /* WL_CFG80211 */ /* Always assumes wl for now */ dhd->iswl = TRUE; diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 66d60420069..f6bb8e5bb56 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -70,6 +70,7 @@ char nv_path[MOD_PARAM_PATHLEN]; #ifdef SOFTAP char fw_path2[MOD_PARAM_PATHLEN]; +extern bool softap_enabled; #endif /* Last connection success/failure status */ @@ -1534,7 +1535,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint32 glom = 0; uint bcn_timeout = 4; uint retry_max = 3; +#if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; +#endif int scan_assoc_time = 40; int scan_unassoc_time = 40; const char *str; @@ -1589,7 +1592,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef SET_RANDOM_MAC_SOFTAP - if (strstr(fw_path, "apsta") != NULL) { + if (strstr(fw_path, "_apsta") != NULL) { uint rand_mac; srandom32((uint)jiffies); @@ -1610,6 +1613,7 @@ 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 (strstr(fw_path, "_p2p") != NULL) { @@ -1619,7 +1623,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= WFD_MASK; +#if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; +#endif /* (ARP_OFFLOAD_SUPPORT) */ + dhd_pkt_filter_enable = FALSE; } } #endif /* !defined(AP) && defined(WLP2P) */ @@ -1634,10 +1641,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= HOSTAPD_MASK; +#if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; +#endif /* (ARP_OFFLOAD_SUPPORT) */ + dhd_pkt_filter_enable = FALSE; } } #endif /* !defined(AP) && defined(WL_CFG80211) */ + + 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; + } DHD_ERROR(("Firmware up: op_mode=%d, " "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", dhd->op_mode, @@ -2089,6 +2105,17 @@ exit: return bcn_li_dtim; } +/* Check if HostAPD or WFD mode setup */ +bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) +{ +#ifdef WL_CFG80211 + if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) || + ((dhd->op_mode & WFD_MASK) == WFD_MASK)) + return TRUE; + else +#endif /* WL_CFG80211 */ + return FALSE; +} #ifdef PNO_SUPPORT int @@ -2133,6 +2160,8 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (ret); memset(iovbuf, 0, sizeof(iovbuf)); /* Check if disassoc to enable pno */ if ((pfn_enabled) && @@ -2180,6 +2209,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, DHD_ERROR(("%s error exit\n", __FUNCTION__)); err = -1; } + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (err); /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { @@ -2296,7 +2327,10 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) int str_len; int res = -1; - DHD_ERROR(("%s Enter\n", __FUNCTION__)); + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (res); + + DHD_TRACE(("%s execution\n", __FUNCTION__)); str = "mkeep_alive"; str_len = strlen(str); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index d07b3ca9e33..03ba34a2c82 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -671,7 +671,7 @@ dhd_timeout_expired(dhd_timeout_t *tmo) return 0; } -static int +int dhd_net2idx(dhd_info_t *dhd, struct net_device *net) { int i = 0; @@ -1022,10 +1022,10 @@ dhd_op_if(dhd_if_t *ifp) free_netdev(ifp->net); } dhd->iflist[ifp->idx] = NULL; - MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); #ifdef WL_CFG80211 - if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { wl_cfg80211_notify_ifdel(ifp->net); + } #endif #ifdef SOFTAP flags = dhd_os_spin_lock(&dhd->pub); @@ -1033,6 +1033,7 @@ dhd_op_if(dhd_if_t *ifp) 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)); } } diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c index 6c1ff4d8ad4..dd9c71f75be 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c @@ -106,8 +106,10 @@ static struct net_device* lookup_real_netdev(char *name) for (i = 0; i < DHD_MAX_IFS; i++) { ndev = dhd_idx2net(g_monitor.dhd_pub, i); if (ndev && strstr(name, ndev->name)) { - if (strlen(ndev->name) > last_name_len) + if (strlen(ndev->name) > last_name_len) { ndev_found = ndev; + last_name_len = strlen(ndev->name); + } } } diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 50bc7e4190d..6d89f6b984a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -77,11 +77,7 @@ #define TXRETRIES 2 /* # of retries for tx frames */ -#if defined(CONFIG_MACH_SANDGATE2G) -#define DHD_RXBOUND 250 /* Default for max rx frames in one scheduling */ -#else #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ -#endif /* defined(CONFIG_MACH_SANDGATE2G) */ #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ @@ -1846,6 +1842,8 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh) sh->console_addr = ltoh32(sh->console_addr); sh->msgtrace_addr = ltoh32(sh->msgtrace_addr); + if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1) + return BCME_OK; if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { DHD_ERROR(("%s: sdpcm_shared version %d in dhd " "is different than sdpcm_shared version %d in dongle\n", diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 30ef842fcbe..f474dfa482a 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 125 -#define EPI_INCREMENTAL_NUMBER 65 +#define EPI_INCREMENTAL_NUMBER 69 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 125, 65 +#define EPI_VERSION 5, 90, 125, 69 -#define EPI_VERSION_NUM 0x055a7d41 +#define EPI_VERSION_NUM 0x055a7d45 #define EPI_VERSION_DEV 5.90.125 -#define EPI_VERSION_STR "5.90.125.65" +#define EPI_VERSION_STR "5.90.125.69" #endif diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h index 7e94e7df13c..ca932266a1b 100644 --- a/drivers/net/wireless/bcmdhd/include/sdio.h +++ b/drivers/net/wireless/bcmdhd/include/sdio.h @@ -376,6 +376,7 @@ typedef volatile struct { #define SDIOH_CMD_5 5 #define SDIOH_CMD_7 7 #define SDIOH_CMD_11 11 +#define SDIOH_CMD_14 14 #define SDIOH_CMD_15 15 #define SDIOH_CMD_19 19 #define SDIOH_CMD_52 52 @@ -411,6 +412,10 @@ typedef volatile struct { #define CMD7_RCA_M BITFIELD_MASK(16) #define CMD7_RCA_S 16 +#define CMD14_RCA_M BITFIELD_MASK(16) +#define CMD14_RCA_S 16 +#define CMD14_SLEEP_M BITFIELD_MASK(1) +#define CMD14_SLEEP_S 15 #define CMD_15_RCA_M BITFIELD_MASK(16) #define CMD_15_RCA_S 16 diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index a09dd269264..1059de147ef 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -555,6 +555,7 @@ typedef enum sup_auth_status { #define CRYPTO_ALGO_AES_OCB_MSDU 5 #define CRYPTO_ALGO_AES_OCB_MPDU 6 #define CRYPTO_ALGO_NALG 7 +#define CRYPTO_ALGO_PMK 12 #define WSEC_GEN_MIC_ERROR 0x0001 #define WSEC_GEN_REPLAY 0x0002 @@ -616,6 +617,9 @@ typedef struct { #define WPA2_AUTH_PSK 0x0080 #define BRCM_AUTH_PSK 0x0100 #define BRCM_AUTH_DPT 0x0200 +#define WPA2_AUTH_MFP 0x1000 +#define WPA2_AUTH_TPK 0x2000 +#define WPA2_AUTH_FT 0x4000 #define MAXPMKID 16 @@ -1499,6 +1503,7 @@ typedef struct wl_sampledata { #define WL_JOIN_PREF_WPA 2 #define WL_JOIN_PREF_BAND 3 #define WL_JOIN_PREF_RSSI_DELTA 4 +#define WL_JOIN_PREF_TRANS_PREF 5 #define WLJP_BAND_ASSOC_PREF 255 diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index b2861f49221..09529136787 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -874,7 +874,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOMEM); } vwdev->wiphy = wl->wdev->wiphy; - WL_INFO((" virtual interface(%s) is created \n", wl->p2p->vir_ifname)); + WL_INFO((" virtual interface(%s) is created memalloc done \n", + wl->p2p->vir_ifname)); index = alloc_idx_vwdev(wl); wl->vwdev[index] = vwdev; vwdev->iftype = @@ -891,7 +892,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, rtnl_unlock(); if (net_attach && !net_attach(dhd, _ndev->ifindex)) WL_DBG((" virtual interface(%s) is " - "created\n", wl->p2p->vir_ifname)); + "created net attach done\n", wl->p2p->vir_ifname)); else { rtnl_lock(); goto fail; @@ -918,6 +919,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) struct wl_priv *wl = wiphy_priv(wiphy); s32 timeout = -1; s32 ret = 0; + WL_DBG(("Enter\n")); if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); if (wl->p2p->vif_created) { @@ -925,8 +927,17 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) wl_cfg80211_scan_abort(wl, dev); } - wl_cfgp2p_ifdel(wl, &p2p_mac); + ret = wl_cfgp2p_ifdel(wl, &p2p_mac); wl_set_p2p_status(wl, IF_DELETING); + if (ret) { + /* Firmware could not delete the interface so we will not get WLC_E_IF event for cleaning the dhd virtual nw interace + * So lets do it here. Failures from fw will ensure the application to do ifconfig down and up sequnce, which will reload the fw + * however we should cleanup the linux network virtual interfaces + */ + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + WL_ERR(("Firmware returned an error from p2p_ifdel, try to remove linux virtual network interface dev->name %s\n", dev->name)); + dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev)); + } /* Wait for any pending scan req to get aborted from the sysioc context */ timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, @@ -1082,8 +1093,8 @@ wl_cfg80211_notify_ifdel(struct net_device *net) if (wl->p2p->vif_created) { s32 index = 0; - WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n", - net->name, wl->p2p->vir_ifname)); + WL_DBG(("IF_DEL event called from dongle, net %x, vif name: %s\n", + (unsigned int)net, wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); index = wl_cfgp2p_find_idx(wl, net); @@ -2220,12 +2231,20 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); act = *(bool *) wl_read_prof(wl, WL_PROF_ACT); if (likely(act)) { + /* + * Cancel ongoing scan to sync up with sme state machine of cfg80211. + */ + if (wl->scan_request) { + wl_cfg80211_scan_abort(wl, dev); + } + wl_set_drv_status(wl, DISCONNECTING); scbval.val = reason_code; memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN); scbval.val = htod32(scbval.val); err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), false); if (unlikely(err)) { + wl_clr_drv_status(wl, DISCONNECTING); WL_ERR(("error (%d)\n", err)); return err; } @@ -2710,6 +2729,11 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); pm = enabled ? PM_FAST : PM_OFF; + /* Do not enable the power save after assoc if it is p2p interface */ + if (wl->p2p && wl->p2p->vif_created) { + WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n")); + pm = PM_OFF; + } pm = htod32(pm); WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), false); @@ -3616,7 +3640,10 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, wldev_iovar_setint(dev, "mpc", 0); wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), false); wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false); - wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false); + if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false)) < 0) { + WL_ERR(("setting AP mode failed %d \n", err)); + return err; + } /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, DOT11_MNG_RSN_ID)) != NULL) { @@ -4188,21 +4215,30 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, ntoh32(e->event_type), ntoh32(e->status))); if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); + act = true; + wl_update_prof(wl, e, &act, WL_PROF_ACT); if (wl_is_ibssmode(wl, ndev)) { printk("cfg80211_ibss_joined"); cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL); WL_DBG(("joined in IBSS network\n")); } else { - printk("wl_bss_connect_done succeeded"); - wl_bss_connect_done(wl, ndev, e, data, true); - WL_DBG(("joined in BSS network \"%s\"\n", + if (!wl_get_drv_status(wl, DISCONNECTING)) { + printk("wl_bss_connect_done succeeded"); + wl_bss_connect_done(wl, ndev, e, data, true); + WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) wl_read_prof(wl, WL_PROF_SSID))->SSID)); + } } - act = true; - wl_update_prof(wl, e, &act, WL_PROF_ACT); + } else if (wl_is_linkdown(wl, e)) { + if (wl->scan_request) { + if (wl->escan_on) { + wl_notify_escan_complete(wl, true); + } else + wl_iscan_aborted(wl); + } if (wl_get_drv_status(wl, CONNECTED)) { printk("link down, call cfg80211_disconnected "); wl_clr_drv_status(wl, CONNECTED); @@ -4213,9 +4249,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, printk("link down, during connecting"); wl_bss_connect_done(wl, ndev, e, data, false); } - if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, ndev); - } + wl_clr_drv_status(wl, DISCONNECTING); + } else if (wl_is_nonetwork(wl, e)) { printk("connect failed e->status 0x%x", (int)ntoh32(e->status)); if (wl_get_drv_status(wl, CONNECTING)) @@ -4498,7 +4533,9 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, s32 err = 0; WL_DBG((" enter\n")); - + if (wl->scan_request) { + wl_cfg80211_scan_abort(wl, ndev); + } if (wl_get_drv_status(wl, CONNECTING)) { wl_clr_drv_status(wl, CONNECTING); if (completed) { @@ -4506,6 +4543,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); + wl_set_drv_status(wl, CONNECTED); } cfg80211_connect_result(ndev, (u8 *)&wl->bssid, @@ -4518,14 +4556,6 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG(("Report connect result - connection %s\n", completed ? "succeeded" : "failed")); } - if (completed) - wl_set_drv_status(wl, CONNECTED); - else { - if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, ndev); - } - } - return err; } @@ -5085,6 +5115,7 @@ static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted) if (unlikely(!wl_get_drv_status(wl, SCANNING))) { wl_clr_drv_status(wl, SCANNING); WL_ERR(("Scan complete while device not scanning\n")); + wl->scan_request = NULL; return; } wl_clr_drv_status(wl, SCANNING); @@ -5191,7 +5222,9 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; if (likely(wl->scan_request)) { rtnl_lock(); - WL_INFO(("ESCAN COMPLETED\n")); + WL_INFO(("ESCAN ABORTED\n")); + wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; + wl_inform_bss(wl); wl_notify_escan_complete(wl, true); rtnl_unlock(); } @@ -6040,7 +6073,6 @@ static s32 wl_update_wiphybands(struct wl_priv *wl) } phy = phylist_buf; for (; *phy; phy++) { - WL_ERR(("%c phy\n", *phy)); if (*phy == 'a' || *phy == 'n') { wiphy = wl_to_wiphy(wl); wiphy->bands[IEEE80211_BAND_5GHZ] = @@ -6087,6 +6119,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) wl_clr_drv_status(wl, SCAN_ABORTING); wl_clr_drv_status(wl, CONNECTING); wl_clr_drv_status(wl, CONNECTED); + wl_clr_drv_status(wl, DISCONNECTING); if (wl_get_drv_status(wl, AP_CREATED)) { wl_clr_drv_status(wl, AP_CREATED); wl_clr_drv_status(wl, AP_CREATING); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 8116d63d56e..a5637240c17 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -129,6 +129,7 @@ enum wl_status { WL_STATUS_SCAN_ABORTING, WL_STATUS_CONNECTING, WL_STATUS_CONNECTED, + WL_STATUS_DISCONNECTING, WL_STATUS_AP_CREATING, WL_STATUS_AP_CREATED }; diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 3d7b5484152..98271c28658 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -176,8 +176,8 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) s32 ret; struct net_device *netdev = wl_to_prmry_ndev(wl); - CFGP2P_INFO(("---wl p2p_ifdel %02x:%02x:%02x:%02x:%02x:%02x\n", - mac->octet[0], mac->octet[1], mac->octet[2], + CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel %02x:%02x:%02x:%02x:%02x:%02x\n", + netdev->ifindex, mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5])); ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), @@ -1047,10 +1047,13 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); - if (status == WLC_E_STATUS_SUCCESS) + if (status == WLC_E_STATUS_SUCCESS) { wl_set_p2p_status(wl, ACTION_TX_COMPLETED); - else + } + else { + wl_set_p2p_status(wl, ACTION_TX_NOACK); CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); + } wake_up_interruptible(&wl->dongle_event_wait); } else { CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," @@ -1081,6 +1084,7 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, af_params->channel, af_params->dwell_time)); wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); + wl_clr_p2p_status(wl, ACTION_TX_NOACK); #define MAX_WAIT_TIME 2000 if (bssidx == P2PAPI_BSSCFG_PRIMARY) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); @@ -1094,7 +1098,7 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, goto exit; } timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, - (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) == TRUE), + (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||wl_get_p2p_status(wl, ACTION_TX_NOACK)), msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index d62f5422708..b08504d8f95 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -88,6 +88,7 @@ enum wl_cfgp2p_status { WLP2P_STATUS_IF_CHANGED, WLP2P_STATUS_LISTEN_EXPIRED, WLP2P_STATUS_ACTION_TX_COMPLETED, + WLP2P_STATUS_ACTION_TX_NOACK, WLP2P_STATUS_SCANNING }; diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index ae28c6d0215..6d546fcd396 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -792,7 +792,7 @@ wl_iw_set_power_mode( #ifdef COEX_DHCP g_bt->ts_dhcp_start = JF2MS; - g_bt->dhcp_done = false; + g_bt->dhcp_done = FALSE; WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n", __FUNCTION__, pm, pm_local)); @@ -806,7 +806,7 @@ wl_iw_set_power_mode( net_os_set_packet_filter(dev, 1); #ifdef COEX_DHCP - g_bt->dhcp_done = true; + g_bt->dhcp_done = TRUE; g_bt->ts_dhcp_ok = JF2MS; WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n", __FUNCTION__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm)); @@ -828,7 +828,7 @@ wl_iw_set_power_mode( bool btcoex_is_sco_active(struct net_device *dev) { int ioc_res = 0; - bool res = false; + bool res = FALSE; int sco_id_cnt = 0; int param27; int i; @@ -852,7 +852,7 @@ bool btcoex_is_sco_active(struct net_device *dev) if (sco_id_cnt > 2) { WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", __FUNCTION__, sco_id_cnt, i)); - res = true; + res = TRUE; break; } @@ -866,7 +866,7 @@ bool btcoex_is_sco_active(struct net_device *dev) static int set_btc_esco_params(struct net_device *dev, bool trump_sco) { - static bool saved_status = false; + 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 }; @@ -902,7 +902,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco) } else { WL_ERROR((":%s: save btc_params failed\n", __FUNCTION__)); - saved_status = false; + saved_status = FALSE; return -1; } @@ -920,7 +920,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco) 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; + saved_status = TRUE; } else if (saved_status) { @@ -946,7 +946,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco) saved_reg50, saved_reg51, saved_reg64, saved_reg65, saved_reg71)); - saved_status = false; + saved_status = FALSE; } else { WL_ERROR((":%s att to restore not saved BTCOEX params\n", __FUNCTION__)); @@ -6320,12 +6320,12 @@ fail: #ifndef AP_ONLY static int last_auto_channel = 6; #endif + static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) { int chosen = 0; wl_uint32_list_t request; - int rescan = 0; int retry = 0; int updown = 0; int ret = 0; @@ -6354,42 +6354,57 @@ get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); ASSERT(iolen); res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen); + #endif - auto_channel_retry: - request.count = htod32(0); - ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request)); - if (ret < 0) { - WL_ERROR(("can't start auto channel scan\n")); - goto fail; - } + + request.count = htod32(0); + ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request)); + if (ret < 0) { + WL_ERROR(("can't start auto channel scan\n")); + goto fail; + } get_channel_retry: - bcm_mdelay(500); + bcm_mdelay(350); - ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen)); - if (ret < 0 || dtoh32(chosen) == 0) { - if (retry++ < 3) - goto get_channel_retry; - else { + ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen)); + if (ret < 0 || dtoh32(chosen) == 0) { + if (retry++ < 15) { + goto get_channel_retry; + } else { + if (ret < 0) { WL_ERROR(("can't get auto channel sel, err = %d, " - "chosen = %d\n", ret, chosen)); + "chosen = 0x%04X\n", ret, (uint16)chosen)); goto fail; + } else { + ap->channel = (uint16)last_auto_channel; + WL_ERROR(("auto channel sel timed out. we get channel %d\n", + ap->channel)); } } - if ((chosen == 1) && (!rescan++)) - goto auto_channel_retry; - WL_SOFTAP(("Set auto channel = %d\n", chosen)); - ap->channel = chosen; - if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) { - WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); - goto fail; - } + } + + if (chosen) { + ap->channel = (uint16)chosen & 0x00FF; + WL_SOFTAP(("%s: Got auto channel = %d, attempt:%d\n", + __FUNCTION__, ap->channel, retry)); + } + + if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) { + WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); + goto fail; + } + #ifndef AP_ONLY - if (!res) + if (!res || !ret) last_auto_channel = ap->channel; #endif fail : + if (ret < 0) { + WL_TRACE(("%s: return value %d\n", __FUNCTION__, ret)); + return ret; + } return res; } @@ -6482,6 +6497,15 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) goto fail; } WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res)); + + + mpc = 0; + if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { + WL_ERROR(("%s fail to set mpc\n", __FUNCTION__)); + goto fail; + } + + #endif updown = 1; @@ -6528,16 +6552,16 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) { ap->channel = 1; - WL_ERROR(("%s auto channel failed, pick up channel=%d\n", + WL_ERROR(("%s auto channel failed, use channel=%d\n", __FUNCTION__, ap->channel)); } channel = ap->channel; if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) { WL_ERROR(("%s fail to set channel\n", __FUNCTION__)); - goto fail; } + if (ap_cfg_running == FALSE) { updown = 0; if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) { @@ -6877,11 +6901,11 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac) char z_mac[6] = {0, 0, 0, 0, 0, 0}; char *sta_mac; struct maclist *assoc_maclist = (struct maclist *) mac_buf; - bool deauth_all = false; + bool deauth_all = FALSE; if (mac == NULL) { - deauth_all = true; + deauth_all = TRUE; sta_mac = z_mac; } else { sta_mac = mac; @@ -7179,7 +7203,7 @@ set_ap_mac_list(struct net_device *dev, void *buf) if (assoc_maclist->count) for (i = 0; i < assoc_maclist->count; i++) { int j; - bool assoc_mac_matched = false; + bool assoc_mac_matched = FALSE; WL_SOFTAP(("\n Cheking assoc STA: ")); dhd_print_buf(&assoc_maclist->ea[i], 6, 7); @@ -7189,7 +7213,7 @@ set_ap_mac_list(struct net_device *dev, void *buf) if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j], ETHER_ADDR_LEN)) { - assoc_mac_matched = true; + assoc_mac_matched = TRUE; break; } -- cgit v1.2.3