net: wireless: bcmdhd: Fixing memory leak problem in wl_get_ies
Greg Goldman [Tue, 9 Aug 2011 18:43:28 +0000 (11:43 -0700)]
Change-Id: I26462c22ba4c3aebc1e157fbf74833c65815647c
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>

drivers/net/wireless/bcmdhd/bcmevent.c
drivers/net/wireless/bcmdhd/dhd_linux.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/include/epivers.h
drivers/net/wireless/bcmdhd/include/proto/bcmevent.h
drivers/net/wireless/bcmdhd/include/wlioctl.h
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfg80211.h
drivers/net/wireless/bcmdhd/wl_cfgp2p.c

index 3cee7c2..24581dd 100644 (file)
@@ -29,7 +29,7 @@
 #include <proto/bcmeth.h>
 #include <proto/bcmevent.h>
 
-#if WLC_E_LAST != 84
+#if WLC_E_LAST != 85
 #error "You need to add an entry to bcmevent_names[] for the new event"
 #endif
 
@@ -115,7 +115,10 @@ const bcmevent_name_t bcmevent_names[] = {
        { WLC_E_CSA_COMPLETE_IND, "WLC_E_CSA_COMPLETE_IND" },
        { WLC_E_EXCESS_PM_WAKE_EVENT, "EXCESS_PM_WAKE_EVENT" },
        { WLC_E_PFN_SCAN_NONE, "PFN_SCAN_NONE" },
-       { WLC_E_PFN_SCAN_ALLGONE, "PFN_SCAN_ALLGONE" }
+       { WLC_E_PFN_SCAN_ALLGONE, "PFN_SCAN_ALLGONE" },
+#ifdef SOFTAP
+       { WLC_E_GTK_PLUMBED, "GTK_PLUMBED" }
+#endif
 };
 
 
index 0651c25..c6e7095 100644 (file)
@@ -971,7 +971,8 @@ dhd_op_if(dhd_if_t *ifp)
                        memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd));
 #ifdef WL_CFG80211
                        if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)
-                               if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, dhd_net_attach)) {
+                               if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, ifp->bssidx,
+                                       dhd_net_attach)) {
                                        ifp->state = 0;
                                        return;
                        }
@@ -2357,6 +2358,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
        if (handle == NULL) {
                ifp->state = WLC_E_IF_ADD;
                ifp->idx = ifidx;
+               ifp->bssidx = bssidx;
                ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0);
                up(&dhd->thr_sysioc_ctl.sema);
        } else
index db763ab..9f7c416 100644 (file)
@@ -1026,7 +1026,9 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
        htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 #ifdef DHD_DEBUG
-       tx_packets[PKTPRIO(pkt)]++;
+       if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets)) {
+               tx_packets[PKTPRIO(pkt)]++;
+       }
        if (DHD_BYTES_ON() &&
            (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) ||
              (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) {
index 5c63a39..b94174e 100644 (file)
 
 #define        EPI_RC_NUMBER           125
 
-#define        EPI_INCREMENTAL_NUMBER  52
+#define        EPI_INCREMENTAL_NUMBER  60
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             5, 90, 125, 52
+#define        EPI_VERSION             5, 90, 125, 60
 
-#define        EPI_VERSION_NUM         0x055a7d34
+#define        EPI_VERSION_NUM         0x055a7d3c
 
 #define EPI_VERSION_DEV                5.90.125
 
 
-#define        EPI_VERSION_STR         "5.90.125.52"
+#define        EPI_VERSION_STR         "5.90.125.60"
 
 #endif 
index 7f51faa..30ec848 100644 (file)
@@ -181,7 +181,8 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
 #define WLC_E_EXCESS_PM_WAKE_EVENT     81      
 #define WLC_E_PFN_SCAN_NONE            82      
 #define WLC_E_PFN_SCAN_ALLGONE 83      
-#define WLC_E_LAST             84      
+#define WLC_E_GTK_PLUMBED 84
+#define WLC_E_LAST     85
 
 
 typedef struct {
index a441eab..a09dd26 100644 (file)
@@ -190,6 +190,7 @@ typedef struct wlc_ssid {
 #define WL_SCANFLAGS_RESERVED 0x02      
 #define WL_SCANFLAGS_PROHIBITED 0x04    
 
+#define WL_SCAN_PARAMS_SSID_MAX        10
 typedef struct wl_scan_params {
        wlc_ssid_t ssid;        
        struct ether_addr bssid;    
index 4b7d104..ed2e5dd 100644 (file)
@@ -83,7 +83,7 @@ u32 wl_dbg_level = WL_DBG_ERR;
 #define WL_TRACE(a) printk("%s ", __FUNCTION__); printk a
 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAX_WAIT_TIME 3000
+#define MAX_WAIT_TIME 1500
 static s8 ioctlbuf[WLC_IOCTL_MAXLEN];
 
 #if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL)
@@ -1118,7 +1118,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 s32
-wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx,
+wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx,
 int (*_net_attach)(dhd_pub_t *dhdp, int ifidx))
 {
        struct wl_priv *wl = WL_PRIV_GET();
@@ -1133,11 +1133,11 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx))
                /* Assign the net device to CONNECT BSSCFG */
                strncpy(net->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
                wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net;
-               wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) =
-                       P2PAPI_BSSCFG_CONNECTION;
+               wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
                wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
-               wl_clr_p2p_status(wl, IF_ADD);
                net->ifindex = idx;
+               wl_clr_p2p_status(wl, IF_ADD);
+
                wake_up_interruptible(&wl->dongle_event_wait);
        }
        return ret;
@@ -2153,7 +2153,10 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
        join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
        wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
-       memcpy(&join_params.params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+       if (sme->bssid)
+               memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
+       else
+               memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
 
        wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
        WL_DBG(("join_param_size %d\n", join_params_size));
@@ -2976,12 +2979,12 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
                 * without turning on P2P
                 */
 
+               p2p_on(wl) = true;
                err = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0);
 
                if (unlikely(err)) {
                        goto exit;
                }
-               p2p_on(wl) = true;
        }
        if (p2p_on(wl))
                wl_cfgp2p_discover_listen(wl, target_channel, duration);
@@ -3926,13 +3929,6 @@ static s32 wl_inform_bss(struct wl_priv *wl)
        s32 i;
 
        bss_list = wl->bss_list;
-#if 0
-       if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
-               WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n",
-                       bss_list->version));
-               return -EOPNOTSUPP;
-       }
-#endif
        WL_DBG(("scanned AP count (%d)\n", bss_list->count));
        bi = next_bss(bss_list, bi);
        for_each_bss(bss_list, bi, i) {
@@ -4279,6 +4275,14 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
        assoc_info.req_len = htod32(assoc_info.req_len);
        assoc_info.resp_len = htod32(assoc_info.resp_len);
        assoc_info.flags = htod32(assoc_info.flags);
+       if (conn_info->req_ie_len) {
+               conn_info->req_ie_len = 0;
+               bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
+       }
+       if (conn_info->resp_ie_len) {
+               conn_info->resp_ie_len = 0;
+               bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
+       }
        if (assoc_info.req_len) {
                err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
                        WL_ASSOC_INFO_MAX);
@@ -4290,11 +4294,15 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
                if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
                        conn_info->req_ie_len -= ETHER_ADDR_LEN;
                }
