&dev_iter_data);
 }
 
+static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload,
+                              u8 length)
+{
+       struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+       dm_info->scan_density = payload[0];
+
+       rtw_dbg(rtwdev, RTW_DBG_FW, "scan.density = %x\n",
+               dm_info->scan_density);
+}
+
 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
 {
        struct rtw_c2h_cmd *c2h;
        case C2H_WLAN_RFON:
                complete(&rtwdev->lps_leave_check);
                break;
+       case C2H_SCAN_RESULT:
+               complete(&rtwdev->fw_scan_density);
+               rtw_fw_scan_result(rtwdev, c2h->payload, len);
+               break;
        default:
                /* pass offset for further operation */
                *((u32 *)skb->cb) = pkt_offset;
 
        rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 }
+
+void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
+{
+       u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+       SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SCAN);
+       SET_SCAN_START(h2c_pkt, start);
+
+       rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
 
 #define BCN_FILTER_CONNECTED           2
 #define BCN_FILTER_NOTIFY_BEACON_LOSS  3
 
+#define SCAN_NOTIFY_TIMEOUT  msecs_to_jiffies(10)
+
 enum rtw_c2h_cmd_id {
        C2H_CCX_TX_RPT = 0x03,
        C2H_BT_INFO = 0x09,
        C2H_WLAN_INFO = 0x27,
        C2H_WLAN_RFON = 0x32,
        C2H_BCN_FILTER_NOTIFY = 0x36,
+       C2H_SCAN_RESULT = 0x38,
        C2H_HW_FEATURE_DUMP = 0xfd,
        C2H_HALMAC = 0xff,
 };
        FW_FEATURE_LCLK = BIT(2),
        FW_FEATURE_PG = BIT(3),
        FW_FEATURE_BCN_FILTER = BIT(5),
+       FW_FEATURE_NOTIFY_SCAN = BIT(6),
        FW_FEATURE_MAX = BIT(31),
 };
 
 #define H2C_CMD_BCN_FILTER_OFFLOAD_P0  0x56
 #define H2C_CMD_BCN_FILTER_OFFLOAD_P1  0x57
 #define H2C_CMD_WL_PHY_INFO            0x58
+#define H2C_CMD_SCAN                   0x59
 
 #define H2C_CMD_COEX_TDMA_TYPE         0x60
 #define H2C_CMD_QUERY_BT_INFO          0x61
 #define SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, value)                \
        le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(13, 4))
 
+#define SET_SCAN_START(h2c_pkt, value)                                        \
+       le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+
 #define SET_PWR_MODE_SET_MODE(h2c_pkt, value)                                  \
        le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(14, 8))
 #define SET_PWR_MODE_SET_RLBM(h2c_pkt, value)                                  \
 void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev);
 int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
                     u32 *buffer);
-
+void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
 #endif
 
        rtw_vif_port_config(rtwdev, rtwvif, config);
 
        rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
+       rtw_core_fw_scan_notify(rtwdev, true);
 
        set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
        set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
        clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
        clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
 
+       rtw_core_fw_scan_notify(rtwdev, false);
+
        ether_addr_copy(rtwvif->mac_addr, vif->addr);
        config |= PORT_SET_MAC_ADDR;
        rtw_vif_port_config(rtwdev, rtwvif, config);
 
        return ret;
 }
 
+void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
+{
+       if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_NOTIFY_SCAN))
+               return;
+
+       if (start) {
+               rtw_fw_scan_notify(rtwdev, true);
+       } else {
+               reinit_completion(&rtwdev->fw_scan_density);
+               rtw_fw_scan_notify(rtwdev, false);
+               if (!wait_for_completion_timeout(&rtwdev->fw_scan_density,
+                                                SCAN_NOTIFY_TIMEOUT))
+                       rtw_warn(rtwdev, "firmware failed to report density after scan\n");
+       }
+}
+
 int rtw_core_start(struct rtw_dev *rtwdev)
 {
        int ret;
 
        init_waitqueue_head(&rtwdev->coex.wait);
        init_completion(&rtwdev->lps_leave_check);
+       init_completion(&rtwdev->fw_scan_density);
 
        rtwdev->sec.total_cam_num = 32;
        rtwdev->hal.current_channel = 1;
 
        struct rtw_iqk_info iqk;
        struct rtw_gapk_info gapk;
        bool is_bt_iqk_timeout;
+
+       u8 scan_density;
 };
 
 struct rtw_efuse {
        struct rtw_wow_param wow;
 
        bool need_rfk;
+       struct completion fw_scan_density;
 
        /* hci related data, must be last */
        u8 priv[] __aligned(sizeof(void *));
 void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
                    bool fw_exist);
 void rtw_fw_recovery(struct rtw_dev *rtwdev);
+void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
 int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
                const char *prefix_str);
 int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size,