break;
        case ATH10K_SCAN_RUNNING:
        case ATH10K_SCAN_ABORTING:
-               if (!ar->scan.is_roc)
-                       ieee80211_scan_completed(ar->hw,
-                                                (ar->scan.state ==
-                                                 ATH10K_SCAN_ABORTING));
-               else if (ar->scan.roc_notify)
+               if (!ar->scan.is_roc) {
+                       struct cfg80211_scan_info info = {
+                               .aborted = (ar->scan.state ==
+                                           ATH10K_SCAN_ABORTING),
+                       };
+
+                       ieee80211_scan_completed(ar->hw, &info);
+               } else if (ar->scan.roc_notify) {
                        ieee80211_remain_on_channel_expired(ar->hw);
+               }
                /* fall through */
        case ATH10K_SCAN_STARTING:
                ar->scan.state = ATH10K_SCAN_IDLE;
 
 void ath_scan_complete(struct ath_softc *sc, bool abort)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct cfg80211_scan_info info = {
+               .aborted = abort,
+       };
 
        if (abort)
                ath_dbg(common, CHAN_CTX, "HW scan aborted\n");
        sc->offchannel.scan_req = NULL;
        sc->offchannel.scan_vif = NULL;
        sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
-       ieee80211_scan_completed(sc->hw, abort);
+       ieee80211_scan_completed(sc->hw, &info);
        clear_bit(ATH_OP_SCANNING, &common->op_flags);
        spin_lock_bh(&sc->chan_lock);
        if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
 
 {
        struct at76_priv *priv = container_of(work, struct at76_priv,
                                              dwork_hw_scan.work);
+       struct cfg80211_scan_info info = {
+               .aborted = false,
+       };
        int ret;
 
        if (priv->device_unplugged)
 
        mutex_unlock(&priv->mtx);
 
-       ieee80211_scan_completed(priv->hw, false);
+       ieee80211_scan_completed(priv->hw, &info);
 
        ieee80211_wake_queues(priv->hw);
 }
 
 static void
 il_complete_scan(struct il_priv *il, bool aborted)
 {
+       struct cfg80211_scan_info info = {
+               .aborted = aborted,
+       };
+
        /* check if scan was requested from mac80211 */
        if (il->scan_request) {
                D_SCAN("Complete scan in mac80211\n");
-               ieee80211_scan_completed(il->hw, aborted);
+               ieee80211_scan_completed(il->hw, &info);
        }
 
        il->scan_vif = NULL;
 
 
 static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
 {
+       struct cfg80211_scan_info info = {
+               .aborted = aborted,
+       };
+
        /* check if scan was requested from mac80211 */
        if (priv->scan_request) {
                IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
-               ieee80211_scan_completed(priv->hw, aborted);
+               ieee80211_scan_completed(priv->hw, &info);
        }
 
        priv->scan_type = IWL_SCAN_NORMAL;
 
                ieee80211_sched_scan_stopped(mvm->hw);
                mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
        } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
+               struct cfg80211_scan_info info = {
+                       .aborted = aborted,
+               };
+
                IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
                               aborted ? "aborted" : "completed",
                               iwl_mvm_ebs_status_str(scan_notif->ebs_status));
 
                mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
-               ieee80211_scan_completed(mvm->hw,
-                               scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
+               ieee80211_scan_completed(mvm->hw, &info);
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
                del_timer(&mvm->scan_timer);
        } else {
 
        /* if the scan is already stopping, we don't need to notify mac80211 */
        if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_REGULAR) {
-               ieee80211_scan_completed(mvm->hw, aborted);
+               struct cfg80211_scan_info info = {
+                       .aborted = aborted,
+               };
+
+               ieee80211_scan_completed(mvm->hw, &info);
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
                del_timer(&mvm->scan_timer);
        } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
 
                uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_REGULAR);
                if (uid >= 0) {
-                       ieee80211_scan_completed(mvm->hw, true);
+                       struct cfg80211_scan_info info = {
+                               .aborted = true,
+                       };
+
+                       ieee80211_scan_completed(mvm->hw, &info);
                        mvm->scan_uid_status[uid] = 0;
                }
                uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
                                mvm->scan_uid_status[i] = 0;
                }
        } else {
-               if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
-                       ieee80211_scan_completed(mvm->hw, true);
+               if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
+                       struct cfg80211_scan_info info = {
+                               .aborted = true,
+                       };
+
+                       ieee80211_scan_completed(mvm->hw, &info);
+               }
 
                /* Sched scan will be restarted by mac80211 in
                 * restart_hw, so do not report if FW is about to be
                 */
                iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
                del_timer(&mvm->scan_timer);
