diff --git a/src/agent.c b/src/agent.c
index 74adcb57ba038364b57ca6310432d633414908d5..bb29a3f4df426e78c69406b37f8d7ce8b87f20e1 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -6481,8 +6481,9 @@ static void parse_ap(struct ubus_request *req, int type,
 
 }
 
-static int agent_radio_update_scanresults_element(struct wifi_radio_element *re, struct wifi_bss *bsss,
-		uint32_t classid)
+static int agent_radio_update_scanresults_element(struct wifi_radio_element *re,
+						  struct wifi_bss *bsss,
+						  uint32_t classid)
 {
 	struct wifi_scanres_channel_element *scanres_el;
 	int idx;
@@ -6532,13 +6533,32 @@ static int agent_radio_update_scanresults_element(struct wifi_radio_element *re,
 	return 0;
 }
 
+/* scan_duration expected as ms */
+static int agent_scanres_update_scan_duration(struct wifi_radio_element *re,
+					      uint8_t classid, uint8_t channel,
+					      uint64_t scan_duration)
+{
+	struct wifi_scanres_channel_element *scanres_el;
+
+	scanres_el = wifi_get_scanres_ch_element(re, classid, channel);
+	if (!scanres_el)
+		return -1;
+
+	scanres_el->scan_duration = scan_duration;
+	return 0;
+}
+
 static int agent_radio_update_scanlist(struct agent *a,
-		struct wifi_radio_element *re, struct wifi_bss *bsss, int bss_num)
+				       struct wifi_radio_element *re,
+				       struct wifi_bss *bsss, int bss_num,
+				       struct chan_entry *ch_entry,
+				       int ch_entry_num)
 {
 	int i;
 
 	trace("%s: update results for [%s]\n", __func__, re->name);
 
+	/* add neighbors */
 	for (i = 0; i < bss_num; i++) {
 		uint8_t classid = wifi_opclass_find_id_from_channel(
 					&re->opclass,
@@ -6556,40 +6576,69 @@ static int agent_radio_update_scanlist(struct agent *a,
 		}
 	}
 
+	/* add scan duration */
+	for (i = 0; i < ch_entry_num; i++) {
+		uint8_t classid = wifi_opclass_find_id_from_channel(
+					&re->opclass,
+					ch_entry[i].channel,
+					20); /* caps */
+
+		/* TODO: current method is not an accurate measurement of
+		 * scan duration for current channel */
+		if (ch_entry[i].channel == re->current_channel)
+			continue;
+
+		agent_scanres_update_scan_duration(re, classid,
+						   ch_entry[i].channel,
+						   ch_entry[i].survey.cca_time / 1000);
+		/* duplicate scan duration for opclass 125 channel overlap */
+		if (classid == OPCLASS_124) {
+			agent_scanres_update_scan_duration(re, OPCLASS_125,
+							    ch_entry[i].channel,
+							    ch_entry[i].survey.cca_time / 1000);
+		}
+	}
+
 	return 0;
 }
 
 int agent_radio_scanresults(struct agent *a, struct wifi_radio_element *re)
 {
 	struct wifi_bss bss[128];
+	struct chan_entry ch_entry[128];
 	int bss_num = ARRAY_SIZE(bss);
+	int ch_entry_num = ARRAY_SIZE(ch_entry);
 	int ret;
 
 	if (!re || !strlen(re->name))
 		return -1;
 
-	trace("[%s] radio scanresults\n", re->name);
+	trace("%s: radio %s scanresults\n", __func__, re->name);
 
 	/* Get scan results from the driver */
 	ret = wifi_get_scan_results(re->name, bss, &bss_num);
 
 	if (ret) {
-		dbg("[%s] failed to get scanresults\n", re->name);
+		dbg("%s: failed to get radio %s scanresults\n", __func__, re->name);
 		return -1;
 	}
 
 	/* Update scan cache */
 	ret = wifi_scanresults_add(&re->scanresults, &re->opclass, bss, bss_num);
 	if (ret) {
-		dbg("[%s] failed to update scan cache\n", re->name);
+		dbg("%s: failed to update scan cache for radio %s\n", __func__, re->name);
 		return -1;
 	}
+	ret = wifi_get_channels_info(re->name, ch_entry, &ch_entry_num);
+	if (ret) {
+		ch_entry_num = 0;
+		dbg("%s: failed to fetch channels info for radio %s\n", __func__, re->name);
+	}
 
 	/* TODO: update scanlist using fresh results from the cache */
-
 	/* Empty scanlist & add most recent results for reporting */
 	free_scanlist_neighbors(re);
-	ret = agent_radio_update_scanlist(a, re, bss, bss_num);
+	ret = agent_radio_update_scanlist(a, re, bss, bss_num, ch_entry, ch_entry_num);
 
 	return ret;
 }
diff --git a/src/agent.h b/src/agent.h
index 1a9eac6b62ce6b8507a7e6c1a024fe4d0a6c5c77..863f5ad3cd78ddadaca2e6a31a41c632c80d3435 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -576,6 +576,7 @@ struct wifi_scanres_channel_element {
 	uint8_t channel;
 	uint8_t utilization;
 	uint8_t anpi;
+	uint32_t scan_duration;
 	uint32_t num_neighbors;
 	struct wifi_scanres_neighbor_element *nbrlist;  /* scanned AP list */
 };
diff --git a/src/agent_map.c b/src/agent_map.c
index b3c5a2c16559c4c00925c821a9d85774c334d0db..499e5f81a9c317c7fd1f143676b6bb07efe3a00e 100644
--- a/src/agent_map.c
+++ b/src/agent_map.c
@@ -5653,10 +5653,6 @@ int handle_channel_scan_request(void *agent, struct cmdu_buff *rx_cmdu,
 
 			/* Special status in 'boot only' mode for 'fresh scan' */
 			scan_req->status = CH_SCAN_STATUS_BOOT_SCAN_ONLY;
-		}
-		/* Do not 'Perform Fresh Scan' */
-		else if (!(ch_scan_req.mode & SCAN_REQUEST_FRESH_SCAN)) {
-
 		}
 		/* Check all requested opc/chan pairs supported by radio */
 		else if (!scan_supported(a, scan_req, re)) {
diff --git a/src/agent_tlv.c b/src/agent_tlv.c
index d816f4647de16c0f6e128de6072105cc9458bd28..baab366094dd9b2999e275604213d34d296d80dc 100644
--- a/src/agent_tlv.c
+++ b/src/agent_tlv.c
@@ -3225,10 +3225,6 @@ int agent_gen_ch_scan_response_tlv(struct agent *a, struct cmdu_buff *cmdu,
 	uint8_t bssload_elem_pres = CH_SCAN_RESULT_BSSLOAD_PRESENT;
 	int i, ret, offset = 0;
 	int reserve_len = CH_SCAN_RESP_TLV_MAX_LEN;
-	/* TODO/FIXME
-	 * add the total scan duration for active scan
-	 */
-	uint32_t scan_duration = 0;
 	uint32_t num_nbr = 0;
 
 	trace("\t %s:INFO: radio " MACFMT ", opclass %d, channel %d\n", __func__,
@@ -3254,7 +3250,7 @@ int agent_gen_ch_scan_response_tlv(struct agent *a, struct cmdu_buff *cmdu,
 		/* Check if nbr data will fit within TLV limits */
 		if ((offset + 18 + strlen(nbr->ssid) + strlen(bw_str)) >= reserve_len) {
 			/* Always add scan duration and scan type to TLV */
-			BUF_PUT_BE32(t->data[offset], scan_duration);
+			BUF_PUT_BE32(t->data[offset], ch->scan_duration);
 			offset += 4;
 			t->data[offset++] = SCAN_RESULT_SCAN_TYPE;
 
@@ -3307,7 +3303,7 @@ int agent_gen_ch_scan_response_tlv(struct agent *a, struct cmdu_buff *cmdu,
 		num_nbr++;
 	}
 
-	BUF_PUT_BE32(t->data[offset], scan_duration);	/* scan duration */
+	BUF_PUT_BE32(t->data[offset], ch->scan_duration);	/* scan duration */
 	offset += 4;
 	t->data[offset++] = SCAN_RESULT_SCAN_TYPE;	/* scan type */
 
diff --git a/src/wifi.c b/src/wifi.c
index f1ca0764010e89cbfd373332618080e05565eb14..89da0315e6855479fabdc697f7bc729fd8261c22 100644
--- a/src/wifi.c
+++ b/src/wifi.c
@@ -111,6 +111,21 @@ int wifi_get_scan_results(const char *name, struct wifi_bss *bsss, int *num)
 	return ret;
 }
 
+int wifi_get_channels_info(const char *name, struct chan_entry *ch_entry, int *num)
+{
+	struct ubus_context *ctx = ubus_connect(NULL);
+	int ret;
+
+	if (!ctx)
+		return -1;
+
+	ret = wifi_ubus_channels_info(ctx, name, ch_entry, num);
+
+	ubus_free(ctx);
+	return ret;
+}
+
+
 int wifi_set_4addr(const char *ifname, bool enable)
 {
 	struct ubus_context *ctx = ubus_connect(NULL);
diff --git a/src/wifi.h b/src/wifi.h
index bef96d28380dc2235901686339fa812b354ca83c..66575bf94236d8e3175f7ae4cae779f1a31f4691 100644
--- a/src/wifi.h
+++ b/src/wifi.h
@@ -83,6 +83,7 @@ int wifi_scan(const char *name, struct scan_param_ex *p,
 	      int num_opclass, uint8_t *opclass,
 	      int num_channel, uint8_t *channel);
 int wifi_get_scan_results(const char *name, struct wifi_bss *bsss, int *num);
+int wifi_get_channels_info(const char *name, struct chan_entry *ch_entry, int *num);
 int wifi_start_cac(const char *name, int channel, enum wifi_bw bw,
 		   enum wifi_cac_method method);
 int wifi_stop_cac(const char *name, int channel, enum wifi_bw bw);
diff --git a/src/wifi_ubus.c b/src/wifi_ubus.c
index 751f2a6ff12a7515ae1a2ddff2ffb7c22d270a1f..74130cbb9f3113cc20943ad0f5bc5680246fa288 100644
--- a/src/wifi_ubus.c
+++ b/src/wifi_ubus.c
@@ -1428,6 +1428,135 @@ out:
 	return ret;
 }
 
+
+struct radio_chinfo_ctx {
+	const char *radio;
+	struct chan_entry *ch;
+	int num;
+	int max;
+	int status;
+};
+
+static void wifi_ubus_channels_info_cb(struct ubus_request *req,
+					   int type,
+					   struct blob_attr *msg)
+{
+	struct radio_chinfo_ctx *ctx = req->priv;
+        static const struct blobmsg_policy radio_chinfo_policy[] = {
+                [0] = { .name = "channels", .type = BLOBMSG_TYPE_ARRAY },
+	};
+	struct blob_attr *tb[ARRAY_SIZE(radio_chinfo_policy)];
+	struct chan_entry *ch;
+	struct blob_attr *cur;
+	int rem, num;
+
+	blobmsg_parse(radio_chinfo_policy, ARRAY_SIZE(radio_chinfo_policy),
+		      tb, blob_data(msg), blob_len(msg));
+
+	num = 0;
+	ctx->num = 0;
+
+	if (!tb[0]) {
+		ctx->status = -1;
+		return;
+	}
+
+	blobmsg_for_each_attr(cur, tb[0], rem) {
+                static const struct blobmsg_policy ch_policy[] = {
+                        [0] = { .name = "channel", .type = BLOBMSG_TYPE_INT32 },
+                        [1] = { .name = "freq", .type = BLOBMSG_TYPE_INT32 },
+                        [2] = { .name = "noise", .type = BLOBMSG_TYPE_INT32 },
+                        [3] = { .name = "diagnostics", .type = BLOBMSG_TYPE_TABLE }
+                };
+                struct blob_attr *ch_tb[ARRAY_SIZE(ch_policy)];
+
+		if (WARN_ON(num >= ctx->max))
+			break;
+
+		blobmsg_parse(ch_policy, ARRAY_SIZE(ch_policy), ch_tb,
+			blobmsg_data(cur), blobmsg_data_len(cur));
+
+		if (!ch_tb[0] || !ch_tb[1] || !ch_tb[2] || !ch_tb[3])
+			continue;
+
+		ch = &ctx->ch[num];
+
+		ch->channel = blobmsg_get_u32(ch_tb[0]);
+		ch->freq = blobmsg_get_u32(ch_tb[1]);
+		ch->noise = (int32_t)blobmsg_get_u32(ch_tb[2]);
+
+		{
+			static const struct blobmsg_policy diag_policy[] = {
+				[0] = { .name = "channel_busy", .type = BLOBMSG_TYPE_INT64 },
+				[1] = { .name = "tx_airtime", .type = BLOBMSG_TYPE_INT64 },
+				[2] = { .name = "rx_airtime", .type = BLOBMSG_TYPE_INT64 },
+				[3] = { .name = "obss_airtime", .type = BLOBMSG_TYPE_INT64 },
+				[4] = { .name = "cca_time", .type = BLOBMSG_TYPE_INT64 },
+				[5] = { .name = "false_cca_count", .type = BLOBMSG_TYPE_INT64 }
+			};
+			struct blob_attr *diag_tb[ARRAY_SIZE(diag_policy)];
+
+			blobmsg_parse(diag_policy, ARRAY_SIZE(diag_policy), diag_tb,
+				blobmsg_data(ch_tb[3]), blobmsg_data_len(ch_tb[3]));
+
+			if (!diag_tb[0] || !diag_tb[1] || !diag_tb[2] || !diag_tb[3] || !diag_tb[4] || !diag_tb[5])
+				continue;
+
+			ch->survey.channel_busy = blobmsg_get_u64(diag_tb[0]);
+			ch->survey.tx_airtime = blobmsg_get_u64(diag_tb[1]);
+			ch->survey.rx_airtime = blobmsg_get_u64(diag_tb[2]);
+			ch->survey.obss_airtime = blobmsg_get_u64(diag_tb[3]);
+			ch->survey.cca_time = blobmsg_get_u64(diag_tb[4]);
+			ch->survey.false_cca_count = blobmsg_get_u64(diag_tb[5]);
+		}
+		num++;
+	}
+
+	ctx->num = num;
+	ctx->status = 0;
+}
+
+
+
+int wifi_ubus_channels_info(struct ubus_context *ubus_ctx, const char *radio,
+				struct chan_entry *ch, int *num)
+{
+	struct radio_chinfo_ctx ctx = {
+		.radio = radio,
+		.ch = ch,
+		.num = 0,
+		.max = *num,
+		.status = -1,
+	};
+	struct blob_buf bb = {};
+	char name[256] = {};
+	uint32_t id;
+	int ret;
+
+	trace("[%s] %s\n", radio, __func__);
+
+	/* Get id from radio name */
+	snprintf(name, sizeof(name), "wifi.radio.%s", radio);
+	ret = ubus_lookup_id(ubus_ctx, name, &id);
+	if (ret != UBUS_STATUS_OK)
+		goto out;
+
+	blob_buf_init(&bb, 0);
+	ret = ubus_invoke(ubus_ctx, id, "channels_info", bb.head,
+			  wifi_ubus_channels_info_cb, &ctx,
+			  2 * 1000);
+	blob_buf_free(&bb);
+
+	if (ctx.status)
+		ret = ctx.status;
+
+	*num = ctx.num;
+
+out:
+	trace("[%s] %s ret %d num %d max %d\n", radio, __func__, ret, *num, ctx.max);
+	return ret;
+}
+
 int wifi_ubus_chan_switch(struct ubus_context *ubus_ctx, const char *ifname,
 			  struct chan_switch_param *param)
 {
diff --git a/src/wifi_ubus.h b/src/wifi_ubus.h
index e7868d313d03505d9d594fb257e23366d978808b..dffd2c22c9c077110f94b84ffae16b9bcea69ef2 100644
--- a/src/wifi_ubus.h
+++ b/src/wifi_ubus.h
@@ -62,6 +62,9 @@ int wifi_ubus_ap_status(struct ubus_context *ubus_ctx, const char *ifname, struc
 int wifi_ubus_radio_scanresults(struct ubus_context *ubus_ctx, const char *radio,
 				struct wifi_bss *bss, int *num);
 
+int wifi_ubus_channels_info(struct ubus_context *ubus_ctx, const char *radio,
+				struct chan_entry *ch_entry, int *num);
+
 int wifi_ubus_monitor_add_del(struct ubus_context *ubus_ctx, const char *ifname,
 			      uint8_t *macaddr, bool add);
 int wifi_ubus_monitor_add(struct ubus_context *ubus_ctx, const char *ifname, uint8_t *macaddr);