diff --git a/MAINTAINERS b/MAINTAINERS
index 7cc8860..5381f0c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -831,6 +831,11 @@ F: drivers/compress/isal/
 F: doc/guides/compressdevs/isal.rst
 F: doc/guides/compressdevs/features/isal.ini
 
+Intel QuickAssist
+M: Fiona Trahe <fiona.trahe@intel.com>
+F: drivers/compress/qat/
+F: drivers/common/qat/
+F: doc/guides/compressdevs/features/qat.ini
 
 Eventdev Drivers
 ----------------
diff --git a/config/common_base b/config/common_base
index f456f95..b85c990 100644
--- a/config/common_base
+++ b/config/common_base
@@ -487,6 +487,8 @@ CONFIG_RTE_LIBRTE_PMD_QAT=y
 # Max. number of QuickAssist devices, which can be detected and attached
 #
 CONFIG_RTE_PMD_QAT_MAX_PCI_DEVICES=48
+CONFIG_RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS=16
+CONFIG_RTE_PMD_QAT_COMP_IM_BUFFER_SIZE=131072
 #
 # Compile PMD for virtio crypto devices
 #
diff --git a/doc/guides/compressdevs/features/qat.ini b/doc/guides/compressdevs/features/qat.ini
new file mode 100644
index 0000000..d99b5de
--- /dev/null
+++ b/doc/guides/compressdevs/features/qat.ini
@@ -0,0 +1,22 @@
+;
+; Refer to default.ini for the full list of available PMD features.
+;
+; Supported features of 'QAT' compression driver.
+;
+[Features]
+HW Accelerated = Y
+CPU SSE        =
+CPU AVX        =
+CPU AVX2       =
+CPU AVX512     =
+CPU NEON       =
+Stateful       =
+By-Pass        =
+Chained mbufs  = Y
+Deflate        = Y
+LZS            =
+Adler32        = Y
+Crc32          = Y
+Adler32&Crc32  = Y
+Fixed          = Y
+Dynamic        = Y
diff --git a/drivers/common/qat/Makefile b/drivers/common/qat/Makefile
index c023c34..a8545f4 100644
--- a/drivers/common/qat/Makefile
+++ b/drivers/common/qat/Makefile
@@ -6,29 +6,24 @@ include $(RTE_SDK)/mk/rte.vars.mk
 # libcrypto detection
 LIBCRYPTO := $(shell pkg-config --exists libcrypto 1>&2 2> /dev/null; echo $$?)
 
-# library name
-LIB = librte_pmd_qat.a
-
-# library version
-LIBABIVER := 1
-
-# build flags
-CFLAGS += $(WERROR_FLAGS)
-CFLAGS += -O3
-
 # build directories
 QAT_CRYPTO_DIR := $(RTE_SDK)/drivers/crypto/qat
+QAT_COMPRESS_DIR := $(RTE_SDK)/drivers/compress/qat
 
 # external library include paths
 CFLAGS += -I$(SRCDIR)/qat_adf
 CFLAGS += -I$(SRCDIR)
+
 CFLAGS += -I$(QAT_CRYPTO_DIR)
+CFLAGS += -I$(QAT_COMPRESS_DIR)
 
-# library common source files
-SRCS-y += qat_device.c
-SRCS-y += qat_common.c
-SRCS-y += qat_logs.c
-SRCS-y += qat_qp.c
+ifeq ($(CONFIG_RTE_LIBRTE_COMPRESSDEV),y)
+	CFLAGS += -DALLOW_EXPERIMENTAL_API
+	LDLIBS += -lrte_compressdev
+	SRCS-y += $(QAT_COMPRESS_DIR)/qat_comp.c
+	SRCS-y += $(QAT_COMPRESS_DIR)/qat_comp_pmd.c
+	build_qat = yes
+endif
 
 ifeq ($(LIBCRYPTO),0)
 	LDLIBS += -lrte_cryptodev
@@ -37,15 +32,38 @@ ifeq ($(LIBCRYPTO),0)
 	SRCS-y += $(QAT_CRYPTO_DIR)/qat_sym.c
 	SRCS-y += $(QAT_CRYPTO_DIR)/qat_sym_session.c
 	SRCS-y += $(QAT_CRYPTO_DIR)/qat_sym_pmd.c
+	build_qat = yes
 endif
 
-LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool
-LDLIBS += -lrte_pci -lrte_bus_pci
 
-# export include files
-SYMLINK-y-include +=
 