-               if (notify)
-                       ieee80211_scan_completed(mvm->hw, true);
+               if (notify) {
+                       struct cfg80211_scan_info info = {
+                               .aborted = true,
+                       };
+
+                       ieee80211_scan_completed(mvm->hw, &info);
+               }
        } else if (notify) {
                ieee80211_sched_scan_stopped(mvm->hw);
                mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
 
 
        mutex_lock(&hwsim->mutex);
        if (hwsim->scan_chan_idx >= req->n_channels) {
+               struct cfg80211_scan_info info = {
+                       .aborted = false,
+               };
+
                wiphy_debug(hwsim->hw->wiphy, "hw scan complete\n");
-               ieee80211_scan_completed(hwsim->hw, false);
+               ieee80211_scan_completed(hwsim->hw, &info);
                hwsim->hw_scan_request = NULL;
                hwsim->hw_scan_vif = NULL;
                hwsim->tmp_chan = NULL;
                                          struct ieee80211_vif *vif)
 {
        struct mac80211_hwsim_data *hwsim = hw->priv;
+       struct cfg80211_scan_info info = {
+               .aborted = true,
+       };
 
        wiphy_debug(hw->wiphy, "hwsim cancel_hw_scan\n");
 
        cancel_delayed_work_sync(&hwsim->hw_scan);
 
        mutex_lock(&hwsim->mutex);
-       ieee80211_scan_completed(hwsim->hw, true);
+       ieee80211_scan_completed(hwsim->hw, &info);
        hwsim->tmp_chan = NULL;
        hwsim->hw_scan_request = NULL;
        hwsim->hw_scan_vif = NULL;
 
        }
 
        if (!priv->scan.req || (priv->scan.curr == priv->scan.end)) {
+               struct cfg80211_scan_info info = {
+                       .aborted = priv->scan.status ? 1 : 0,
+               };
+
                if (priv->scan.output_power != priv->output_power)
                        wsm_set_output_power(priv, priv->output_power * 10);
                if (priv->join_status == CW1200_JOIN_STATUS_STA &&
                cw1200_scan_restart_delayed(priv);
                wsm_unlock_tx(priv);
                mutex_unlock(&priv->conf_mutex);
-               ieee80211_scan_completed(priv->hw, priv->scan.status ? 1 : 0);
+               ieee80211_scan_completed(priv->hw, &info);
                up(&priv->scan.lock);
                return;
        } else {
 
                     mbox->scheduled_scan_channels);
 
        if (wl->scanning) {
-               ieee80211_scan_completed(wl->hw, false);
+               struct cfg80211_scan_info info = {
+                       .aborted = false,
+               };
+
+               ieee80211_scan_completed(wl->hw, &info);
                wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
                wl->scanning = false;
                if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
 
        WARN_ON(wl->state != WL1251_STATE_ON);
 
        if (wl->scanning) {
-               ieee80211_scan_completed(wl->hw, true);
+               struct cfg80211_scan_info info = {
+                       .aborted = true,
+               };
+
+               ieee80211_scan_completed(wl->hw, &info);
                wl->scanning = false;
        }
 
 
 
        if (wl->scan.state != WL1271_SCAN_STATE_IDLE &&
            wl->scan_wlvif == wlvif) {
+               struct cfg80211_scan_info info = {
+                       .aborted = true,
+               };
+
                /*
                 * Rearm the tx watchdog just before idling scan. This
                 * prevents just-finished scans from triggering the watchdog
                memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
                wl->scan_wlvif = NULL;
                wl->scan.req = NULL;
-               ieee80211_scan_completed(wl->hw, true);
+               ieee80211_scan_completed(wl->hw, &info);
        }
 
        if (wl->sched_vif == wlvif)
 {
        struct wl1271 *wl = hw->priv;
        struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+       struct cfg80211_scan_info info = {
+               .aborted = true,
+       };
        int ret;
 
        wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan");
        memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
        wl->scan_wlvif = NULL;
        wl->scan.req = NULL;
-       ieee80211_scan_completed(wl->hw, true);
+       ieee80211_scan_completed(wl->hw, &info);
 
 out_sleep:
        wl1271_ps_elp_sleep(wl);
 
        struct delayed_work *dwork;
        struct wl1271 *wl;
        struct wl12xx_vif *wlvif;
+       struct cfg80211_scan_info info = {
+               .aborted = false,
+       };
        int ret;
 
        dwork = to_delayed_work(work);
 
        wlcore_cmd_regdomain_config_locked(wl);
 
-       ieee80211_scan_completed(wl->hw, false);
+       ieee80211_scan_completed(wl->hw, &info);
 
 out:
        mutex_unlock(&wl->mutex);
 
  * any context, including hardirq context.
  *
  * @hw: the hardware that finished the scan
- * @aborted: set to true if scan was aborted
+ * @info: information about the completed scan
  */
-void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted);
+void ieee80211_scan_completed(struct ieee80211_hw *hw,
+                             struct cfg80211_scan_info *info);
 
 /**
  * ieee80211_sched_scan_results - got results from scheduled scan
 
        int scan_channel_idx;
        int scan_ies_len;
        int hw_scan_ies_bufsize;
+       struct cfg80211_scan_info scan_info;
 
        struct work_struct sched_scan_stopped_work;
        struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
 
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2013-2015  Intel Mobile Communications GmbH
+ * Copyright 2016  Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
                .boottime_ns = rx_status->boottime_ns,
        };
        bool signal_valid;
+       struct ieee80211_sub_if_data *scan_sdata;
 
        if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
                bss_meta.signal = rx_status->signal * 100;
                bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
 
        bss_meta.chan = channel;
+
+       rcu_read_lock();
+       scan_sdata = rcu_dereference(local->scan_sdata);
+       if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
+           scan_sdata->vif.bss_conf.assoc &&
+           ieee80211_have_rx_timestamp(rx_status)) {
+               bss_meta.parent_tsf =
+                       ieee80211_calculate_rx_timestamp(local, rx_status,
+                                                        len + FCS_LEN, 24);
+               ether_addr_copy(bss_meta.parent_bssid,
+                               scan_sdata->vif.bss_conf.bssid);
+       }
+       rcu_read_unlock();
+
        cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
                                              mgmt, len, GFP_ATOMIC);
        if (!cbss)
 
                if (rc == 0)
                        return;
+
+               /* HW scan failed and is going to be reported as done, so clear
+                * old scan info.
+                */
+               memset(&local->scan_info, 0, sizeof(local->scan_info));
        }
 
        kfree(local->hw_scan_req);
                                             lockdep_is_held(&local->mtx));
 
        if (scan_req != local->int_scan_req) {
-               struct cfg80211_scan_info info = {
-                       .aborted = aborted,
-               };
-
-               cfg80211_scan_done(scan_req, &info);
+               local->scan_info.aborted = aborted;
+               cfg80211_scan_done(scan_req, &local->scan_info);
        }
        RCU_INIT_POINTER(local->scan_req, NULL);
 
                ieee80211_start_next_roc(local);
 }
 
-void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
+void ieee80211_scan_completed(struct ieee80211_hw *hw,
+                             struct cfg80211_scan_info *info)
 {
        struct ieee80211_local *local = hw_to_local(hw);
 
-       trace_api_scan_completed(local, aborted);
+       trace_api_scan_completed(local, info);
 
        set_bit(SCAN_COMPLETED, &local->scanning);
-       if (aborted)
+       if (info->aborted)
                set_bit(SCAN_ABORTED, &local->scanning);
+
+       memcpy(&local->scan_info, info, sizeof(*info));
+
        ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
 }
 EXPORT_SYMBOL(ieee80211_scan_completed);
                local->hw_scan_req->req.ie = ies;
                local->hw_scan_req->req.flags = req->flags;
                eth_broadcast_addr(local->hw_scan_req->req.bssid);
+               local->hw_scan_req->req.duration = req->duration;
+               local->hw_scan_req->req.duration_mandatory =
+                       req->duration_mandatory;
 
                local->hw_scan_band = 0;
 
         */
        cancel_delayed_work(&local->scan_work);
        /* and clean up */
+       memset(&local->scan_info, 0, sizeof(local->scan_info));
        __ieee80211_scan_completed(&local->hw, true);
 out:
        mutex_unlock(&local->mtx);