qed_dmae_info_free(p_hwfn);
                qed_dcbx_info_free(p_hwfn);
                qed_dbg_user_data_free(p_hwfn);
+               qed_fw_overlay_mem_free(p_hwfn, p_hwfn->fw_overlay_mem);
 
                /* Destroy doorbell recovery mechanism */
                qed_db_recovery_teardown(p_hwfn);
        if (rc)
                return rc;
 
+       qed_fw_overlay_init_ram(p_hwfn, p_ptt, p_hwfn->fw_overlay_mem);
+
        /* Pure runtime initializations - directly to the HW  */
        qed_int_igu_init_pure_rt(p_hwfn, p_ptt, true, true);
 
        u32 load_code, resp, param, drv_mb_param;
        bool b_default_mtu = true;
        struct qed_hwfn *p_hwfn;
-       int rc = 0, i;
+       const u32 *fw_overlays;
+       u32 fw_overlays_len;
        u16 ether_type;
+       int rc = 0, i;
 
        if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
                DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
                 */
                qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt);
 
+               fw_overlays = cdev->fw_data->fw_overlays;
+               fw_overlays_len = cdev->fw_data->fw_overlays_len;
+               p_hwfn->fw_overlay_mem =
+                   qed_fw_overlay_mem_alloc(p_hwfn, fw_overlays,
+                                            fw_overlays_len);
+               if (!p_hwfn->fw_overlay_mem) {
+                       DP_NOTICE(p_hwfn,
+                                 "Failed to allocate fw overlay memory\n");
+                       goto load_err;
+               }
+
                switch (load_code) {
                case FW_MSG_CODE_DRV_LOAD_ENGINE:
                        rc = qed_hw_init_common(p_hwfn, p_hwfn->p_main_ptt,
 
 #define SDM_OP_GEN_RESERVED_SHIFT      20
 };
 
+/* Physical memory descriptor */
+struct phys_mem_desc {
+       dma_addr_t phys_addr;
+       void *virt_addr;
+       u32 size;               /* In bytes */
+};
+
+/* Virtual memory descriptor */
+struct virt_mem_desc {
+       void *ptr;
+       u32 size;               /* In bytes */
+};
+
 /****************************************/
 /* Debug Tools HSI constants and macros */
 /****************************************/
        MAX_BIN_INIT_BUFFER_TYPE
 };
 
+/* FW overlay buffer header */
+struct fw_overlay_buf_hdr {
+       u32 data;
+#define FW_OVERLAY_BUF_HDR_STORM_ID_MASK  0xFF
+#define FW_OVERLAY_BUF_HDR_STORM_ID_SHIFT 0
+#define FW_OVERLAY_BUF_HDR_BUF_SIZE_MASK  0xFFFFFF
+#define FW_OVERLAY_BUF_HDR_BUF_SIZE_SHIFT 8
+};
+
 /* init array header: raw */
 struct init_array_raw_hdr {
        u32 data;
 void qed_set_rdma_error_level(struct qed_hwfn *p_hwfn,
                              struct qed_ptt *p_ptt,
                              u8 assert_level[NUM_STORMS]);
+/**
+ * @brief qed_fw_overlay_mem_alloc - Allocates and fills the FW overlay memory.
+ *
+ * @param p_hwfn - HW device data
+ * @param fw_overlay_in_buf - the input FW overlay buffer.
+ * @param buf_size - the size of the input FW overlay buffer in bytes.
+ *                  must be aligned to dwords.
+ * @param fw_overlay_out_mem - OUT: a pointer to the allocated overlays memory.
+ *
+ * @return a pointer to the allocated overlays memory,
+ * or NULL in case of failures.
+ */
+struct phys_mem_desc *
+qed_fw_overlay_mem_alloc(struct qed_hwfn *p_hwfn,
+                        const u32 * const fw_overlay_in_buf,
+                        u32 buf_size_in_bytes);
+
+/**
+ * @brief qed_fw_overlay_init_ram - Initializes the FW overlay RAM.
+ *
+ * @param p_hwfn - HW device data.
+ * @param p_ptt - ptt window used for writing the registers.
+ * @param fw_overlay_mem - the allocated FW overlay memory.
+ */
+void qed_fw_overlay_init_ram(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt,
+                            struct phys_mem_desc *fw_overlay_mem);
+
+/**
+ * @brief qed_fw_overlay_mem_free - Frees the FW overlay memory.
+ *
+ * @param p_hwfn - HW device data.
+ * @param fw_overlay_mem - the allocated FW overlay memory to free.
+ */
+void qed_fw_overlay_mem_free(struct qed_hwfn *p_hwfn,
+                            struct phys_mem_desc *fw_overlay_mem);
 
 /* Ystorm flow control mode. Use enum fw_flow_ctrl_mode */
 #define YSTORM_FLOW_CONTROL_MODE_OFFSET                        (IRO[0].base)
 
                qed_wr(p_hwfn, p_ptt, ram_addr, assert_level[storm_id]);
        }
 }
