iwlwifi-objs           += pcie/trans-gen2.o pcie/tx-gen2.o
 iwlwifi-$(CONFIG_IWLDVM) += cfg/1000.o cfg/2000.o cfg/5000.o cfg/6000.o
 iwlwifi-$(CONFIG_IWLMVM) += cfg/7000.o cfg/8000.o cfg/9000.o cfg/22000.o
+iwlwifi-objs           += iwl-dbg-tlv.o
 iwlwifi-objs           += iwl-trans.o
 iwlwifi-objs           += fw/notif-wait.o
 iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o fw/dbg.o
 
        } u;
 };
 
+#define IWL_UCODE_INI_TLV_GROUP        BIT(24)
+
 /*
  * new TLV uCode file layout
  *
        IWL_UCODE_TLV_FW_GSCAN_CAPA     = 50,
        IWL_UCODE_TLV_FW_MEM_SEG        = 51,
        IWL_UCODE_TLV_IML               = 52,
+       IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION    = IWL_UCODE_INI_TLV_GROUP | 0x1,
+       IWL_UCODE_TLV_TYPE_HCMD                 = IWL_UCODE_INI_TLV_GROUP | 0x2,
+       IWL_UCODE_TLV_TYPE_REGIONS              = IWL_UCODE_INI_TLV_GROUP | 0x3,
+       IWL_UCODE_TLV_TYPE_TRIGGERS             = IWL_UCODE_INI_TLV_GROUP | 0x4,
+       IWL_UCODE_TLV_TYPE_DEBUG_FLOW           = IWL_UCODE_INI_TLV_GROUP | 0x5,
 
        /* TLVs 0x1000-0x2000 are for internal driver usage */
        IWL_UCODE_TLV_FW_DBG_DUMP_LST   = 0x1000,
 
--- /dev/null
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright (C) 2018 Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <linux/firmware.h>
+#include "iwl-trans.h"
+#include "iwl-dbg-tlv.h"
+
+void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv)
+{
+       struct iwl_apply_point_data *data;
+       struct iwl_fw_ini_header *header = (void *)&tlv->data[0];
+       u32 apply_point = le32_to_cpu(header->apply_point);
+
+       int copy_size = le32_to_cpu(tlv->length) + sizeof(*tlv);
+
+       if (WARN_ONCE(apply_point >= IWL_FW_INI_APPLY_NUM,
+                     "Invalid apply point id %d\n", apply_point))
+               return;
+
+       data = &trans->apply_points[apply_point];
+
+       /*
+        * Make sure we still have room to copy this TLV. Offset points to the
+        * location the last copy ended.
+        */
+       if (WARN_ONCE(data->offset + copy_size > data->size,
+                     "Not enough memory for apply point %d\n",
+                     apply_point))
+               return;
+
+       memcpy(data->data + data->offset, (void *)tlv, copy_size);
+       data->offset += copy_size;
+}
+
+void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data)
+{
+       struct iwl_ucode_tlv *tlv;
+       u32 size[IWL_FW_INI_APPLY_NUM] = {0};
+       int i;
+
+       while (len >= sizeof(*tlv)) {
+               u32 tlv_len, tlv_type, apply;
+               struct iwl_fw_ini_header *hdr;
+
+               len -= sizeof(*tlv);
+               tlv = (void *)data;
+
+               tlv_len = le32_to_cpu(tlv->length);
+               tlv_type = le32_to_cpu(tlv->type);
+
+               if (len < tlv_len)
+                       return;
+
+               len -= ALIGN(tlv_len, 4);
+               data += sizeof(*tlv) + ALIGN(tlv_len, 4);
+
+               if (!(tlv_type & IWL_UCODE_INI_TLV_GROUP))
+                       continue;
+
+               hdr = (void *)&tlv->data[0];
+               apply = le32_to_cpu(hdr->apply_point);
+
+               if (WARN_ON(apply >= IWL_FW_INI_APPLY_NUM))
+                       continue;
+
+               size[apply] += sizeof(*tlv) + tlv_len;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(size); i++) {
+               void *mem;
+
+               if (!size[i])
+                       continue;
+
+               mem = kzalloc(size[i], GFP_KERNEL);
+
+               if (!mem) {
+                       IWL_ERR(trans, "No memory for apply point %d\n", i);
+                       return;
+               }
+
+               trans->apply_points[i].data = mem;
+               trans->apply_points[i].size = size[i];
+       }
+}
+
+void iwl_fw_dbg_free(struct iwl_trans *trans)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(trans->apply_points); i++) {
+               kfree(trans->apply_points[i].data);
+               trans->apply_points[i].size = 0;
+               trans->apply_points[i].offset = 0;
+       }
+}
 
