crypto: qat - add KPT support for GEN6 devices

Add support for Intel Key Protection Technology (KPT) on QAT GEN6
devices.

KPT protects private keys from exposure by keeping them wrapped
(encrypted) while in use, in-flight, and at rest. Keys remain in wrapped
form and are not exposed in plaintext in host memory. This feature
operates outside of the Linux crypto framework and kernel keyring.

Extend the firmware admin interface to enable and configure KPT. During
device initialisation, if KPT is enabled, the driver sends an admin
message to firmware to enable KPT mode and configure parameters such as
the maximum number of SWK (Symmetric Wrapping Key) slots and the SWK
time-to-live (TTL).

Expose KPT configuration via a new sysfs attribute group, "qat_kpt", and
add ABI documentation.

Co-developed-by: Nitesh Venkatesh <nitesh.venkatesh@intel.com>
Signed-off-by: Nitesh Venkatesh <nitesh.venkatesh@intel.com>
Signed-off-by: Junyuan Wang <junyuan.wang@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Ahsan Atta <ahsan.atta@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Junyuan Wang 2026-05-26 09:28:39 +00:00 committed by Herbert Xu
parent ed459fe319
commit fb98254a5e
15 changed files with 586 additions and 2 deletions

View File

@ -0,0 +1,97 @@
What: /sys/bus/pci/devices/<BDF>/qat_kpt/
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
Directory containing attributes related to the QAT Key Protection
Technology (KPT) feature. KPT allows cryptographic keys to be used
by the accelerator without being exposed in plaintext to the host.
What: /sys/bus/pci/devices/<BDF>/qat_kpt/enable
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
(RW) Enables or disables Key Protection Technology (KPT).
Write 1 to enable KPT, or 0 to disable it.
Example usage::
# cat /sys/bus/pci/devices/<BDF>/qat_kpt/enable
0
# echo 1 > /sys/bus/pci/devices/<BDF>/qat_kpt/enable
This attribute is only available on devices that support KPT.
What: /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_fn
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
(RW) Configures the maximum number of KPT symmetric wrapping keys
(SWKs) that a Virtual Function (VF) may be associated with.
Valid values range from 0 to 128. A value of 0 indicates no limit.
Example usage::
# cat /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_fn
128
# echo 128 > /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_fn
This attribute is only available on devices that support KPT.
What: /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_pasid
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
(RW) Configures the maximum number of KPT symmetric wrapping keys
(SWKs) per Process Address Space ID (PASID).
Valid values range from 0 to 128. A value of 0 indicates no limit.
Example usage::
# cat /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_pasid
128
# echo 128 > /sys/bus/pci/devices/<BDF>/qat_kpt/swk_cnt_per_pasid
This attribute is only available on devices that support KPT.
What: /sys/bus/pci/devices/<BDF>/qat_kpt/swk_max_ttl
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
(RW) Configures the maximum Time To Live (TTL) for KPT symmetric
wrapping keys (SWK).
Valid values range from 0 to 31536000 seconds. A value of 0
indicates that the SWK TTL is unlimited.
Example usage::
# cat /sys/bus/pci/devices/<BDF>/qat_kpt/swk_max_ttl
1000
# echo 1000 > /sys/bus/pci/devices/<BDF>/qat_kpt/swk_max_ttl
This attribute is only available on devices that support KPT.
What: /sys/bus/pci/devices/<BDF>/qat_kpt/swk_shared
Date: August 2026
KernelVersion: 7.2
Contact: qat-linux@intel.com
Description:
(RW) Controls shared mode for KPT symmetric wrapping keys (SWK).
Write 1 to enable shared mode, or 0 to disable it (non-shared mode).
Example usage::
# cat /sys/bus/pci/devices/<BDF>/qat_kpt/swk_shared
0
# echo 1 > /sys/bus/pci/devices/<BDF>/qat_kpt/swk_shared
This attribute is only available on devices that support KPT.

View File