+
+#define PHYS_ADDR_DWORDS        DIV_ROUND_UP(sizeof(dma_addr_t), 4)
+#define OVERLAY_HDR_SIZE_DWORDS (sizeof(struct fw_overlay_buf_hdr) / 4)
+
+static u32 qed_get_overlay_addr_ram_addr(struct qed_hwfn *p_hwfn, u8 storm_id)
+{
+       switch (storm_id) {
+       case 0:
+               return TSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   TSTORM_OVERLAY_BUF_ADDR_OFFSET;
+       case 1:
+               return MSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   MSTORM_OVERLAY_BUF_ADDR_OFFSET;
+       case 2:
+               return USEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   USTORM_OVERLAY_BUF_ADDR_OFFSET;
+       case 3:
+               return XSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   XSTORM_OVERLAY_BUF_ADDR_OFFSET;
+       case 4:
+               return YSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   YSTORM_OVERLAY_BUF_ADDR_OFFSET;
+       case 5:
+               return PSEM_REG_FAST_MEMORY + SEM_FAST_REG_INT_RAM +
+                   PSTORM_OVERLAY_BUF_ADDR_OFFSET;
+
+       default:
+               return 0;
+       }
+}
+
+struct phys_mem_desc *qed_fw_overlay_mem_alloc(struct qed_hwfn *p_hwfn,
+                                              const u32 * const
+                                              fw_overlay_in_buf,
+                                              u32 buf_size_in_bytes)
+{
+       u32 buf_size = buf_size_in_bytes / sizeof(u32), buf_offset = 0;
+       struct phys_mem_desc *allocated_mem;
+
+       if (!buf_size)
+               return NULL;
+
+       allocated_mem = kcalloc(NUM_STORMS, sizeof(struct phys_mem_desc),
+                               GFP_KERNEL);
+       if (!allocated_mem)
+               return NULL;
+
+       memset(allocated_mem, 0, NUM_STORMS * sizeof(struct phys_mem_desc));
+
+       /* For each Storm, set physical address in RAM */
+       while (buf_offset < buf_size) {
+               struct phys_mem_desc *storm_mem_desc;
+               struct fw_overlay_buf_hdr *hdr;
+               u32 storm_buf_size;
+               u8 storm_id;
+
+               hdr =
+                   (struct fw_overlay_buf_hdr *)&fw_overlay_in_buf[buf_offset];
+               storm_buf_size = GET_FIELD(hdr->data,
+                                          FW_OVERLAY_BUF_HDR_BUF_SIZE);
+               storm_id = GET_FIELD(hdr->data, FW_OVERLAY_BUF_HDR_STORM_ID);
+               storm_mem_desc = allocated_mem + storm_id;
+               storm_mem_desc->size = storm_buf_size * sizeof(u32);
+
+               /* Allocate physical memory for Storm's overlays buffer */
+               storm_mem_desc->virt_addr =
+                   dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+                                      storm_mem_desc->size,
+                                      &storm_mem_desc->phys_addr, GFP_KERNEL);
+               if (!storm_mem_desc->virt_addr)
+                       break;
+
+               /* Skip overlays buffer header */
+               buf_offset += OVERLAY_HDR_SIZE_DWORDS;
+
+               /* Copy Storm's overlays buffer to allocated memory */
+               memcpy(storm_mem_desc->virt_addr,
+                      &fw_overlay_in_buf[buf_offset], storm_mem_desc->size);
+
+               /* Advance to next Storm */
+               buf_offset += storm_buf_size;
+       }
+
+       /* If memory allocation has failed, free all allocated memory */
+       if (buf_offset < buf_size) {
+               qed_fw_overlay_mem_free(p_hwfn, allocated_mem);
+               return NULL;
+       }
+
+       return allocated_mem;
+}
+
+void qed_fw_overlay_init_ram(struct qed_hwfn *p_hwfn,
+                            struct qed_ptt *p_ptt,
+                            struct phys_mem_desc *fw_overlay_mem)
+{
+       u8 storm_id;
+
+       for (storm_id = 0; storm_id < NUM_STORMS; storm_id++) {
+               struct phys_mem_desc *storm_mem_desc =
+                   (struct phys_mem_desc *)fw_overlay_mem + storm_id;
+               u32 ram_addr, i;
+
+               /* Skip Storms with no FW overlays */
+               if (!storm_mem_desc->virt_addr)
+                       continue;
+
+               /* Calculate overlay RAM GRC address of current PF */
+               ram_addr = qed_get_overlay_addr_ram_addr(p_hwfn, storm_id) +
+                          sizeof(dma_addr_t) * p_hwfn->rel_pf_id;
+
+               /* Write Storm's overlay physical address to RAM */
+               for (i = 0; i < PHYS_ADDR_DWORDS; i++, ram_addr += sizeof(u32))
+                       qed_wr(p_hwfn, p_ptt, ram_addr,
+                              ((u32 *)&storm_mem_desc->phys_addr)[i]);
+       }
+}
+
+void qed_fw_overlay_mem_free(struct qed_hwfn *p_hwfn,
+                            struct phys_mem_desc *fw_overlay_mem)
+{
+       u8 storm_id;
+
+       if (!fw_overlay_mem)
+               return;
+
+       for (storm_id = 0; storm_id < NUM_STORMS; storm_id++) {
+               struct phys_mem_desc *storm_mem_desc =
+                   (struct phys_mem_desc *)fw_overlay_mem + storm_id;
+
+               /* Free Storm's physical memory */
+               if (storm_mem_desc->virt_addr)
+                       dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+                                         storm_mem_desc->size,
+                                         storm_mem_desc->virt_addr,
+                                         storm_mem_desc->phys_addr);
+       }
+
+       /* Free allocated virtual memory */
+       kfree(fw_overlay_mem);
+}