-               conn_info->req_ie =
-                   kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
+               if (conn_info->req_ie_len <= MAX_REQ_LINE)
+                       memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
+               else {
+                       WL_ERR(("%s IE size %d above max %d size \n",
+                               __FUNCTION__, conn_info->req_ie_len, MAX_REQ_LINE));
+                       return err;
+               }
        } else {
                conn_info->req_ie_len = 0;
-               conn_info->req_ie = NULL;
        }
        if (assoc_info.resp_len) {
                err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
@@ -4304,11 +4312,15 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
                        return err;
                }
                conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
-               conn_info->resp_ie =
-                   kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
+               if (conn_info->resp_ie_len <= MAX_REQ_LINE)
+                       memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
+               else {
+                       WL_ERR(("%s IE size %d above max %d size \n",
+                               __FUNCTION__, conn_info->resp_ie_len, MAX_REQ_LINE));
+                       return err;
+               }
        } else {
                conn_info->resp_ie_len = 0;
-               conn_info->resp_ie = NULL;
        }
        WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
                conn_info->resp_ie_len));
@@ -4459,11 +4471,14 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
        s32 err = 0;
 
        WL_DBG((" enter\n"));
-       wl_get_assoc_ies(wl, ndev);
-       memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
-       wl_update_bss_info(wl, ndev);
+
        if (wl_get_drv_status(wl, CONNECTING)) {
                wl_clr_drv_status(wl, CONNECTING);
+               if (completed) {
+                       wl_get_assoc_ies(wl, ndev);
+                       memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
+                       wl_update_bss_info(wl, ndev);
+               }
                cfg80211_connect_result(ndev,
                        (u8 *)&wl->bssid,
                        conn_info->req_ie,
@@ -6267,11 +6282,7 @@ static void wl_link_down(struct wl_priv *wl)
 
        WL_DBG(("In\n"));
        wl->link_up = false;
-       kfree(conn_info->req_ie);
-       conn_info->req_ie = NULL;
        conn_info->req_ie_len = 0;
-       kfree(conn_info->resp_ie);
-       conn_info->resp_ie = NULL;
        conn_info->resp_ie_len = 0;
 }
 
index 5b89401..9611076 100644 (file)
@@ -274,10 +274,11 @@ struct wl_iscan_ctrl {
 };
 
 /* association inform */
+#define MAX_REQ_LINE 1024
 struct wl_connect_info {
-       u8 *req_ie;
+       u8 req_ie[MAX_REQ_LINE];
        s32 req_ie_len;
-       u8 *resp_ie;
+       u8 resp_ie[MAX_REQ_LINE];
        s32 resp_ie_len;
 };
 
@@ -498,7 +499,7 @@ extern void wl_cfg80211_set_sdio_func(void *func);  /* set sdio function info */
 extern struct sdio_func *wl_cfg80211_get_sdio_func(void);      /* set sdio function info */
 extern s32 wl_cfg80211_up(void);       /* dongle up */
 extern s32 wl_cfg80211_down(void);     /* dongle down */
-extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx,
+extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx,
 int (*_net_attach)(dhd_pub_t *dhdp, int ifidx));
 extern s32 wl_cfg80211_ifdel_ops(struct net_device *net);
 extern s32 wl_cfg80211_notify_ifdel(struct net_device *net);
index 7a5619e..a261a72 100644 (file)
@@ -200,7 +200,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 {
        wl_p2p_if_t ifreq;
        s32 err;
-       struct net_device *netdev = wl_to_prmry_ndev(wl);
+       struct net_device *netdev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
 
        ifreq.type = if_type;
        ifreq.chspec = chspec;