@ -752,10 +752,12 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
unsigned long mask;
u32 caps = 0;
u32 fusectl1;
u32 fusectl0;
if (adf_6xxx_is_wcy(GET_HW_DATA(accel_dev)))
return get_accel_cap_wcy(accel_dev);
fusectl0 = GET_HW_DATA(accel_dev)->fuses[ADF_FUSECTL0];
fusectl1 = GET_HW_DATA(accel_dev)->fuses[ADF_FUSECTL1];
/* Read accelerator capabilities mask */
@ -785,7 +787,8 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC |
ICP_ACCEL_CAPABILITIES_SM2 |
ICP_ACCEL_CAPABILITIES_ECEDMONT;
ICP_ACCEL_CAPABILITIES_ECEDMONT |
ICP_ACCEL_CAPABILITIES_KPT;
if (fusectl1 & ICP_ACCEL_GEN6_MASK_PKE_SLICE) {
capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC;
@ -793,6 +796,9 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev)
capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT;
}
if (fusectl0 & ADF_GEN6_KPT_FUSE_BIT)
capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_KPT;
capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION |
ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION |
ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION |
@ -960,6 +966,18 @@ static int dev_config(struct adf_accel_dev *accel_dev)
return ret;
}
static void adf_gen6_init_kpt(struct adf_kpt_hw_data *kpt_data)
{
kpt_data->max_swk_cnt_per_fn_pasid = ADF_6XXX_KPT_MAX_SWK_COUNT_PER_FNPASID;
kpt_data->max_swk_ttl = ADF_6XXX_KPT_MAX_SWK_TTL;
kpt_data->user_input.enable = false;
kpt_data->user_input.swk_shared = ADF_6XXX_KPT_DEFAULT_SWK_SHARED_MODE;
kpt_data->user_input.swk_max_ttl = ADF_6XXX_KPT_DEFAULT_SWK_TTL;
kpt_data->user_input.swk_cnt_per_fn = ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_FN;
kpt_data->user_input.swk_cnt_per_pasid = ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_PASID;
}
static void adf_gen6_init_rl_data(struct adf_rl_hw_data *rl_data)
{
rl_data->pciout_tb_offset = ADF_GEN6_RL_TOKEN_PCIEOUT_BUCKET_OFFSET;
@ -1057,6 +1075,7 @@ void adf_init_hw_data_6xxx(struct adf_hw_device_data *hw_data)
adf_gen6_init_tl_data(&hw_data->tl_data);
adf_gen6_init_rl_data(&hw_data->rl_data);
adf_gen6_init_anti_rb(&hw_data->anti_rb_data);
adf_gen6_init_kpt(&hw_data->kpt_data);
}
void adf_clean_hw_data_6xxx(struct adf_hw_device_data *hw_data)

View File

@ -58,6 +58,7 @@
/* Fuse bits */
#define ADF_GEN6_ANTI_RB_FUSE_BIT BIT(24)
#define ADF_GEN6_KPT_FUSE_BIT BIT(16)
/*
* Watchdog timers
@ -164,6 +165,14 @@
/* Clock frequency */
#define ADF_6XXX_AE_FREQ (1000 * HZ_PER_MHZ)
/* KPT */
#define ADF_6XXX_KPT_MAX_SWK_COUNT_PER_FNPASID 128
#define ADF_6XXX_KPT_MAX_SWK_TTL 31536000
#define ADF_6XXX_KPT_DEFAULT_SWK_SHARED_MODE 1
#define ADF_6XXX_KPT_DEFAULT_SWK_TTL 0
#define ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_FN 0
#define ADF_6XXX_KPT_DEFAULT_SWK_CNT_PER_PASID 0
enum icp_qat_gen6_slice_mask {
ICP_ACCEL_GEN6_MASK_UCS_SLICE = BIT(0),
ICP_ACCEL_GEN6_MASK_AUTH_SLICE = BIT(1),

View File

@ -13,6 +13,7 @@
#include <adf_cfg.h>
#include <adf_common_drv.h>
#include <adf_dbgfs.h>
#include <adf_sysfs_kpt.h>
#include "adf_gen6_shared.h"
#include "adf_6xxx_hw_data.h"
@ -217,6 +218,11 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return ret;
ret = adf_sysfs_init(accel_dev);
if (ret)
return ret;
if (!(hw_data->fuses[ADF_FUSECTL0] & ADF_GEN6_KPT_FUSE_BIT))
ret = adf_sysfs_init_kpt(accel_dev);
return ret;
}