--- /dev/null
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <linuxwifi@intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright (C) 2018 Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_dbg_tlv_h__
+#define __iwl_dbg_tlv_h__
+
+#include <linux/device.h>
+#include <linux/types.h>
+
+/**
+ * struct iwl_apply_point_data
+ * @data: start address of this apply point data
+ * @size total size of the data
+ * @offset: current offset of the copied data
+ */
+struct iwl_apply_point_data {
+       void *data;
+       int size;
+       int offset;
+};
+
+struct iwl_trans;
+void iwl_fw_dbg_free(struct iwl_trans *trans);
+void iwl_fw_dbg_copy_tlv(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv);
+void iwl_alloc_dbg_tlv(struct iwl_trans *trans, size_t len, const u8 *data);
+
+#endif /* __iwl_dbg_tlv_h__*/
 
 #include "iwl-op-mode.h"
 #include "iwl-agn-hw.h"
 #include "fw/img.h"
+#include "iwl-dbg-tlv.h"
 #include "iwl-config.h"
 #include "iwl-modparams.h"
 
 
        len -= sizeof(*ucode);
 
+       if (iwlwifi_mod_params.enable_ini)
+               iwl_alloc_dbg_tlv(drv->trans, len, data);
+
        while (len >= sizeof(*tlv)) {
                len -= sizeof(*tlv);
                tlv = (void *)data;
                                return -ENOMEM;
                        break;
                        }
+               case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
+               case IWL_UCODE_TLV_TYPE_HCMD:
+               case IWL_UCODE_TLV_TYPE_REGIONS:
+               case IWL_UCODE_TLV_TYPE_TRIGGERS:
+               case IWL_UCODE_TLV_TYPE_DEBUG_FLOW:
+                       if (iwlwifi_mod_params.enable_ini)
+                               iwl_fw_dbg_copy_tlv(drv->trans, tlv);
                default:
                        IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
                        break;
        debugfs_remove_recursive(drv->dbgfs_drv);
 #endif
 
+       iwl_fw_dbg_free(drv->trans);
+
        kfree(drv);
 }
 
 module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable, uint, 0644);
 MODULE_PARM_DESC(uapsd_disable,
                 "disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3)");
+module_param_named(enable_ini, iwlwifi_mod_params.enable_ini,
+                  bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(enable_ini,
+                "Enable debug INI TLV FW debug infrastructure (default: 0");
 
 /*
  * set bt_coex_active to true, uCode will do kill/defer
 
  * @fw_monitor: allow to use firmware monitor
  * @disable_11ac: disable VHT capabilities, default = false.
  * @remove_when_gone: remove an inaccessible device from the PCIe bus.
+ * @enable_ini: enable new FW debug infratructure (INI TLVs)
  */
 struct iwl_mod_params {
        int swcrypto;
         */
        bool disable_11ax;
        bool remove_when_gone;
+       bool enable_ini;
 };
 
 #endif /* #__iwl_modparams_h__ */
 
 #include "iwl-op-mode.h"
 #include "fw/api/cmdhdr.h"
 #include "fw/api/txq.h"
+#include "fw/api/dbg-tlv.h"
+#include "iwl-dbg-tlv.h"
 
 /**
  * DOC: Transport layer - what is it ?
        struct lockdep_map sync_cmd_lockdep_map;
 #endif
 
+       struct iwl_apply_point_data apply_points[IWL_FW_INI_APPLY_NUM];
+
        const struct iwl_fw_dbg_dest_tlv_v1 *dbg_dest_tlv;
        const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
        struct iwl_fw_dbg_trigger_tlv * const *dbg_trigger_tlv;