u64 timestamp;
        int beacon_int;
 
-       bool probe_resp;
+       unsigned long last_probe_resp;
        unsigned long last_update;
 
        /* during assocation, we save an ERP value from a probe response so
 #define IEEE80211_STA_PRIVACY_INVOKED  BIT(13)
 /* flags for  MLME request*/
 #define IEEE80211_STA_REQ_SCAN 0
-#define IEEE80211_STA_REQ_AUTH 1
-#define IEEE80211_STA_REQ_RUN  2
+#define IEEE80211_STA_REQ_DIRECT_PROBE 1
+#define IEEE80211_STA_REQ_AUTH 2
+#define IEEE80211_STA_REQ_RUN  3
 
 /* flags used for setting mlme state */
 enum ieee80211_sta_mlme_state {
        IEEE80211_STA_MLME_DISABLED,
+       IEEE80211_STA_MLME_DIRECT_PROBE,
        IEEE80211_STA_MLME_AUTHENTICATE,
        IEEE80211_STA_MLME_ASSOCIATE,
        IEEE80211_STA_MLME_ASSOCIATED,
        struct sk_buff_head skb_queue;
 
        int assoc_scan_tries; /* number of scans done pre-association */
+       int direct_probe_tries; /* retries for direct probes */
        int auth_tries; /* retries for auth req */
        int assoc_tries; /* retries for assoc req */
 
 
 static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
                                   struct ieee80211_if_sta *ifsta, int deauth)
 {
-       if (deauth)
+       if (deauth) {
+               ifsta->direct_probe_tries = 0;
                ifsta->auth_tries = 0;
+       }
        ifsta->assoc_scan_tries = 0;
        ifsta->assoc_tries = 0;
        ieee80211_set_associated(sdata, ifsta, 0);
        ieee80211_sta_tx(sdata, skb, encrypt);
 }
 
+static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
+                                  struct ieee80211_if_sta *ifsta)
+{
+       DECLARE_MAC_BUF(mac);
+
+       ifsta->direct_probe_tries++;
+       if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
+               printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n",
+                      sdata->dev->name, print_mac(mac, ifsta->bssid));
+               ifsta->state = IEEE80211_STA_MLME_DISABLED;
+               return;
+       }
+
+       printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n",
+                       sdata->dev->name, print_mac(mac, ifsta->bssid),
+                       ifsta->direct_probe_tries);
+
+       ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
+
+       set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request);
+
+       /* Direct probe is sent to broadcast address as some APs
+        * will not answer to direct packet in unassociated state.
+        */
+       ieee80211_send_probe_req(sdata, NULL,
+                                ifsta->ssid, ifsta->ssid_len);
+
+       mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
+}
+
 
 static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
                                   struct ieee80211_if_sta *ifsta)
        if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE ||
            ifsta->state == IEEE80211_STA_MLME_ASSOCIATE ||
            ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) {
-               ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
+               ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
                mod_timer(&ifsta->timer, jiffies +
                                      IEEE80211_RETRY_AUTH_INTERVAL);
        }
                                  struct ieee80211_mgmt *mgmt,
                                  size_t len,
                                  struct ieee80211_rx_status *rx_status,
-                                 struct ieee802_11_elems *elems,
-                                 int beacon)
+                                 struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
        int freq, clen;
        struct sta_info *sta;
        u64 beacon_timestamp, rx_timestamp;
        struct ieee80211_channel *channel;
+       bool beacon = ieee80211_is_beacon(mgmt->frame_control);
        DECLARE_MAC_BUF(mac);
        DECLARE_MAC_BUF(mac2);
 
        bss->signal = rx_status->signal;
        bss->noise = rx_status->noise;
        bss->qual = rx_status->qual;
-       if (!beacon && !bss->probe_resp)
-               bss->probe_resp = true;
-
+       if (!beacon)
+               bss->last_probe_resp = jiffies;
        /*
         * In STA mode, the remaining parameters should not be overridden
         * by beacons because they're not necessarily accurate there.
         */
        if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-           bss->probe_resp && beacon) {
+           bss->last_probe_resp && beacon) {
                ieee80211_rx_bss_put(local, bss);
                return;
        }
 {
        size_t baselen;
        struct ieee802_11_elems elems;
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
 
        if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN))
                return; /* ignore ProbeResp to foreign address */
        ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
                                &elems);
 
-       ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 0);
+       ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
+
+       /* direct probe may be part of the association flow */
+       if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE,
+                                                       &ifsta->request)) {
+               printk(KERN_DEBUG "%s direct probe responded\n",
+                      sdata->dev->name);
+               ieee80211_authenticate(sdata, ifsta);
+       }
 }
 
 
 
        ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
 
-       ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 1);
+       ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
 
        if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
                return;
                mesh_path_start_discovery(sdata);
 #endif
 
-       if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
+       if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
+           ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
            ifsta->state != IEEE80211_STA_MLME_ASSOCIATE &&
            test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
                if (ifsta->scan_ssid_len)
        switch (ifsta->state) {
        case IEEE80211_STA_MLME_DISABLED:
                break;
+       case IEEE80211_STA_MLME_DIRECT_PROBE:
+               ieee80211_direct_probe(sdata, ifsta);
+               break;
        case IEEE80211_STA_MLME_AUTHENTICATE:
                ieee80211_authenticate(sdata, ifsta);
                break;
        ifsta->auth_transaction = -1;
        ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
        ifsta->assoc_scan_tries = 0;
+       ifsta->direct_probe_tries = 0;
        ifsta->auth_tries = 0;
        ifsta->assoc_tries = 0;
        netif_carrier_off(sdata->dev);
                                               selected->ssid_len);
                ieee80211_sta_set_bssid(sdata, selected->bssid);
                ieee80211_sta_def_wmm_params(sdata, selected, 0);
+
+               /* Send out direct probe if no probe resp was received or
+                * the one we have is outdated
+                */
+               if (!selected->last_probe_resp ||
+                   time_after(jiffies, selected->last_probe_resp
+                                       + IEEE80211_SCAN_RESULT_EXPIRE))
+                       ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
+               else
+                       ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
+
                ieee80211_rx_bss_put(local, selected);
-               ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
                ieee80211_sta_reset_auth(sdata, ifsta);
                return 0;
        } else {