View File

@ -25,12 +25,14 @@ intel_qat-y := adf_accel_engine.o \
adf_hw_arbiter.o \
adf_init.o \
adf_isr.o \
adf_kpt.o \
adf_module.o \
adf_mstate_mgr.o \
adf_rl_admin.o \
adf_rl.o \
adf_sysfs.o \
adf_sysfs_anti_rb.o \
adf_sysfs_kpt.o \
adf_sysfs_ras_counters.o \
adf_sysfs_rl.o \
adf_timer.o \

View File

@ -14,6 +14,7 @@
#include "adf_anti_rb.h"
#include "adf_cfg_common.h"
#include "adf_dc.h"
#include "adf_kpt.h"
#include "adf_rl.h"
#include "adf_telemetry.h"
#include "adf_pfvf_msg.h"
@ -335,6 +336,7 @@ struct adf_hw_device_data {
struct adf_rl_hw_data rl_data;
struct adf_tl_hw_data tl_data;
struct adf_anti_rb_hw_data anti_rb_data;
struct adf_kpt_hw_data kpt_data;
struct qat_migdev_ops vfmig_ops;
const char *fw_name;
const char *fw_mmp_name;

View File

@ -13,6 +13,7 @@
#include "adf_common_drv.h"
#include "adf_cfg.h"
#include "adf_heartbeat.h"
#include "adf_kpt.h"
#include "icp_qat_fw_init_admin.h"
#define ADF_ADMIN_MAILBOX_STRIDE 0x1000
@ -606,6 +607,44 @@ int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev)
return adf_send_admin_svn(accel_dev, ICP_QAT_FW_SVN_COMMIT, &resp);
}
static_assert(sizeof(struct icp_qat_fw_init_admin_kpt_cfg) < PAGE_SIZE);
static void adf_cfg_kpt_config(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_kpt_cfg *kpt_config)
{
struct adf_kpt_interface_data *user_data = GET_KPT_USER_DATA(accel_dev);
kpt_config->swk_cnt_per_fn = user_data->swk_cnt_per_fn;
kpt_config->swk_cnt_per_pasid = user_data->swk_cnt_per_pasid;
kpt_config->swk_ttl_in_secs = user_data->swk_max_ttl;
kpt_config->swk_shared_disable = !user_data->swk_shared;
}
int adf_send_admin_kpt_init(struct adf_accel_dev *accel_dev, void *init_cfg,
size_t init_cfg_sz, dma_addr_t init_ptr)
{
struct icp_qat_fw_init_admin_kpt_cfg *kpt_config = init_cfg;
u32 ae_mask = GET_HW_DATA(accel_dev)->admin_ae_mask;
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };
int ret;
if (!kpt_config || init_cfg_sz < sizeof(*kpt_config))
return -EINVAL;
adf_cfg_kpt_config(accel_dev, kpt_config);
req.cmd_id = ICP_QAT_FW_KPT_ENABLE;
req.init_cfg_ptr = init_ptr;
req.init_cfg_sz = sizeof(*kpt_config);
ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
if (ret)
dev_err(&GET_DEV(accel_dev), "Failed to send KPT init admin message\n");
return ret;
}
int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
struct adf_admin_comms *admin;

View File

