net: wireless: bcmdhd: Fix bssid profile update
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 19 Oct 2011 20:09:49 +0000 (13:09 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:25:02 +0000 (12:25 -0800)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/wl_cfg80211.c

index ac374af..fae07ab 100644 (file)
@@ -477,6 +477,8 @@ extern int  dhd_bus_start(dhd_pub_t *dhdp);
 extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
 extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
 
+bool is_associated(dhd_pub_t *dhd, void *bss_buf);
+
 #if defined(KEEP_ALIVE)
 extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
 #endif /* KEEP_ALIVE */
index 2703784..d269172 100644 (file)
@@ -2187,6 +2187,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        u32 wpsie_len = 0;
        u32 chan_cnt = 0;
        u8 wpsie[IE_MAX_LEN];
+       struct ether_addr bssid;
+
        WL_DBG(("In\n"));
        CHECK_SYS_UP(wl);
 
@@ -2197,6 +2199,10 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                wl_cfg80211_scan_abort(wl, dev);
        }
 
+       /* Clean BSSID */
+       bzero(&bssid, sizeof(bssid));
+       wl_update_prof(wl, NULL, (void *)&bssid, WL_PROF_BSSID);
+
        if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
                /* we only allow to connect using virtual interface in case of P2P */
                if (p2p_on(wl) && is_wps_conn(sme)) {
@@ -2302,7 +2308,6 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                return err;
        }
 
-       wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
        /*
         *  Join with specific BSSID and cached SSID
         *  If SSID is zero join based on BSSID only
@@ -2835,8 +2840,10 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
        s8 eabuf[ETHER_ADDR_STR_LEN];
 #endif
+       dhd_pub_t *dhd =  (dhd_pub_t *)(wl->pub);
 
        CHECK_SYS_UP(wl);
+       WL_DBG((" Enter\n"));
        if (get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
                err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
                        ETHER_ADDR_LEN, ioctlbuf, sizeof(ioctlbuf));
@@ -2863,12 +2870,19 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 #endif
        } else if (get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
                        u8 *curmacp = wl_read_prof(wl, WL_PROF_BSSID);
+
+                       if (!wl_get_drv_status(wl, CONNECTED) ||
+                           (is_associated(dhd, NULL) == FALSE)) {
+                               WL_ERR(("NOT assoc\n"));
+                               err = -ENODEV;
+                               goto get_station_err;
+                       }
+
                        if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
                                WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n",
                                        MAC2STR(mac), MAC2STR(curmacp)));
-                               err = -ENOENT;
-                               goto get_station_err;
                        }
+
                        /* Report the current tx rate */
                        err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
                        if (err) {
@@ -2880,23 +2894,27 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                                WL_DBG(("Rate %d Mbps\n", (rate / 2)));
                        }
 
-                       if (wl_get_drv_status(wl, CONNECTED)) {
-                               memset(&scb_val, 0, sizeof(scb_val));
-                               scb_val.val = 0;
-                               err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
+                       memset(&scb_val, 0, sizeof(scb_val));
+                       scb_val.val = 0;
+                       err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
                                        sizeof(scb_val_t), false);
-                               if (err) {
-                                       WL_ERR(("Could not get rssi (%d)\n", err));
-                                       goto get_station_err;
-                               }
-                               rssi = dtoh32(scb_val.val);
-                               sinfo->filled |= STATION_INFO_SIGNAL;
-                               sinfo->signal = rssi;
-                               WL_DBG(("RSSI %d dBm\n", rssi));
+                       if (err) {
+                               WL_ERR(("Could not get rssi (%d)\n", err));
+                               goto get_station_err;
                        }
+
+                       rssi = dtoh32(scb_val.val);
+                       sinfo->filled |= STATION_INFO_SIGNAL;
+                       sinfo->signal = rssi;
+                       WL_DBG(("RSSI %d dBm\n", rssi));
+
 get_station_err:
-               if (err)
+               if (err) {
+                       WL_ERR(("force cfg80211_disconnected\n"));
+                       wl_clr_drv_status(wl, CONNECTED);
                        cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
+                       wl_link_down(wl);
+               }
        }
 
        return err;
@@ -4427,6 +4445,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                        wl_link_up(wl);
                        act = true;
                        wl_update_prof(wl, e, &act, WL_PROF_ACT);
+                       wl_update_prof(wl, NULL, (void *)&e->addr, WL_PROF_BSSID);
                        if (wl_is_ibssmode(wl, ndev)) {
                                printk("cfg80211_ibss_joined\n");
                                cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
@@ -4511,6 +4530,7 @@ wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
                        wl_bss_connect_done(wl, ndev, e, data, true);
                act = true;
                wl_update_prof(wl, e, &act, WL_PROF_ACT);
+               wl_update_prof(wl, NULL, (void *)&e->addr, WL_PROF_BSSID);
        }
        return err;
 }