* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * 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
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #define CONT_REC_COMMAND_SIZE  80
 #define ENABLE_CONT_RECORDING  0x15
 #define DISABLE_CONT_RECORDING 0x16
+#define BUFFER_ALLOCATION      0x27
+#define START_DEBUG_RECORDING  0x29
+#define STOP_DEBUG_RECORDING   0x2A
 
 /*
  * struct iwl_continuous_record_mode - recording mode
                sizeof(struct iwl_continuous_record_mode)];
 } __packed;
 
+/* maximum fragments to be allocated per target of allocationId */
+#define IWL_BUFFER_LOCATION_MAX_FRAGS  2
+
+/**
+ * struct iwl_fragment_data single fragment structure
+ * @address: 64bit start address
+ * @size: size in bytes
+ */
+struct iwl_fragment_data {
+       __le64 address;
+       __le32 size;
+} __packed; /* FRAGMENT_STRUCTURE_API_S_VER_1 */
+
+/**
+ * struct iwl_buffer_allocation_cmd - buffer allocation command structure
+ * @allocation_id: id of the allocation
+ * @buffer_location: location of the buffer
+ * @num_frags: number of fragments
+ * @fragments: memory fragments
+ */
+struct iwl_buffer_allocation_cmd {
+       __le32 allocation_id;
+       __le32 buffer_location;
+       __le32 num_frags;
+       struct iwl_fragment_data fragments[IWL_BUFFER_LOCATION_MAX_FRAGS];
+} __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_1 */
+
 #endif /* __iwl_fw_api_debug_h__ */
 
                goto out;
        }
 
-       iwl_fw_dbg_stop_recording(fwrt->trans, ¶ms);
+       iwl_fw_dbg_stop_recording(fwrt, ¶ms);
 
        iwl_fw_error_dump(fwrt);
 
            fwrt->fw->dbg_dest_tlv) {
                /* wait before we collect the data till the DBGC stop */
                udelay(500);
-               iwl_fw_dbg_restart_recording(fwrt->trans, ¶ms);
+               iwl_fw_dbg_restart_recording(fwrt, ¶ms);
        }
 out:
        if (fwrt->ops && fwrt->ops->dump_end)
 
 #include "iwl-io.h"
 #include "file.h"
 #include "error-dump.h"
+#include "api/commands.h"
 
 /**
  * struct iwl_fw_dump_desc - describes the dump
                                        iwl_fw_dbg_get_trigger((fwrt)->fw,\
                                                               (trig)))
 
+static int iwl_fw_dbg_start_stop_hcmd(struct iwl_fw_runtime *fwrt, bool start)
+{
+       struct iwl_continuous_record_cmd cont_rec = {};
+       struct iwl_host_cmd hcmd = {
+               .id = LDBG_CONFIG_CMD,
+               .flags = CMD_ASYNC,
+               .data[0] = &cont_rec,
+               .len[0] = sizeof(cont_rec),
+       };
+
+       cont_rec.record_mode.enable_recording = start ?
+               cpu_to_le16(START_DEBUG_RECORDING) :
+               cpu_to_le16(STOP_DEBUG_RECORDING);
+
+       return iwl_trans_send_cmd(fwrt->trans, &hcmd);
+}
+
 static inline void
-iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
-                         struct iwl_fw_dbg_params *params)
+_iwl_fw_dbg_stop_recording(struct iwl_trans *trans,
+                          struct iwl_fw_dbg_params *params)
 {
        if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
                iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x100);
 }
 
 static inline void
-iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
-                            struct iwl_fw_dbg_params *params)
+iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt,
+                         struct iwl_fw_dbg_params *params)
+{
+       if (fwrt->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
+               _iwl_fw_dbg_stop_recording(fwrt->trans, params);
+       else
+               iwl_fw_dbg_start_stop_hcmd(fwrt, false);
+}
+
+static inline void
+_iwl_fw_dbg_restart_recording(struct iwl_trans *trans,
+                             struct iwl_fw_dbg_params *params)
 {
        if (WARN_ON(!params))
                return;
        }
 }
 
+static inline void
+iwl_fw_dbg_restart_recording(struct iwl_fw_runtime *fwrt,
+                            struct iwl_fw_dbg_params *params)
+{
+       if (fwrt->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560)
+               _iwl_fw_dbg_restart_recording(fwrt->trans, params);
+       else
+               iwl_fw_dbg_start_stop_hcmd(fwrt, true);
+}
+
 static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt)
 {
        fwrt->dump.conf = FW_DBG_INVALID;
 
         * the recording automatically before entering D3.  This can
         * be removed once the FW starts doing that.
         */
-       iwl_fw_dbg_stop_recording(mvm->fwrt.trans, NULL);
+       _iwl_fw_dbg_stop_recording(mvm->fwrt.trans, NULL);
 
        /* must be last -- this switches firmware state */
        ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
 
        trans_pcie->is_down = true;
 
        /* Stop dbgc before stopping device */
-       iwl_fw_dbg_stop_recording(trans, NULL);
+       _iwl_fw_dbg_stop_recording(trans, NULL);
 
        /* tell the device to stop sending interrupts */
        iwl_disable_interrupts(trans);
 
        trans_pcie->is_down = true;
 
        /* Stop dbgc before stopping device */
-       iwl_fw_dbg_stop_recording(trans, NULL);
+       _iwl_fw_dbg_stop_recording(trans, NULL);
 
        /* tell the device to stop sending interrupts */
        iwl_disable_interrupts(trans);