@ -29,5 +29,7 @@ int adf_send_admin_tl_start(struct adf_accel_dev *accel_dev,
int adf_send_admin_tl_stop(struct adf_accel_dev *accel_dev);
int adf_send_admin_arb_query(struct adf_accel_dev *accel_dev, int cmd, u8 *svn);
int adf_send_admin_arb_commit(struct adf_accel_dev *accel_dev);
int adf_send_admin_kpt_init(struct adf_accel_dev *accel_dev, void *init_cfg,
size_t init_cfg_sz, dma_addr_t init_ptr);
#endif

View File

@ -10,6 +10,7 @@
#include "adf_dbgfs.h"
#include "adf_heartbeat.h"
#include "adf_rl.h"
#include "adf_kpt.h"
#include "adf_sysfs_anti_rb.h"
#include "adf_sysfs_ras_counters.h"
#include "adf_telemetry.h"
@ -219,6 +220,13 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
return -EFAULT;
}
/* Enable Key Protection Technology (KPT) */
ret = adf_enable_kpt(accel_dev);
if (ret) {
dev_err(&GET_DEV(accel_dev), "Failed to enable KPT\n");
return ret;
}
if (hw_data->start_timer) {
ret = hw_data->start_timer(accel_dev);
if (ret) {

View File

@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2026 Intel Corporation */
#include <linux/dma-mapping.h>
#include "adf_admin.h"
#include "adf_cfg_services.h"
#include "adf_common_drv.h"
#include "adf_kpt.h"
static bool adf_kpt_supported(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
return hw_data->accel_capabilities_mask & ICP_ACCEL_CAPABILITIES_KPT;
}
int adf_enable_kpt(struct adf_accel_dev *accel_dev)
{
struct adf_kpt_interface_data *user_data = GET_KPT_USER_DATA(accel_dev);
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
dma_addr_t paddr;
void *vaddr;
int ret;
int svc;
/* Return 0 if KPT is not supported by the hardware */
if (!adf_kpt_supported(accel_dev))
return 0;
if (!user_data->enable) {
/* Disable KPT capability if user has not enabled it */
hw_data->accel_capabilities_mask &= ~ICP_ACCEL_CAPABILITIES_KPT;
return 0;
}
svc = adf_get_service_enabled(accel_dev);
if (svc < 0)
return svc;
if (svc != SVC_ASYM) {
dev_err(&GET_DEV(accel_dev),
"KPT can only be enabled when service is configured as 'asym'\n");
return -EINVAL;
}
vaddr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE, &paddr,
GFP_KERNEL);
if (!vaddr)
return -ENOMEM;
ret = adf_send_admin_kpt_init(accel_dev, vaddr, PAGE_SIZE, paddr);
dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE, vaddr, paddr);
return ret;
}

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright(c) 2026 Intel Corporation */
#ifndef ADF_KPT_H_
#define ADF_KPT_H_
#include <linux/types.h>
#define GET_KPT_CFG_DATA(accel_dev) (&(accel_dev)->hw_device->kpt_data)
#define GET_KPT_USER_DATA(accel_dev) (&(accel_dev)->hw_device->kpt_data.user_input)
struct adf_accel_dev;
struct adf_kpt_interface_data {
bool enable;
bool swk_shared;
unsigned int swk_cnt_per_fn;
unsigned int swk_cnt_per_pasid;
unsigned int swk_max_ttl;
};
struct adf_kpt_hw_data {
unsigned int max_swk_cnt_per_fn_pasid;
unsigned int max_swk_ttl;
struct adf_kpt_interface_data user_input;
};
int adf_enable_kpt(struct adf_accel_dev *accel_dev);
#endif /* ADF_KPT_H_ */

View File