-# versioning export map
-EXPORT_MAP := qat/rte_pmd_qat_version.map
+ifdef build_qat
+
+	# library name
+	LIB = librte_pmd_qat.a
+
+	# library version
+	LIBABIVER := 1
+
+	# build flags
+	CFLAGS += $(WERROR_FLAGS)
+	CFLAGS += -O3
+
+	# library common source files
+	SRCS-y += qat_device.c
+	SRCS-y += qat_common.c
+	SRCS-y += qat_logs.c
+	SRCS-y += qat_qp.c
+
+	LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool
+	LDLIBS += -lrte_pci -lrte_bus_pci
+
+	# export include files
+	SYMLINK-y-include +=
+
+	# versioning export map
+	EXPORT_MAP := qat/rte_pmd_qat_version.map
+
+endif
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/common/qat/qat_adf/icp_qat_fw_comp.h b/drivers/common/qat/qat_adf/icp_qat_fw_comp.h
new file mode 100644
index 0000000..4ad1d30
--- /dev/null
+++ b/drivers/common/qat/qat_adf/icp_qat_fw_comp.h
@@ -0,0 +1,586 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2018 Intel Corporation
+ */
+#ifndef _ICP_QAT_FW_COMP_H_
+#define _ICP_QAT_FW_COMP_H_
+
+#include "icp_qat_fw.h"
+
+/* Next curr slice */
+#define ICP_QAT_FW_COMN_NEXT_ID_BITPOS 4
+#define ICP_QAT_FW_COMN_NEXT_ID_MASK 0xF0
+#define ICP_QAT_FW_COMN_CURR_ID_BITPOS 0
+#define ICP_QAT_FW_COMN_CURR_ID_MASK 0x0F
+
+#define ICP_QAT_FW_COMN_NEXT_ID_SET_2(next_curr_id, val)                       \
+	do {                                                                   \
+		(next_curr_id) =                                               \
+		    (((next_curr_id)&ICP_QAT_FW_COMN_CURR_ID_MASK) |           \
+		     (((val) << ICP_QAT_FW_COMN_NEXT_ID_BITPOS) &              \
+		      ICP_QAT_FW_COMN_NEXT_ID_MASK))                           \
+	} while (0)
+
+#define ICP_QAT_FW_COMN_CURR_ID_SET_2(next_curr_id, val)                       \
+	do {                                                                   \
+		(next_curr_id) =                                               \
+		    (((next_curr_id)&ICP_QAT_FW_COMN_NEXT_ID_MASK) |           \
+		     ((val)&ICP_QAT_FW_COMN_CURR_ID_MASK))                     \
+	} while (0)
+
+/* Private defines */
+#define QAT_COMPRESSION_DIR_BITPOS 4
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression direction bit position
+ */
+
+#define QAT_COMPRESSION_DIR_MASK 0x7
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression direction mask (three bits)
+ */
+
+#define QAT_COMPRESSION_DELAYED_MATCH_BITPOS 16
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression delayed match bit position
+ */
+
+#define QAT_COMPRESSION_DELAYED_MATCH_MASK 0x1
+/**< @ingroup icp_qat_hw_defs
+ * Define for the delayed match mask (one bit)
+ */
+
+#define QAT_COMPRESSION_ALGO_BITPOS 31
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression algorithm bit position
+ */
+
+#define QAT_COMPRESSION_ALGO_MASK 0x1
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression algorithm mask (one bit)
+ */
+
+#define QAT_COMPRESSION_DEPTH_BITPOS 28
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression depth bit position
+ */
+
+#define QAT_COMPRESSION_DEPTH_MASK 0x7
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression depth mask (three bits)
+ */
+
+#define QAT_COMPRESSION_FILE_TYPE_BITPOS 24
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression file type bit position
+ */
+
+#define QAT_COMPRESSION_FILE_TYPE_MASK 0xF
+/**< @ingroup icp_qat_hw_defs
+ * Define for the compression file type mask (four bits)
+ */
+
+#define ICP_QAT_FW_COMP_NOT_SOP 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that a request is NOT Start of Packet
+ */
+
+#define ICP_QAT_FW_COMP_SOP 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that a request IS Start of Packet
+ */
+
+#define ICP_QAT_FW_COMP_NOT_EOP 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that a request is NOT Start of Packet
+ */
+
+#define ICP_QAT_FW_COMP_EOP 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that a request IS End of Packet
+ */
+
+#define ICP_QAT_FW_COMP_NOT_BFINAL 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing to indicate firmware this is not the last block
+ */
+
+#define ICP_QAT_FW_COMP_BFINAL 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing to indicate firmware this is the last block
+ */
+
+#define ICP_QAT_FW_COMP_NO_MCA 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag indicating that NO mca check is to be performed on the request
+ */
+
+#define ICP_QAT_FW_COMP_MCA 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag indicating that an mca check IS to be performed on the request
+ */
+
+#define ICP_QAT_FW_COMP_SOP_BITPOS 0
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for SOP
+ */
+
+#define ICP_QAT_FW_COMP_SOP_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ *  One bit mask used to determine SOP
+ */
+
+#define ICP_QAT_FW_COMP_EOP_BITPOS 1
+/**< @ingroup icp_qat_fw_comp
+ *  Starting bit position for EOP
+ */
+
+#define ICP_QAT_FW_COMP_EOP_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ *  One bit mask used to determine EOP
+ */
+
+#define ICP_QAT_FW_COMP_BFINAL_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ *  One bit mask for the bfinal bit
+ */
+
+#define ICP_QAT_FW_COMP_BFINAL_BITPOS 6
+/**< @ingroup icp_qat_fw_comp
+ *  Starting bit position for the bfinal bit
+ */
+
+#define ICP_QAT_FW_COMP_MCA_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ *  One bit mask for the MCA bit
+ */
+
+#define ICP_QAT_FW_COMP_MCA_BITPOS 16
+/**< @ingroup icp_qat_fw_comp
+ *  Starting bit position for the MCA bit
+ */
+
+#define ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(dir, delayed, algo, depth,         \
+					    filetype)                          \
+	((((dir)&QAT_COMPRESSION_DIR_MASK) << QAT_COMPRESSION_DIR_BITPOS) |    \
+	 (((delayed)&QAT_COMPRESSION_DELAYED_MATCH_MASK)                       \
+	  << QAT_COMPRESSION_DELAYED_MATCH_BITPOS) |                           \
+	 (((algo)&QAT_COMPRESSION_ALGO_MASK) << QAT_COMPRESSION_ALGO_BITPOS) | \
+	 (((depth)&QAT_COMPRESSION_DEPTH_MASK)                                 \
+	  << QAT_COMPRESSION_DEPTH_BITPOS) |                                   \
+	 (((filetype)&QAT_COMPRESSION_FILE_TYPE_MASK)                          \
+	  << QAT_COMPRESSION_FILE_TYPE_BITPOS))
+
+/**< Flag usage */
+
+#define ICP_QAT_FW_COMP_STATELESS_SESSION 0
+/**< @ingroup icp_qat_fw_comp
+ *  Flag representing that session is stateless
+ */
+
+#define ICP_QAT_FW_COMP_STATEFUL_SESSION 1
+/**< @ingroup icp_qat_fw_comp
+ *  Flag representing that session is stateful
+ */
+
+#define ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that autoselectbest is NOT used
+ */
+
+#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that autoselectbest is used
+ */
+
+#define ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that enhanced autoselectbest is NOT used
+ */
+
+#define ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that enhanced autoselectbest is used
+ */
+
+#define ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that enhanced autoselectbest is NOT used
+ */
+
+#define ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing that enhanced autoselectbest is used
+ */
+
+#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF 1
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing secure RAM from being used as
+ * an intermediate buffer is DISABLED.
+ */
+
+#define ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF 0
+/**< @ingroup icp_qat_fw_comp
+ * Flag representing secure RAM from being used as
+ * an intermediate buffer is ENABLED.
+ */
+
+/**< Flag mask & bit position */
+
+#define ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS 2
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for the session type
+ */
+
+#define ICP_QAT_FW_COMP_SESSION_TYPE_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ * One bit mask used to determine the session type
+ */
+
+#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS 3
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for auto select best
+ */
+
+#define ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ * One bit mask for auto select best
+ */
+
+#define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS 4
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for enhanced auto select best
+ */
+
+#define ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ * One bit mask for enhanced auto select best
+ */
+
+#define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS 5
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for disabling type zero header write back
+ * when Enhanced autoselect best is enabled. If set firmware does
+ * not return type0 store block header, only copies src to dest.
+ * (if best output is Type0)
+ */
+
+#define ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ * One bit mask for auto select best
+ */
+
+#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS 7
+/**< @ingroup icp_qat_fw_comp
+ * Starting bit position for flag used to disable secure ram from
+ *  being used as an intermediate buffer.
+ */
+
+#define ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK 0x1
+/**< @ingroup icp_qat_fw_comp
+ * One bit mask for disable secure ram for use as an intermediate
+ * buffer.
+ */
+
+#define ICP_QAT_FW_COMP_FLAGS_BUILD(sesstype, autoselect, enhanced_asb,        \
+				    ret_uncomp, secure_ram)                    \
+	((((sesstype)&ICP_QAT_FW_COMP_SESSION_TYPE_MASK)                       \
+	  << ICP_QAT_FW_COMP_SESSION_TYPE_BITPOS) |                            \
+	 (((autoselect)&ICP_QAT_FW_COMP_AUTO_SELECT_BEST_MASK)                 \
+	  << ICP_QAT_FW_COMP_AUTO_SELECT_BEST_BITPOS) |                        \
+	 (((enhanced_asb)&ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_MASK)      \
+	  << ICP_QAT_FW_COMP_ENHANCED_AUTO_SELECT_BEST_BITPOS) |               \
+	 (((ret_uncomp)&ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_MASK)    \
+	  << ICP_QAT_FW_COMP_RET_DISABLE_TYPE0_HEADER_DATA_BITPOS) |           \
+	 (((secure_ram)&ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_MASK)  \
+	  << ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_AS_INTMD_BUF_BITPOS))
+
+enum icp_qat_hw_compression_algo {
+	ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE = 0,  /*!< Deflate compression */
+	ICP_QAT_HW_COMPRESSION_ALGO_LZS = 1,      /*!< LZS compression */
+	ICP_QAT_HW_COMPRESSION_ALGO_DELIMITER = 2 /**< Delimiter type */
+};
+
+enum icp_qat_hw_compression_file_type {
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_0 = 0,
+	/*!< Use Static Trees */
+
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_1 = 1,
+	/*!< Use Semi-Dynamic Trees at offset 0 */
+
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_2 = 2,
+	/*!< Use Semi-Dynamic Trees at offset 320 */
+
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_3 = 3,
+	/*!< Use Semi-Dynamic Trees at offset 640 */
+
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_4 = 4,
+	/*!< Use Semi-Dynamic Trees at offset 960 */
+
+	ICP_QAT_HW_COMPRESSION_FILE_TYPE_DELIMITER = 5
+	/**< Delimiter type */
+};
+
+enum icp_qat_hw_compression_depth {
+	ICP_QAT_HW_COMPRESSION_DEPTH_1 = 0,
+	/*!< Search depth 1 (Fastest least exhaustive) */
+
+	ICP_QAT_HW_COMPRESSION_DEPTH_4 = 1,
+	/*!< Search depth 4 */
+
+	ICP_QAT_HW_COMPRESSION_DEPTH_8 = 2,
+	/*!< Search depth 8 */
+
+	ICP_QAT_HW_COMPRESSION_DEPTH_16 = 3,
+	/*!< Search depth 16 (Slowest, most exhaustive) */
+
+	ICP_QAT_HW_COMPRESSION_DEPTH_DELIMITER = 4
+	/**< Delimiter type */
+};
+
+enum icp_qat_hw_compression_delayed_match {
+	ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED = 0,
+	/*!< Delayed match disabled */
+
+	ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED = 1,
+	/*!< Delayed match enabled
+	 * Note: This is the only valid mode - refer to CPM1.6 SAS
+	 */
+
+	ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DELIMITER = 2
+	/**< Delimiter type */
+};
+
+enum icp_qat_fw_comp_cmd_id {
+	ICP_QAT_FW_COMP_CMD_STATIC = 0,
+	/*!< Static Compress Request */
+
+	ICP_QAT_FW_COMP_CMD_DYNAMIC = 1,
+	/*!< Dynamic Compress Request */
+
+	ICP_QAT_FW_COMP_CMD_DECOMPRESS = 2,
+	/*!< Decompress Request */
+
+	ICP_QAT_FW_COMP_CMD_DELIMITER
+	/**< Delimiter type */
+};
+
+enum { ICP_QAT_HW_COMPRESSION_DIR_COMPRESS = 0,    /*!< Compression */
+	ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS = 1, /*!< Decompression */
+	ICP_QAT_HW_COMPRESSION_DIR_DELIMITER = 2   /**< Delimiter type */
+} icp_qat_hw_compression_direction;
+
+enum qat_comp_request {
+	QAT_COMP_REQUEST_STATIC_COMP_STATELESS,
+	QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS,
+	QAT_COMP_REQUEST_DECOMPRESS,
+	REQ_COMP_END
+};
+
+union icp_qat_fw_comp_req_hdr_cd_pars {
+	/**< LWs 2-5 */
+	struct {
+		uint64_t content_desc_addr;
+		/**< Address of the content descriptor */
+
+		uint16_t content_desc_resrvd1;
+		/**< Content descriptor reserved field */
+
+		uint8_t content_desc_params_sz;
+		/**< Size of the content descriptor parameters in quad words.
+		 * These parameters describe the session setup configuration
+		 * info for the slices that this request relies upon i.e.
+		 * the configuration word and cipher key needed by the cipher
+		 * slice if there is a request for cipher processing.
+		 */
+
+		uint8_t   content_desc_hdr_resrvd2;
+		/**< Content descriptor reserved field */
+
+		uint32_t	content_desc_resrvd3;
+		/**< Content descriptor reserved field */
+	} s;
+
+	struct {
+		uint32_t comp_slice_cfg_word[ICP_QAT_FW_NUM_LONGWORDS_2];
+		/* Compression Slice Config Word */
+
+		uint32_t content_desc_resrvd4;
+		/**< Content descriptor reserved field */
+
+	} sl;
+
+};
+
+struct icp_qat_fw_comp_req_params {
+	/**< LW 14 */
+	uint32_t comp_len;
+	/**< Size of input to process in bytes Note:  Only EOP requests can be
+	 * odd for decompression. IA must set LSB to zero for odd sized
+	 * intermediate inputs
+	 */
+
+	/**< LW 15 */
+	uint32_t out_buffer_sz;
+	/**< Size of output buffer in bytes */
+
+	/**< LW 16 */
+	uint32_t initial_crc32;
+	/**< CRC of previously processed bytes */
+
+	/**< LW 17 */
+	uint32_t initial_adler;
+	/**< Adler of previously processed bytes */
+
+	/**< LW 18 */
+	uint32_t req_par_flags;
+
+	/**< LW 19 */
+	uint32_t rsrvd;
+};
+
+struct icp_qat_fw_xlt_req_params {
+	/**< LWs 20-21 */
+	uint64_t inter_buff_ptr;
+	/**< This field specifies the physical address of an intermediate
+	 *  buffer SGL array. The array contains a pair of 64-bit
+	 *  intermediate buffer pointers to SGL buffer descriptors, one pair
+	 *  per CPM. Please refer to the CPM1.6 Firmware Interface HLD
+	 *  specification for more details.
+	 */
+};
+
+struct icp_qat_fw_comp_cd_hdr {
+	/**< LW 24 */
+	uint16_t ram_bank_flags;
+	/**< Flags to show which ram banks to access */
+
+	uint8_t comp_cfg_offset;
+	/**< Quad word offset from the content descriptor parameters address
+	 * to the parameters for the compression processing
+	 */
+
+	uint8_t next_curr_id;
+	/**< This field combines the next and current id (each four bits) -
+	 * the next id is the most significant nibble.
+	 * Next Id:  Set to the next slice to pass the compressed data through.
+	 * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through
+	 * anymore slices after compression
+	 * Current Id: Initialised with the compression slice type
+	 */
+
+	/**< LW 25 */
+	uint32_t resrvd;
+
+	/**< LWs 26-27 */
+	uint64_t comp_state_addr;
+	/**< Pointer to compression state */
+
+	/**< LWs 28-29 */
+	uint64_t ram_banks_addr;
+	/**< Pointer to banks */
+
+};
+
+struct icp_qat_fw_xlt_cd_hdr {
+	/**< LW 30 */
+	uint16_t resrvd1;
+	/**< Reserved field and assumed set to 0 */
+
+	uint8_t resrvd2;
+	/**< Reserved field and assumed set to 0 */
+
+	uint8_t next_curr_id;
+	/**< This field combines the next and current id (each four bits) -
+	 * the next id is the most significant nibble.
+	 * Next Id:  Set to the next slice to pass the translated data through.
+	 * Set to ICP_QAT_FW_SLICE_DRAM_WR if the data is not to go through
+	 * any more slices after compression
+	 * Current Id: Initialised with the translation slice type
+	 */
+
+	/**< LW 31 */
+	uint32_t resrvd3;
+	/**< Reserved and should be set to zero, needed for quadword
+	 * alignment
+	 */
+};
+
+struct icp_qat_fw_comp_req {
+	/**< LWs 0-1 */
+	struct icp_qat_fw_comn_req_hdr comn_hdr;
+	/**< Common request header - for Service Command Id,
+	 * use service-specific Compression Command Id.
+	 * Service Specific Flags - use Compression Command Flags
+	 */
+
+	/**< LWs 2-5 */
+	union icp_qat_fw_comp_req_hdr_cd_pars cd_pars;
+	/**< Compression service-specific content descriptor field which points
+	 * either to a content descriptor parameter block or contains the
+	 * compression slice config word.
+	 */
+
+	/**< LWs 6-13 */
+	struct icp_qat_fw_comn_req_mid comn_mid;
+	/**< Common request middle section */
+
+	/**< LWs 14-19 */
+	struct icp_qat_fw_comp_req_params comp_pars;
+	/**< Compression request Parameters block */
+
+	/**< LWs 20-21 */
+	union {
+		struct icp_qat_fw_xlt_req_params xlt_pars;
+		/**< Translation request Parameters block */
+
+		uint32_t resrvd1[ICP_QAT_FW_NUM_LONGWORDS_2];
+		/**< Reserved if not used for translation */
+
+	} u1;
+
+	/**< LWs 22-23 */
+	union {
+		uint32_t resrvd2[ICP_QAT_FW_NUM_LONGWORDS_2];
+		/**< Reserved - not used if Batch and Pack is disabled.*/
+
+		uint64_t bnp_res_table_addr;
+		/**< A generic pointer to the unbounded list of
+		 * icp_qat_fw_resp_comp_pars_t members. This pointer is only
+		 * used when the Batch and Pack is enabled.
+		 */
+	} u3;
+
+	/**< LWs 24-29 */
+	struct icp_qat_fw_comp_cd_hdr comp_cd_ctrl;
+	/**< Compression request content descriptor control block header */
+
+	/**< LWs 30-31 */
+	union {
+		struct icp_qat_fw_xlt_cd_hdr xlt_cd_ctrl;
+		/**< Translation request content descriptor
+		 * control block header
+		 */
+
+		uint32_t resrvd3[ICP_QAT_FW_NUM_LONGWORDS_2];
+		/**< Reserved if not used for translation */
+	} u2;
+};
+
+struct qat_comp_res_data {
+	uint32_t consumed;
+	uint32_t produced;
+	union {
+		uint64_t curr_chksum;
+		struct {
+			uint32_t curr_crc;
+			uint32_t curr_adler;
+		};
+	};
+};
+
+#define ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(sop, eop, bfinal, mca)           \
+	((((sop)&ICP_QAT_FW_COMP_SOP_MASK) << ICP_QAT_FW_COMP_SOP_BITPOS) |    \
+	 (((eop)&ICP_QAT_FW_COMP_EOP_MASK) << ICP_QAT_FW_COMP_EOP_BITPOS) |    \
+	 (((bfinal)&ICP_QAT_FW_COMP_BFINAL_MASK)                               \
+	  << ICP_QAT_FW_COMP_BFINAL_BITPOS) |                                  \
+	 (((mca)&ICP_QAT_FW_COMP_MCA_MASK) << ICP_QAT_FW_COMP_MCA_BITPOS))
+#endif
diff --git a/drivers/common/qat/qat_common.c b/drivers/common/qat/qat_common.c
index c206d3b..b05c09f 100644
--- a/drivers/common/qat/qat_common.c
+++ b/drivers/common/qat/qat_common.c
@@ -8,11 +8,12 @@
 
 int
 qat_sgl_fill_array(struct rte_mbuf *buf, uint64_t buf_start,
-		struct qat_sgl *list, uint32_t data_len)
+		void *lst, uint32_t data_len,
+		const int32_t max_segs)
 {
 	int nr = 1;
-
-	uint32_t buf_len = rte_pktmbuf_iova(buf) -
+	struct qat_sgl *list = (struct qat_sgl *)lst;
+	uint32_t buf_len = rte_pktmbuf_mtophys(buf) -
 			buf_start + rte_pktmbuf_data_len(buf);
 
 	list->buffers[0].addr = buf_start;
@@ -27,16 +28,16 @@
 
 	buf = buf->next;
 	while (buf) {
-		if (unlikely(nr == QAT_SGL_MAX_NUMBER)) {
-			QAT_LOG(ERR,
-				"QAT PMD exceeded size of QAT SGL entry(%u)",
-					QAT_SGL_MAX_NUMBER);
+		if (unlikely(nr == max_segs)) {
+			QAT_LOG(ERR, "QAT PMD exceeded size of QAT SGL"
+					" entry(%u)",
+					max_segs);
 			return -EINVAL;
 		}
 
 		list->buffers[nr].len = rte_pktmbuf_data_len(buf);
 		list->buffers[nr].resrvd = 0;
-		list->buffers[nr].addr = rte_pktmbuf_iova(buf);
+		list->buffers[nr].addr = rte_pktmbuf_mtophys(buf);
 
 		buf_len += list->buffers[nr].len;
 		buf = buf->next;
diff --git a/drivers/common/qat/qat_common.h b/drivers/common/qat/qat_common.h
index db85d54..a011f5a 100644
--- a/drivers/common/qat/qat_common.h
+++ b/drivers/common/qat/qat_common.h
@@ -31,6 +31,7 @@ enum qat_service_type {
 	QAT_SERVICE_COMPRESSION,
 	QAT_SERVICE_INVALID
 };
+
 #define QAT_MAX_SERVICES		(QAT_SERVICE_INVALID)
 
 /**< Common struct for scatter-gather list operations */
@@ -40,11 +41,17 @@ struct qat_flat_buf {
 	uint64_t addr;
 } __rte_packed;
 
+#define qat_sgl_hdr  struct { \
+	uint64_t resrvd; \
+	uint32_t num_bufs; \
+	uint32_t num_mapped_bufs; \
+}
+
+__extension__
 struct qat_sgl {
-	uint64_t resrvd;
-	uint32_t num_bufs;
-	uint32_t num_mapped_bufs;
-	struct qat_flat_buf buffers[QAT_SGL_MAX_NUMBER];
+	qat_sgl_hdr;
+	/* flexible array of flat buffers*/
+	struct qat_flat_buf buffers[0];
 } __rte_packed __rte_cache_aligned;
 
 /** Common, i.e. not service-specific, statistics */
@@ -64,7 +71,8 @@ struct qat_common_stats {
 
 int
 qat_sgl_fill_array(struct rte_mbuf *buf, uint64_t buf_start,
-		struct qat_sgl *list, uint32_t data_len);
+		void *lst, uint32_t data_len,
+		const int32_t max_segs);
 void
 qat_stats_get(struct qat_pci_device *dev,
 		struct qat_common_stats *stats,
diff --git a/drivers/common/qat/qat_device.c b/drivers/common/qat/qat_device.c
index 64f236e..0dadc8f 100644
--- a/drivers/common/qat/qat_device.c
+++ b/drivers/common/qat/qat_device.c
@@ -5,6 +5,7 @@
 #include "qat_device.h"
 #include "adf_transport_access_macros.h"
 #include "qat_sym_pmd.h"
+#include "qat_comp_pmd.h"
 
 /* Hardware device information per generation */
 __extension__
@@ -12,11 +13,13 @@ struct qat_gen_hw_data qat_gen_config[] =  {
 	[QAT_GEN1] = {
 		.dev_gen = QAT_GEN1,
 		.qp_hw_data = qat_gen1_qps,
+		.comp_num_im_bufs_required = QAT_NUM_INTERM_BUFS_GEN1
 	},
 	[QAT_GEN2] = {
 		.dev_gen = QAT_GEN2,
 		.qp_hw_data = qat_gen1_qps,
 		/* gen2 has same ring layout as gen1 */
+		.comp_num_im_bufs_required = QAT_NUM_INTERM_BUFS_GEN2
 	},
 };
 
diff --git a/drivers/common/qat/qat_device.h b/drivers/common/qat/qat_device.h
index 0cb370c..41f874b 100644
--- a/drivers/common/qat/qat_device.h
+++ b/drivers/common/qat/qat_device.h
@@ -16,6 +16,11 @@
 
 #define QAT_DEV_NAME_MAX_LEN	64
 
+enum qat_comp_num_im_buffers {
+	QAT_NUM_INTERM_BUFS_GEN1 = 12,
+	QAT_NUM_INTERM_BUFS_GEN2 = 20
+};
+
 /*
  * This struct holds all the data about a QAT pci device
  * including data about all services it supports.
@@ -25,6 +30,8 @@
  *  - runtime data
  */
 struct qat_sym_dev_private;
+struct qat_comp_dev_private;
+
 struct qat_pci_device {
 
 	/* Data used by all services */
@@ -55,6 +62,8 @@ struct qat_pci_device {
 	 */
 
 	/* Data relating to compression service */
+	struct qat_comp_dev_private *comp_dev;
+	/**< link back to compressdev private data */
 
 	/* Data relating to asymmetric crypto service */
 
@@ -63,6 +72,7 @@ struct qat_pci_device {
 struct qat_gen_hw_data {
 	enum qat_device_gen dev_gen;
 	const struct qat_qp_hw_data (*qp_hw_data)[ADF_MAX_QPS_ON_ANY_SERVICE];
+	enum qat_comp_num_im_buffers comp_num_im_bufs_required;
 };
 
 extern struct qat_gen_hw_data qat_gen_config[];
diff --git a/drivers/common/qat/qat_qp.c b/drivers/common/qat/qat_qp.c
index 32c1759..7ca7a45 100644
--- a/drivers/common/qat/qat_qp.c
+++ b/drivers/common/qat/qat_qp.c
@@ -15,6 +15,7 @@
 #include "qat_device.h"
 #include "qat_qp.h"
 #include "qat_sym.h"
+#include "qat_comp.h"
 #include "adf_transport_access_macros.h"
 
 
@@ -606,8 +607,8 @@ void rxq_free_desc(struct qat_qp *qp, struct qat_queue *q)
 
 		if (tmp_qp->service_type == QAT_SERVICE_SYMMETRIC)
 			qat_sym_process_response(ops, resp_msg);
-		/* add qat_asym_process_response here */
-		/* add qat_comp_process_response here */
+		else if (tmp_qp->service_type == QAT_SERVICE_COMPRESSION)
+			qat_comp_process_response(ops, resp_msg);
 
 		head = adf_modulo(head + rx_queue->msg_size,
 				  rx_queue->modulo_mask);
@@ -633,3 +634,9 @@ void rxq_free_desc(struct qat_qp *qp, struct qat_queue *q)
 	}
 	return resp_counter;
 }
+
+__attribute__((weak)) int
+qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused)
+{
+	return  0;
+}
diff --git a/drivers/common/qat/qat_qp.h b/drivers/common/qat/qat_qp.h
index 59db945..69f8a61 100644
--- a/drivers/common/qat/qat_qp.h
+++ b/drivers/common/qat/qat_qp.h
@@ -103,4 +103,9 @@ struct qat_qp {
 int
 qat_qps_per_service(const struct qat_qp_hw_data *qp_hw_data,
 			enum qat_service_type service);
+
+/* Needed for weak function*/
+int
+qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused);
+
 #endif /* _QAT_QP_H_ */
diff --git a/drivers/compress/qat/qat_comp.c b/drivers/compress/qat/qat_comp.c
new file mode 100644
index 0000000..813d841
--- /dev/null
+++ b/drivers/compress/qat/qat_comp.c
@@ -0,0 +1,383 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_hexdump.h>
+#include <rte_comp.h>
+#include <rte_bus_pci.h>
+#include <rte_byteorder.h>
+#include <rte_memcpy.h>
+#include <rte_common.h>
+#include <rte_spinlock.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+
+#include "qat_logs.h"
+#include "qat_comp.h"
+#include "qat_comp_pmd.h"
+
+int
+qat_comp_build_request(void *in_op, uint8_t *out_msg, void *op_cookie,
+		       enum qat_device_gen qat_dev_gen __rte_unused)
+{
+	struct rte_comp_op *op = in_op;
+	struct qat_comp_op_cookie *cookie =
+			(struct qat_comp_op_cookie *)op_cookie;
+	struct qat_comp_xform *qat_xform = op->private_xform;
+	const uint8_t *tmpl = (uint8_t *)&qat_xform->qat_comp_req_tmpl;
+	struct icp_qat_fw_comp_req *comp_req =
+	    (struct icp_qat_fw_comp_req *)out_msg;
+
+	if (unlikely(op->op_type != RTE_COMP_OP_STATELESS)) {
+		QAT_DP_LOG(ERR, "QAT PMD only supports stateless compression "
+				"operation requests, op (%p) is not a "
+				"stateless operation.", op);
+		return -EINVAL;
+	}
+
+	rte_mov128(out_msg, tmpl);
+	comp_req->comn_mid.opaque_data = (uint64_t)(uintptr_t)op;
+
+	/* common for sgl and flat buffers */
+	comp_req->comp_pars.comp_len = op->src.length;
+	comp_req->comp_pars.out_buffer_sz = rte_pktmbuf_pkt_len(op->m_dst);
+
+	/* sgl */
+	if (op->m_src->next != NULL || op->m_dst->next != NULL) {
+		if (unlikely(op->m_src->next == NULL ||
+			     op->m_dst->next == NULL)) {
+			QAT_DP_LOG(ERR, "QAT PMD doesn't support SGL on one "
+				    "side only: src->next (%p), dst->next (%p)",
+				    op->m_src->next, op->m_dst->next);
+			return -EINVAL;
+		}
+
+		int ret = 0;
+
+		ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
+				QAT_COMN_PTR_TYPE_SGL);
+		ret = qat_sgl_fill_array(op->m_src,
+				rte_pktmbuf_mtophys_offset(op->m_src,
+							op->src.offset),
+				&cookie->qat_sgl_src,
+				op->src.length,
+				RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS);
+		if (ret) {
+			QAT_DP_LOG(ERR, "QAT PMD Cannot fill sgl array");
+			return ret;
+		}
+
+		ret = qat_sgl_fill_array(op->m_dst,
+				rte_pktmbuf_mtophys_offset(op->m_dst,
+							op->dst.offset),
+				&cookie->qat_sgl_dst,
+				comp_req->comp_pars.out_buffer_sz,
+				RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS);
+		if (ret) {
+			QAT_DP_LOG(ERR, "QAT PMD Cannot fill sgl array");
+			return ret;
+		}
+
+		comp_req->comn_mid.src_data_addr =
+				cookie->qat_sgl_src_phys_addr;
+		comp_req->comn_mid.dest_data_addr =
+				cookie->qat_sgl_dst_phys_addr;
+		comp_req->comn_mid.src_length = 0;
+		comp_req->comn_mid.dst_length = 0;
+
+	} else {
+		ICP_QAT_FW_COMN_PTR_TYPE_SET(comp_req->comn_hdr.comn_req_flags,
+				QAT_COMN_PTR_TYPE_FLAT);
+		comp_req->comn_mid.src_length = rte_pktmbuf_data_len(op->m_src);
+		comp_req->comn_mid.dst_length = rte_pktmbuf_data_len(op->m_dst);
+
+		comp_req->comn_mid.src_data_addr =
+		    rte_pktmbuf_mtophys_offset(op->m_src, op->src.offset);
+		comp_req->comn_mid.dest_data_addr =
+		    rte_pktmbuf_mtophys_offset(op->m_dst, op->dst.offset);
+	}
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+	QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message:", comp_req,
+		    sizeof(struct icp_qat_fw_comp_req));
+#endif
+	return 0;
+}
+
+int
+qat_comp_process_response(void **op, uint8_t *resp)
+{
+	struct icp_qat_fw_comn_resp *resp_msg =
+			(struct icp_qat_fw_comn_resp *)resp;
+	struct rte_comp_op *rx_op = (struct rte_comp_op *)(uintptr_t)
+			(resp_msg->opaque_data);
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+	QAT_DP_HEXDUMP_LOG(DEBUG,  "qat_response:", (uint8_t *)resp_msg,
+			sizeof(struct icp_qat_fw_comn_resp));
+#endif
+
+	if ((ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(resp_msg->comn_hdr.comn_status) |
+				ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(
+					resp_msg->comn_hdr.comn_status)) !=
+				ICP_QAT_FW_COMN_STATUS_FLAG_OK) {
+
+		rx_op->status = RTE_COMP_OP_STATUS_ERROR;
+		rx_op->debug_status =
+				*((uint16_t *)(&resp_msg->comn_hdr.comn_error));
+	} else {
+		struct qat_comp_xform *qat_xform = rx_op->private_xform;
+		struct qat_comp_res_data *comp_resp =
+		    (struct qat_comp_res_data *)&resp_msg->resrvd;
+
+		rx_op->status = RTE_COMP_OP_STATUS_SUCCESS;
+		rx_op->consumed = comp_resp->consumed;
+		rx_op->produced = comp_resp->produced;
+
+		if (qat_xform->checksum_type != RTE_COMP_CHECKSUM_NONE) {
+			if (qat_xform->checksum_type == RTE_COMP_CHECKSUM_CRC32)
+				rx_op->output_chksum = comp_resp->curr_crc;
+			else if (qat_xform->checksum_type ==
+				 RTE_COMP_CHECKSUM_ADLER32)
+				rx_op->output_chksum = comp_resp->curr_adler;
+			else
+				rx_op->output_chksum = comp_resp->curr_chksum;
+		}
+	}
+	*op = (void *)rx_op;
+
+	return 0;
+}
+
+unsigned int
+qat_comp_xform_size(void)
+{
+	return RTE_ALIGN_CEIL(sizeof(struct qat_comp_xform), 8);
+}
+
+static void qat_comp_create_req_hdr(struct icp_qat_fw_comn_req_hdr *header,
+				    enum qat_comp_request request)
+{
+	if (request == QAT_COMP_REQUEST_FIXED_COMP_STATELESS)
+		header->service_cmd_id = ICP_QAT_FW_COMP_CMD_STATIC;
+	else if (request == QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS)
+		header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DYNAMIC;
+	else if (request == QAT_COMP_REQUEST_DECOMPRESS)
+		header->service_cmd_id = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
+
+	header->service_type = ICP_QAT_FW_COMN_REQ_CPM_FW_COMP;
+	header->hdr_flags =
+	    ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
+
+	header->comn_req_flags = ICP_QAT_FW_COMN_FLAGS_BUILD(
+	    QAT_COMN_CD_FLD_TYPE_16BYTE_DATA, QAT_COMN_PTR_TYPE_FLAT);
+}
+
+static int qat_comp_create_templates(struct qat_comp_xform *qat_xform,
+				     const struct rte_memzone *interm_buff_mz,
+				     const struct rte_comp_xform *xform)
+{
+	struct icp_qat_fw_comp_req *comp_req;
+	int comp_level, algo;
+	int direction = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
+
+	if (unlikely(qat_xform == NULL)) {
+		QAT_LOG(ERR, "Session was not created for this device");
+		return -EINVAL;
+	}
+
+	if (qat_xform->qat_comp_request == QAT_COMP_REQUEST_DECOMPRESS) {
+		direction = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS;
+		comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_1;
+
+	} else {
+		if (xform->compress.level == RTE_COMP_LEVEL_PMD_DEFAULT)
+			comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_8;
+		else if (xform->compress.level == 1)
+			comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_1;
+		else if (xform->compress.level == 2)
+			comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_4;
+		else if (xform->compress.level == 3)
+			comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_8;
+		else if (xform->compress.level >= 4 &&
+			 xform->compress.level <= 9)
+			comp_level = ICP_QAT_HW_COMPRESSION_DEPTH_16;
+		else {
+			QAT_LOG(ERR, "compression level not supported");
+			return -EINVAL;
+		}
+	}
+
+	switch (xform->compress.algo) {
+	case RTE_COMP_ALGO_DEFLATE:
+		algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
+		break;
+	case RTE_COMP_ALGO_LZS:
+	default:
+		/* RTE_COMP_NULL */
+		QAT_LOG(ERR, "compression algorithm not supported");
+		return -EINVAL;
+	}
+
+	comp_req = &qat_xform->qat_comp_req_tmpl;
+
+	/* Initialize header */
+	qat_comp_create_req_hdr(&comp_req->comn_hdr,
+					qat_xform->qat_comp_request);
+
+	comp_req->comn_hdr.serv_specif_flags = ICP_QAT_FW_COMP_FLAGS_BUILD(
+	    ICP_QAT_FW_COMP_STATELESS_SESSION,
+	    ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST,
+	    ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST,
+	    ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST,
+	    ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF);
+
+	comp_req->cd_pars.sl.comp_slice_cfg_word[0] =
+	    ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(
+		direction,
+		/* In CPM 1.6 only valid mode ! */
+		ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED, algo,
+		/* Translate level to depth */
+		comp_level, ICP_QAT_HW_COMPRESSION_FILE_TYPE_0);
+
+	comp_req->comp_pars.initial_adler = 1;
+	comp_req->comp_pars.initial_crc32 = 0;
+	comp_req->comp_pars.req_par_flags =
+	    ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
+		ICP_QAT_FW_COMP_SOP, ICP_QAT_FW_COMP_EOP,
+		ICP_QAT_FW_COMP_BFINAL, ICP_QAT_FW_COMP_NO_MCA);
+
+	if (qat_xform->qat_comp_request == QAT_COMP_REQUEST_FIXED_COMP_STATELESS
+		|| qat_xform->qat_comp_request == QAT_COMP_REQUEST_DECOMPRESS) {
+		ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
+					    ICP_QAT_FW_SLICE_DRAM_WR);
+		ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
+					    ICP_QAT_FW_SLICE_COMP);
+	} else if (qat_xform->qat_comp_request ==
+		   QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS) {
+
+		ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->comp_cd_ctrl,
+					    ICP_QAT_FW_SLICE_XLAT);
+		ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->comp_cd_ctrl,
+					    ICP_QAT_FW_SLICE_COMP);
+
+		ICP_QAT_FW_COMN_NEXT_ID_SET(&comp_req->u2.xlt_cd_ctrl,
+					    ICP_QAT_FW_SLICE_DRAM_WR);
+		ICP_QAT_FW_COMN_CURR_ID_SET(&comp_req->u2.xlt_cd_ctrl,
+					    ICP_QAT_FW_SLICE_XLAT);
+
+		comp_req->u1.xlt_pars.inter_buff_ptr =
+				interm_buff_mz->phys_addr;
+	}
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+	QAT_DP_HEXDUMP_LOG(DEBUG, "qat compression message template:", comp_req,
+		    sizeof(struct icp_qat_fw_comp_req));
+#endif
+	return 0;
+}
+
+/**
+ * Create driver private_xform data.
+ *
+ * @param dev
+ *   Compressdev device
+ * @param xform
+ *   xform data from application
+ * @param private_xform
+ *   ptr where handle of pmd's private_xform data should be stored
+ * @return
+ *  - if successful returns 0
+ *    and valid private_xform handle
+ *  - <0 in error cases
+ *  - Returns -EINVAL if input parameters are invalid.
+ *  - Returns -ENOTSUP if comp device does not support the comp transform.
+ *  - Returns -ENOMEM if the private_xform could not be allocated.
+ */
+int
+qat_comp_private_xform_create(struct rte_compressdev *dev,
+			      const struct rte_comp_xform *xform,
+			      void **private_xform)
+{
+	struct qat_comp_dev_private *qat = dev->data->dev_private;
+
+	if (unlikely(private_xform == NULL)) {
+		QAT_LOG(ERR, "QAT: private_xform parameter is NULL");
+		return -EINVAL;
+	}
+	if (unlikely(qat->xformpool == NULL)) {
+		QAT_LOG(ERR, "QAT device has no private_xform mempool");
+		return -ENOMEM;
+	}
+	if (rte_mempool_get(qat->xformpool, private_xform)) {
+		QAT_LOG(ERR, "Couldn't get object from qat xform mempool");
+		return -ENOMEM;
+	}
+
+	struct qat_comp_xform *qat_xform =
+			(struct qat_comp_xform *)*private_xform;
+
+	if (xform->type == RTE_COMP_COMPRESS) {
+		if (xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED ||
+		  ((xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_DEFAULT)
+				   && qat->interm_buff_mz == NULL))
+
+			qat_xform->qat_comp_request =
+					QAT_COMP_REQUEST_FIXED_COMP_STATELESS;
+		else if ((xform->compress.deflate.huffman ==
+						RTE_COMP_HUFFMAN_DYNAMIC ||
+			xform->compress.deflate.huffman ==
+						RTE_COMP_HUFFMAN_DEFAULT) &&
+			qat->interm_buff_mz != NULL)
+
+			qat_xform->qat_comp_request =
+					QAT_COMP_REQUEST_DYNAMIC_COMP_STATELESS;
+		else {
+			QAT_LOG(ERR,
+	      "IM buffers needed for dynamic deflate. Set size in config file");
+			return -EINVAL;
+		}
+
+	} else {
+		qat_xform->qat_comp_request = QAT_COMP_REQUEST_DECOMPRESS;
+	}
+
+	qat_xform->checksum_type = xform->compress.chksum;
+
+	if (qat_comp_create_templates(qat_xform, qat->interm_buff_mz, xform)) {
+		QAT_LOG(ERR, "QAT: Problem with setting compression");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * Free driver private_xform data.
+ *
+ * @param dev
+ *   Compressdev device
+ * @param private_xform
+ *   handle of pmd's private_xform data
+ * @return
+ *  - 0 if successful
+ *  - <0 in error cases
+ *  - Returns -EINVAL if input parameters are invalid.
+ */
+int
+qat_comp_private_xform_free(struct rte_compressdev *dev __rte_unused,
+			    void *private_xform)
+{
+	struct qat_comp_xform *qat_xform =
+			(struct qat_comp_xform *)private_xform;
+
+	if (qat_xform) {
+		memset(qat_xform, 0, qat_comp_xform_size());
+		struct rte_mempool *mp = rte_mempool_from_obj(qat_xform);
+
+		rte_mempool_put(mp, qat_xform);
+		return 0;
+	}
+	return -EINVAL;
+}
diff --git a/drivers/compress/qat/qat_comp.h b/drivers/compress/qat/qat_comp.h
new file mode 100644
index 0000000..ba3beec
--- /dev/null
+++ b/drivers/compress/qat/qat_comp.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2018 Intel Corporation
+ */
+
+#ifndef _QAT_COMP_H_
+#define _QAT_COMP_H_
+
+#ifdef RTE_LIBRTE_COMPRESSDEV
+
+#include <rte_compressdev.h>
+#include <rte_compressdev_pmd.h>
+
+#include "qat_common.h"
+#include "icp_qat_hw.h"
+#include "icp_qat_fw_comp.h"
+#include "icp_qat_fw_la.h"
+
+/*
+ * This macro rounds up a number to a be a multiple of
+ * the alignment when the alignment is a power of 2
+ */
+#define ALIGN_POW2_ROUNDUP(num, align) \
+	(((num) + (align) - 1) & ~((align) - 1))
+#define QAT_64_BYTE_ALIGN_MASK (~0x3f)
+#define QAT_64_BYTE_ALIGN (64)
+#define QAT_NUM_BUFS_IN_IM_SGL 2
+/* Use correct Deflate terminology */
+#define QAT_COMP_REQUEST_FIXED_COMP_STATELESS QAT_COMP_REQUEST_STATIC_COMP_STATELESS
+
+
+struct array_of_ptrs {
+	phys_addr_t pointer[0];
+};
+
+struct qat_inter_sgl {
+	qat_sgl_hdr;
+	struct qat_flat_buf buffers[QAT_NUM_BUFS_IN_IM_SGL];
+} __rte_packed __rte_cache_aligned;
+
+struct qat_comp_sgl {
+	qat_sgl_hdr;
+	struct qat_flat_buf buffers[RTE_PMD_QAT_COMP_SGL_MAX_SEGMENTS];
+} __rte_packed __rte_cache_aligned;
+
+struct qat_comp_op_cookie {
+	struct qat_comp_sgl qat_sgl_src;
+	struct qat_comp_sgl qat_sgl_dst;
+	phys_addr_t qat_sgl_src_phys_addr;
+	phys_addr_t qat_sgl_dst_phys_addr;
+};
+
+struct qat_comp_xform {
+	struct icp_qat_fw_comp_req qat_comp_req_tmpl;
+	enum qat_comp_request qat_comp_request;
+	enum rte_comp_checksum_type checksum_type;
+};
+
+int
+qat_comp_build_request(void *in_op, uint8_t *out_msg, void *op_cookie,
+		       enum qat_device_gen qat_dev_gen __rte_unused);
+
+int
+qat_comp_process_response(void **op, uint8_t *resp);
+
+
+int
+qat_comp_private_xform_create(struct rte_compressdev *dev,
+			      const struct rte_comp_xform *xform,
+			      void **private_xform);
+
+int
+qat_comp_private_xform_free(struct rte_compressdev *dev, void *private_xform);
+
+unsigned int
+qat_comp_xform_size(void);
+
+#endif
+#endif
diff --git a/drivers/compress/qat/qat_comp_pmd.c b/drivers/compress/qat/qat_comp_pmd.c
new file mode 100644
index 0000000..6006e03
--- /dev/null
+++ b/drivers/compress/qat/qat_comp_pmd.c
@@ -0,0 +1,479 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2018 Intel Corporation
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_common.h>
+#include <rte_dev.h>
+#include <rte_malloc.h>
+#include <rte_pci.h>
+
+#include "qat_logs.h"
+#include "qat_comp.h"
+#include "qat_comp_pmd.h"
+
+uint8_t compressdev_qat_driver_id;
+
+static const struct rte_compressdev_capabilities qat_comp_gen_capabilities[] = {
+	{/* COMPRESSION - deflate */
+	 .algo = RTE_COMP_ALGO_DEFLATE,
+	 .comp_feature_flags = RTE_COMP_FF_MBUF_SCATTER_GATHER |
+			       RTE_COMP_FF_MULTI_PKT_CHECKSUM |
+			       RTE_COMP_FF_CRC32_ADLER32_CHECKSUM,
+	 .window_size = {.min = 15, .max = 15, .increment = 0} },
+	{RTE_COMP_ALGO_LIST_END, 0, {0, 0, 0} } };
+
+static void
+qat_comp_stats_get(struct rte_compressdev *dev,
+		struct rte_compressdev_stats *stats)
+{
+	struct qat_common_stats qat_stats = {0};
+	struct qat_comp_dev_private *qat_priv;
+
+	if (stats == NULL || dev == NULL) {
+		QAT_LOG(ERR, "invalid ptr: stats %p, dev %p", stats, dev);
+		return;
+	}
+	qat_priv = dev->data->dev_private;
+
+	qat_stats_get(qat_priv->qat_dev, &qat_stats, QAT_SERVICE_COMPRESSION);
+	stats->enqueued_count = qat_stats.enqueued_count;
+	stats->dequeued_count = qat_stats.dequeued_count;
+	stats->enqueue_err_count = qat_stats.enqueue_err_count;
+	stats->dequeue_err_count = qat_stats.dequeue_err_count;
+}
+
+static void
+qat_comp_stats_reset(struct rte_compressdev *dev)
+{
+	struct qat_comp_dev_private *qat_priv;
+
+	if (dev == NULL) {
+		QAT_LOG(ERR, "invalid compressdev ptr %p", dev);
+		return;
+	}
+	qat_priv = dev->data->dev_private;
+
+	qat_stats_reset(qat_priv->qat_dev, QAT_SERVICE_COMPRESSION);
+
+}
+
+static int
+qat_comp_qp_release(struct rte_compressdev *dev, uint16_t queue_pair_id)
+{
+	struct qat_comp_dev_private *qat_private = dev->data->dev_private;
+
+	QAT_LOG(DEBUG, "Release comp qp %u on device %d",
+				queue_pair_id, dev->data->dev_id);
+
+	qat_private->qat_dev->qps_in_use[QAT_SERVICE_COMPRESSION][queue_pair_id]
+						= NULL;
+
+	return qat_qp_release((struct qat_qp **)
+			&(dev->data->queue_pairs[queue_pair_id]));
+}
+
+static int
+qat_comp_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
+		  uint32_t max_inflight_ops, int socket_id)
+{
+	struct qat_qp *qp;
+	int ret = 0;
+	uint32_t i;
+	struct qat_qp_config qat_qp_conf;
+
+	struct qat_qp **qp_addr =
+			(struct qat_qp **)&(dev->data->queue_pairs[qp_id]);
+	struct qat_comp_dev_private *qat_private = dev->data->dev_private;
+	const struct qat_qp_hw_data *comp_hw_qps =
+			qat_gen_config[qat_private->qat_dev->qat_dev_gen]
+				      .qp_hw_data[QAT_SERVICE_COMPRESSION];
+	const struct qat_qp_hw_data *qp_hw_data = comp_hw_qps + qp_id;
+
+	/* If qp is already in use free ring memory and qp metadata. */
+	if (*qp_addr != NULL) {
+		ret = qat_comp_qp_release(dev, qp_id);
+		if (ret < 0)
+			return ret;
+	}
+	if (qp_id >= qat_qps_per_service(comp_hw_qps,
+					 QAT_SERVICE_COMPRESSION)) {
+		QAT_LOG(ERR, "qp_id %u invalid for this device", qp_id);
+		return -EINVAL;
+	}
+
+	qat_qp_conf.hw = qp_hw_data;
+	qat_qp_conf.build_request = qat_comp_build_request;
+	qat_qp_conf.cookie_size = sizeof(struct qat_comp_op_cookie);
+	qat_qp_conf.nb_descriptors = max_inflight_ops;
+	qat_qp_conf.socket_id = socket_id;
+	qat_qp_conf.service_str = "comp";
+
+	ret = qat_qp_setup(qat_private->qat_dev, qp_addr, qp_id, &qat_qp_conf);
+	if (ret != 0)
+		return ret;
+
+	/* store a link to the qp in the qat_pci_device */
+	qat_private->qat_dev->qps_in_use[QAT_SERVICE_COMPRESSION][qp_id]
+							= *qp_addr;
+
+	qp = (struct qat_qp *)*qp_addr;
+
+	for (i = 0; i < qp->nb_descriptors; i++) {
+
+		struct qat_comp_op_cookie *cookie =
+				qp->op_cookies[i];
+
+		cookie->qat_sgl_src_phys_addr =
+				rte_mempool_virt2iova(cookie) +
+				offsetof(struct qat_comp_op_cookie,
+				qat_sgl_src);
+
+		cookie->qat_sgl_dst_phys_addr =
+				rte_mempool_virt2iova(cookie) +
+				offsetof(struct qat_comp_op_cookie,
+				qat_sgl_dst);
+	}
+
+	return ret;
+}
+
+static const struct rte_memzone *
+qat_comp_setup_inter_buffers(struct qat_comp_dev_private *comp_dev,
+			      uint32_t buff_size)
+{
+	char inter_buff_mz_name[RTE_MEMZONE_NAMESIZE];
+	const struct rte_memzone *memzone;
+	uint8_t *mz_start = NULL;
+	phys_addr_t mz_start_phys = 0;
+	struct array_of_ptrs *array_of_pointers;
+	int size_of_ptr_array;
+	uint32_t full_size;
+	uint32_t offset_of_sgls, offset_of_flat_buffs = 0;
+	int i;
+	int num_im_sgls = qat_gen_config[comp_dev->qat_dev->qat_dev_gen].
+						comp_num_im_bufs_required;
+
+	QAT_LOG(DEBUG, "QAT COMP device %s needs %d sgls",
+				comp_dev->qat_dev->name, num_im_sgls);
+	snprintf(inter_buff_mz_name, RTE_MEMZONE_NAMESIZE,
+				"%s_inter_buff", comp_dev->qat_dev->name);
+	memzone = rte_memzone_lookup(inter_buff_mz_name);
+	if (memzone != NULL) {
+		QAT_LOG(DEBUG, "QAT COMP im buffer memzone created already");
+		return memzone;
+	}
+
+	/* Create a memzone to hold intermediate buffers and associated
+	 * meta-data needed by the firmware. The memzone contains:
+	 *  - a list of num_im_sgls physical pointers to sgls
+	 *  - the num_im_sgl sgl structures, each pointing to 2 flat buffers
+	 *  - the flat buffers: num_im_sgl * 2
+	 * where num_im_sgls depends on the hardware generation of the device
+	 */
+
+	size_of_ptr_array = num_im_sgls * sizeof(phys_addr_t);
+	offset_of_sgls = (size_of_ptr_array + (~QAT_64_BYTE_ALIGN_MASK))
+			& QAT_64_BYTE_ALIGN_MASK;
+	offset_of_flat_buffs =
+	    offset_of_sgls + num_im_sgls * sizeof(struct qat_inter_sgl);
+	full_size = offset_of_flat_buffs +
+			num_im_sgls * buff_size * QAT_NUM_BUFS_IN_IM_SGL;
+
+	memzone = rte_memzone_reserve_aligned(inter_buff_mz_name, full_size,
+			comp_dev->compressdev->data->socket_id,
+			RTE_MEMZONE_2MB, QAT_64_BYTE_ALIGN);
+	if (memzone == NULL) {
+		QAT_LOG(ERR, "Can't allocate intermediate buffers"
+				" for device %s", comp_dev->qat_dev->name);
+		return NULL;
+	}
+
+	mz_start = (uint8_t *)memzone->addr;
+	mz_start_phys = memzone->phys_addr;
+	QAT_LOG(DEBUG, "Memzone %s: addr = %p, phys = %lx, size required %d,"
+			"size created %ld",
+			inter_buff_mz_name, mz_start, mz_start_phys,
+			full_size, memzone->len);
+
+	array_of_pointers = (struct array_of_ptrs *)mz_start;
+	for (i = 0; i < num_im_sgls; i++) {
+		uint32_t curr_sgl_offset =
+		    offset_of_sgls + i * sizeof(struct qat_inter_sgl);
+		struct qat_inter_sgl *sgl =
+		    (struct qat_inter_sgl *)(mz_start +	curr_sgl_offset);
+		array_of_pointers->pointer[i] = mz_start_phys + curr_sgl_offset;
+
+		sgl->num_bufs = QAT_NUM_BUFS_IN_IM_SGL;
+		sgl->num_mapped_bufs = 0;
+		sgl->resrvd = 0;
+		sgl->buffers[0].addr = mz_start_phys + offset_of_flat_buffs +
+				i * buff_size * QAT_NUM_BUFS_IN_IM_SGL;
+		sgl->buffers[1].addr = mz_start_phys + offset_of_flat_buffs +
+				buff_size * (QAT_NUM_BUFS_IN_IM_SGL * i + 1);
+		sgl->buffers[0].len = sgl->buffers[1].len = buff_size;
+		sgl->buffers[0].resrvd = sgl->buffers[1].resrvd = 0;
+
+		QAT_LOG(DEBUG, "  : array_of_pointers->pointer[i]"
+			    "= %lx", array_of_pointers->pointer[i]);
+		QAT_LOG(DEBUG, "  : sgl[%i] = %p", i, sgl);
+		QAT_LOG(DEBUG, "  : sgl->buffers[0].addr = %lx, len=%d",
+				sgl->buffers[0].addr, sgl->buffers[0].len);
+		QAT_LOG(DEBUG, "  : sgl->buffers[1].addr = %lx, len=%d",
+				sgl->buffers[1].addr, sgl->buffers[1].len);
+	}
+	return memzone;
+}
+
+static struct rte_mempool *
+qat_comp_create_xform_pool(struct qat_comp_dev_private *comp_dev,
+			      uint32_t num_elements)
+{
+	char xform_pool_name[RTE_MEMPOOL_NAMESIZE];
+	struct rte_mempool *mp;
+
+	snprintf(xform_pool_name, RTE_MEMPOOL_NAMESIZE,
+			"%s_xforms", comp_dev->qat_dev->name);
+
+	QAT_LOG(DEBUG, "xformpool: %s", xform_pool_name);
+	mp = rte_mempool_lookup(xform_pool_name);
+
+	if (mp != NULL) {
+		QAT_LOG(DEBUG, "xformpool already created");
+		if (mp->size != num_elements) {
+			QAT_LOG(DEBUG, "xformpool wrong size - delete it");
+			rte_mempool_free(mp);
+			mp = NULL;
+			comp_dev->xformpool = NULL;
+		}
+	}
+
+	if (mp == NULL)
+		mp = rte_mempool_create(xform_pool_name,
+				num_elements,
+				qat_comp_xform_size(), 0, 0,
+				NULL, NULL, NULL, NULL, rte_socket_id(),
+				0);
+	if (mp == NULL) {
+		QAT_LOG(ERR, "Err creating mempool %s w %d elements of size %d",
+			xform_pool_name, num_elements, qat_comp_xform_size());
+		return NULL;
+	}
+
+	return mp;
+}
+
+static void
+_qat_comp_dev_config_clear(struct qat_comp_dev_private *comp_dev)
+{
+	/* Free intermediate buffers */
+	if (comp_dev->interm_buff_mz) {
+		rte_memzone_free(comp_dev->interm_buff_mz);
+		comp_dev->interm_buff_mz = NULL;
+	}
+	/* Free private_xform pool */
+	if (comp_dev->xformpool) {
+		/* Free internal mempool for private xforms */
+		rte_mempool_free(comp_dev->xformpool);
+		comp_dev->xformpool = NULL;
+	}
+}
+
+static int
+qat_comp_dev_config(struct rte_compressdev *dev,
+		struct rte_compressdev_config *config)
+{
+	struct qat_comp_dev_private *comp_dev = dev->data->dev_private;
+	int ret = 0;
+
+	if (config->max_nb_streams != 0) {
+		QAT_LOG(ERR,
+	"QAT device does not support STATEFUL so max_nb_streams must be 0");
+		return -EINVAL;
+	}
+
+	if (RTE_PMD_QAT_COMP_IM_BUFFER_SIZE == 0) {
+		QAT_LOG(WARNING,
+			"RTE_PMD_QAT_COMP_IM_BUFFER_SIZE = 0 in config file, so"
+			" QAT device can't be used for Dynamic Deflate. "
+			"Did you really intend to do this?");
+	} else {
+		comp_dev->interm_buff_mz =
+				qat_comp_setup_inter_buffers(comp_dev,
+					RTE_PMD_QAT_COMP_IM_BUFFER_SIZE);
+		if (comp_dev->interm_buff_mz == NULL) {
+			ret = -ENOMEM;
+			goto error_out;
+		}
+	}
+
+	comp_dev->xformpool = qat_comp_create_xform_pool(comp_dev,
+					config->max_nb_priv_xforms);
+	if (comp_dev->xformpool == NULL) {
+
+		ret = -ENOMEM;
+		goto error_out;
+	}
+	return 0;
+
+error_out:
+	_qat_comp_dev_config_clear(comp_dev);
+	return ret;
+}
+
+static int
+qat_comp_dev_start(struct rte_compressdev *dev __rte_unused)
+{
+	return 0;
+}
+
+static void
+qat_comp_dev_stop(struct rte_compressdev *dev __rte_unused)
+{
+
+}
+
+static int
+qat_comp_dev_close(struct rte_compressdev *dev)
+{
+	int i;
+	int ret = 0;
+	struct qat_comp_dev_private *comp_dev = dev->data->dev_private;
+
+	for (i = 0; i < dev->data->nb_queue_pairs; i++) {
+		ret = qat_comp_qp_release(dev, i);
+		if (ret < 0)
+			return ret;
+	}
+
+	_qat_comp_dev_config_clear(comp_dev);
+
+	return ret;
+}
+
+static void
+qat_comp_dev_info_get(struct rte_compressdev *dev,
+			struct rte_compressdev_info *info)
+{
+	struct qat_comp_dev_private *comp_dev = dev->data->dev_private;
+	const struct qat_qp_hw_data *comp_hw_qps =
+		qat_gen_config[comp_dev->qat_dev->qat_dev_gen]
+			      .qp_hw_data[QAT_SERVICE_COMPRESSION];
+
+	if (info != NULL) {
+		info->max_nb_queue_pairs =
+			qat_qps_per_service(comp_hw_qps,
+					    QAT_SERVICE_COMPRESSION);
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = comp_dev->qat_dev_capabilities;
+	}
+}
+
+static uint16_t
+qat_comp_pmd_enqueue_op_burst(void *qp, struct rte_comp_op **ops,
+		uint16_t nb_ops)
+{
+	return qat_enqueue_op_burst(qp, (void **)ops, nb_ops);
+}
+
+static uint16_t
+qat_comp_pmd_dequeue_op_burst(void *qp, struct rte_comp_op **ops,
+			      uint16_t nb_ops)
+{
+	return qat_dequeue_op_burst(qp, (void **)ops, nb_ops);
+}
+
+static struct rte_compressdev_ops compress_qat_ops = {
+
+	/* Device related operations */
+	.dev_configure		= qat_comp_dev_config,
+	.dev_start		= qat_comp_dev_start,
+	.dev_stop		= qat_comp_dev_stop,
+	.dev_close		= qat_comp_dev_close,
+	.dev_infos_get		= qat_comp_dev_info_get,
+
+	.stats_get		= qat_comp_stats_get,
+	.stats_reset		= qat_comp_stats_reset,
+	.queue_pair_setup	= qat_comp_qp_setup,
+	.queue_pair_release	= qat_comp_qp_release,
+
+	/* Compression related operations */
+	.private_xform_create	= qat_comp_private_xform_create,
+	.private_xform_free	= qat_comp_private_xform_free
+};
+
+int
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev)
+{
+	struct rte_compressdev_pmd_init_params init_params = {
+		.name = "",
+		.socket_id = qat_pci_dev->pci_dev->device.numa_node,
+	};
+	char name[RTE_COMPRESSDEV_NAME_MAX_LEN];
+	struct rte_compressdev *compressdev;
+	struct qat_comp_dev_private *comp_dev;
+
+	snprintf(name, RTE_COMPRESSDEV_NAME_MAX_LEN, "%s_%s",
+			qat_pci_dev->name, "comp");
+	QAT_LOG(DEBUG, "Creating QAT COMP device %s", name);
+
+	compressdev = rte_compressdev_pmd_create(name,
+			&qat_pci_dev->pci_dev->device,
+			sizeof(struct qat_comp_dev_private),
+			&init_params);
+
+	if (compressdev == NULL)
+		return -ENODEV;
+
+	compressdev->driver_id = compressdev_qat_driver_id;
+	compressdev->dev_ops = &compress_qat_ops;
+
+	compressdev->enqueue_burst = qat_comp_pmd_enqueue_op_burst;
+	compressdev->dequeue_burst = qat_comp_pmd_dequeue_op_burst;
+
+	compressdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED;
+
+	comp_dev = compressdev->data->dev_private;
+	comp_dev->qat_dev = qat_pci_dev;
+	comp_dev->compressdev = compressdev;
+	qat_pci_dev->comp_dev = comp_dev;
+
+	switch (qat_pci_dev->qat_dev_gen) {
+	case QAT_GEN1:
+	case QAT_GEN2:
+		comp_dev->qat_dev_capabilities = qat_comp_gen_capabilities;
+		break;
+	default:
+		comp_dev->qat_dev_capabilities = qat_comp_gen_capabilities;
+		QAT_LOG(DEBUG,
+			"QAT gen %d capabilities unknown, default to GEN1",
+					qat_pci_dev->qat_dev_gen);
+		break;
+	}
+
+	QAT_LOG(DEBUG,
+		    "Created QAT COMP device %s as compressdev instance %d",
+			name, compressdev->data->dev_id);
+	return 0;
+}
+
+int
+qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev)
+{
+	struct qat_comp_dev_private *comp_dev;
+
+	if (qat_pci_dev == NULL)
+		return -ENODEV;
+
+	comp_dev = qat_pci_dev->comp_dev;
+	if (comp_dev == NULL)
+		return 0;
+
+	/* clean up any resources used by the device */
+	qat_comp_dev_close(comp_dev->compressdev);
+
+	rte_compressdev_pmd_destroy(comp_dev->compressdev);
+	qat_pci_dev->comp_dev = NULL;
+
+	return 0;
+}
diff --git a/drivers/compress/qat/qat_comp_pmd.h b/drivers/compress/qat/qat_comp_pmd.h
new file mode 100644
index 0000000..11ea467
--- /dev/null
+++ b/drivers/compress/qat/qat_comp_pmd.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2015-2018 Intel Corporation
+ */
+
+#ifndef _QAT_COMP_PMD_H_
+#define _QAT_COMP_PMD_H_
+
+#ifdef RTE_LIBRTE_COMPRESSDEV
+
+#include <rte_compressdev.h>
+#include <rte_compressdev_pmd.h>
+
+#include "qat_device.h"
+
+/**< Intel(R) QAT Compression PMD device name */
+#define COMPRESSDEV_NAME_QAT_PMD	comp_qat
+
+/** private data structure for a QAT compression device.
+ * This QAT device is a device offering only a compression service,
+ * there can be one of these on each qat_pci_device (VF).
+ */
+struct qat_comp_dev_private {
+	struct qat_pci_device *qat_dev;
+	/**< The qat pci device hosting the service */
+	struct rte_compressdev *compressdev;
+	/**< The pointer to this compression device structure */
+	const struct rte_compressdev_capabilities *qat_dev_capabilities;
+	/* QAT device compression capabilities */
+	const struct rte_memzone *interm_buff_mz;
+	struct rte_mempool *xformpool;
+};
+
+int
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev);
+
+int
+qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev);
+
+#endif
+#endif /* _QAT_COMP_PMD_H_ */
diff --git a/drivers/crypto/qat/qat_sym.c b/drivers/crypto/qat/qat_sym.c
index 17d63eb..3e3c3ac 100644
--- a/drivers/crypto/qat/qat_sym.c
+++ b/drivers/crypto/qat/qat_sym.c
@@ -495,8 +495,9 @@
 		ICP_QAT_FW_COMN_PTR_TYPE_SET(qat_req->comn_hdr.comn_req_flags,
 				QAT_COMN_PTR_TYPE_SGL);
 		ret = qat_sgl_fill_array(op->sym->m_src, src_buf_start,
-				&cookie->qat_sgl_src,
-				qat_req->comn_mid.src_length);
+					&cookie->qat_sgl_src,
+					qat_req->comn_mid.src_length,
+					QAT_SYM_SGL_MAX_NUMBER);
 
 		if (unlikely(ret)) {
 			QAT_DP_LOG(ERR, "QAT PMD Cannot fill sgl array");
@@ -509,9 +510,10 @@
 				cookie->qat_sgl_src_phys_addr;
 		else {
 			ret = qat_sgl_fill_array(op->sym->m_dst,
-					dst_buf_start,
-					&cookie->qat_sgl_dst,
-						qat_req->comn_mid.dst_length);
+						 dst_buf_start,
+						 &cookie->qat_sgl_dst,
+						 qat_req->comn_mid.dst_length,
+						 QAT_SYM_SGL_MAX_NUMBER);
 
 			if (unlikely(ret)) {
 				QAT_DP_LOG(ERR, "QAT PMD can't fill sgl array");
diff --git a/drivers/crypto/qat/qat_sym.h b/drivers/crypto/qat/qat_sym.h
index 3c8ec5b..53c3275 100644
--- a/drivers/crypto/qat/qat_sym.h
+++ b/drivers/crypto/qat/qat_sym.h
@@ -22,11 +22,21 @@
  */
 #define BPI_MAX_ENCR_IV_LEN ICP_QAT_HW_AES_BLK_SZ
 
+/*
+ * Maximum number of SGL entries
+ */
+#define QAT_SYM_SGL_MAX_NUMBER	16
+
 struct qat_sym_session;
 
+struct qat_sym_sgl {
+	qat_sgl_hdr;
+	struct qat_flat_buf buffers[QAT_SYM_SGL_MAX_NUMBER];
+} __rte_packed __rte_cache_aligned;
+
 struct qat_sym_op_cookie {
-	struct qat_sgl qat_sgl_src;
-	struct qat_sgl qat_sgl_dst;
+	struct qat_sym_sgl qat_sgl_src;
+	struct qat_sym_sgl qat_sgl_dst;
 	phys_addr_t qat_sgl_src_phys_addr;
 	phys_addr_t qat_sgl_dst_phys_addr;
 };