@ -0,0 +1,296 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2026 Intel Corporation */
#include <linux/sysfs.h>
#include <linux/types.h>
#include "adf_cfg.h"
#include "adf_cfg_services.h"
#include "adf_common_drv.h"
#include "adf_kpt.h"
#include "adf_sysfs_kpt.h"
static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
user_data = GET_KPT_USER_DATA(accel_dev);
return sysfs_emit(buf, "%d\n", user_data->enable);
}
static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct adf_kpt_interface_data *user_data;
struct adf_hw_device_data *hw_data;
struct adf_accel_dev *accel_dev;
bool enable;
int ret;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
if (adf_dev_started(accel_dev)) {
dev_info(dev, "Device qat_dev%d must be down before enabling KPT\n",
accel_dev->accel_id);
return -EINVAL;
}
if (adf_get_service_enabled(accel_dev) != SVC_ASYM) {
dev_info(dev, "KPT can only be enabled when the asymmetric service is enabled\n");
return -EINVAL;
}
hw_data = GET_HW_DATA(accel_dev);
/*
* Restore the KPT capability bit in the device's capabilities mask
* before processing user input, as the bit may have been cleared if
* KPT was previously disabled by the user.
*/
hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev);
if (!hw_data->accel_capabilities_mask)
return -EINVAL;
ret = kstrtobool(buf, &enable);
if (ret)
return ret;
user_data = GET_KPT_USER_DATA(accel_dev);
user_data->enable = enable;
return count;
}
static DEVICE_ATTR_RW(enable);
static ssize_t swk_shared_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
user_data = GET_KPT_USER_DATA(accel_dev);
return sysfs_emit(buf, "%d\n", user_data->swk_shared);
}
static ssize_t swk_shared_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
bool swk_shared;
int ret;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
if (adf_dev_started(accel_dev)) {
dev_info(dev, "Device qat_dev%d must be down before setting swk_shared\n",
accel_dev->accel_id);
return -EINVAL;
}
ret = kstrtobool(buf, &swk_shared);
if (ret)
return ret;
user_data = GET_KPT_USER_DATA(accel_dev);
user_data->swk_shared = swk_shared;
return count;
}
static DEVICE_ATTR_RW(swk_shared);
static ssize_t swk_max_ttl_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
user_data = GET_KPT_USER_DATA(accel_dev);
return sysfs_emit(buf, "%u\n", user_data->swk_max_ttl);
}
static ssize_t swk_max_ttl_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct adf_kpt_hw_data *kpt_data;
struct adf_accel_dev *accel_dev;
unsigned int swk_max_ttl;
int ret;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
if (adf_dev_started(accel_dev)) {
dev_info(dev, "Device qat_dev%d must be down before setting swk_max_ttl\n",
accel_dev->accel_id);
return -EINVAL;
}
ret = kstrtouint(buf, 10, &swk_max_ttl);
if (ret)
return ret;
kpt_data = GET_KPT_CFG_DATA(accel_dev);
if (swk_max_ttl > kpt_data->max_swk_ttl) {
dev_info(dev, "Configuration value is out of range (%u - %u)\n",
0, kpt_data->max_swk_ttl);
return -EINVAL;
}
kpt_data->user_input.swk_max_ttl = swk_max_ttl;
return count;
}
static DEVICE_ATTR_RW(swk_max_ttl);
static ssize_t swk_cnt_per_fn_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
user_data = GET_KPT_USER_DATA(accel_dev);
return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_fn);
}
static ssize_t swk_cnt_per_fn_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct adf_kpt_hw_data *kpt_data;
struct adf_accel_dev *accel_dev;
unsigned int swk_cnt_per_fn;
int ret;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
if (adf_dev_started(accel_dev)) {
dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_fn\n",
accel_dev->accel_id);
return -EINVAL;
}
ret = kstrtouint(buf, 10, &swk_cnt_per_fn);
if (ret)
return ret;
kpt_data = GET_KPT_CFG_DATA(accel_dev);
if (swk_cnt_per_fn > kpt_data->max_swk_cnt_per_fn_pasid) {
dev_info(dev, "swk_cnt_per_fn: value out of range (0 - %u)\n",
kpt_data->max_swk_cnt_per_fn_pasid);
return -EINVAL;
}
kpt_data->user_input.swk_cnt_per_fn = swk_cnt_per_fn;
return count;
}
static DEVICE_ATTR_RW(swk_cnt_per_fn);
static ssize_t swk_cnt_per_pasid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct adf_kpt_interface_data *user_data;
struct adf_accel_dev *accel_dev;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
user_data = GET_KPT_USER_DATA(accel_dev);
return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_pasid);
}
static ssize_t swk_cnt_per_pasid_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct adf_kpt_hw_data *kpt_data;
struct adf_accel_dev *accel_dev;
unsigned int swk_cnt_per_pasid;
int ret;
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
if (!accel_dev)
return -EINVAL;
if (adf_dev_started(accel_dev)) {
dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_pasid\n",
accel_dev->accel_id);
return -EINVAL;
}
ret = kstrtouint(buf, 10, &swk_cnt_per_pasid);
if (ret)
return ret;
kpt_data = GET_KPT_CFG_DATA(accel_dev);
if (swk_cnt_per_pasid > kpt_data->max_swk_cnt_per_fn_pasid) {
dev_info(dev, "swk_cnt_per_pasid: value out of range (0 - %u)\n",
kpt_data->max_swk_cnt_per_fn_pasid);
return -EINVAL;
}
kpt_data->user_input.swk_cnt_per_pasid = swk_cnt_per_pasid;
return count;
}
static DEVICE_ATTR_RW(swk_cnt_per_pasid);
static struct attribute *qat_kpt_attrs[] = {
&dev_attr_enable.attr,
&dev_attr_swk_shared.attr,
&dev_attr_swk_max_ttl.attr,
&dev_attr_swk_cnt_per_fn.attr,
&dev_attr_swk_cnt_per_pasid.attr,
NULL,
};
static const struct attribute_group qat_kpt_group = {
.attrs = qat_kpt_attrs,
.name = "qat_kpt",
};
int adf_sysfs_init_kpt(struct adf_accel_dev *accel_dev)
{
int ret;
ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_kpt_group);
if (ret) {
dev_err(&GET_DEV(accel_dev), "Failed to create qat_kpt attribute group\n");
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(adf_sysfs_init_kpt);

View File

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright(c) 2026 Intel Corporation */
#ifndef ADF_SYSFS_KPT_H_
#define ADF_SYSFS_KPT_H_
struct adf_accel_dev;
int adf_sysfs_init_kpt(struct adf_accel_dev *accel_dev);
#endif /* ADF_SYSFS_KPT_H_ */

View File

@ -31,6 +31,7 @@ enum icp_qat_fw_init_admin_cmd_id {
ICP_QAT_FW_RL_REMOVE = 136,
ICP_QAT_FW_TL_START = 137,
ICP_QAT_FW_TL_STOP = 138,
ICP_QAT_FW_KPT_ENABLE = 144,
ICP_QAT_FW_SVN_READ = 146,
ICP_QAT_FW_SVN_COMMIT = 147,
};
@ -212,4 +213,11 @@ struct icp_qat_fw_init_admin_pm_info {
__u32 resvrd3[6];
};
struct icp_qat_fw_init_admin_kpt_cfg {
__u32 swk_cnt_per_fn;
__u32 swk_cnt_per_pasid;
__u32 swk_ttl_in_secs;
__u32 swk_shared_disable;
};
#endif

View File

@ -114,7 +114,8 @@ enum icp_qat_capabilities_mask {
ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = BIT(24),
ICP_ACCEL_CAPABILITIES_LZ4S_COMPRESSION = BIT(25),
ICP_ACCEL_CAPABILITIES_AES_V2 = BIT(26),
/* Bits 27-28 are currently reserved */
ICP_ACCEL_CAPABILITIES_KPT = BIT(27),
/* Bit 28 is currently reserved */
ICP_ACCEL_CAPABILITIES_ZUC_256 = BIT(29),
ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT = BIT(30),
};