Skip to content

Commit

Permalink
crypto: qat - add rate limiting feature to qat_4xxx
Browse files Browse the repository at this point in the history
The Rate Limiting (RL) feature allows to control the rate of requests
that can be submitted on a ring pair (RP). This allows sharing a QAT
device among multiple users while ensuring a guaranteed throughput.

The driver provides a mechanism that allows users to set policies, that
are programmed to the device. The device is then enforcing those policies.

Configuration of RL is accomplished through entities called SLAs
(Service Level Agreement). Each SLA object gets a unique identifier
and defines the limitations for a single service across up to four
ring pairs (RPs count allocated to a single VF).

The rate is determined using two fields:
  * CIR (Committed Information Rate), i.e., the guaranteed rate.
  * PIR (Peak Information Rate), i.e., the maximum rate achievable
    when the device has available resources.
The rate values are expressed in permille scale i.e. 0-1000.
Ring pair selection is achieved by providing a 64-bit mask, where
each bit corresponds to one of the ring pairs.

This adds an interface and logic that allow to add, update, retrieve
and remove an SLA.

Signed-off-by: Damian Muszynski <[email protected]>
Reviewed-by: Giovanni Cabiddu <[email protected]>
Reviewed-by: Tero Kristo <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
dmuszyns authored and herbertx committed Oct 27, 2023
1 parent c7fd537 commit d9fb840
Show file tree
Hide file tree
Showing 13 changed files with 1,590 additions and 1 deletion.
20 changes: 20 additions & 0 deletions drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,24 @@ static u32 get_heartbeat_clock(struct adf_hw_device_data *self)
return ADF_4XXX_KPT_COUNTER_FREQ;
}

static void adf_init_rl_data(struct adf_rl_hw_data *rl_data)
{
rl_data->pciout_tb_offset = ADF_GEN4_RL_TOKEN_PCIEOUT_BUCKET_OFFSET;
rl_data->pciin_tb_offset = ADF_GEN4_RL_TOKEN_PCIEIN_BUCKET_OFFSET;
rl_data->r2l_offset = ADF_GEN4_RL_R2L_OFFSET;
rl_data->l2c_offset = ADF_GEN4_RL_L2C_OFFSET;
rl_data->c2s_offset = ADF_GEN4_RL_C2S_OFFSET;

rl_data->pcie_scale_div = ADF_4XXX_RL_PCIE_SCALE_FACTOR_DIV;
rl_data->pcie_scale_mul = ADF_4XXX_RL_PCIE_SCALE_FACTOR_MUL;
rl_data->dcpr_correction = ADF_4XXX_RL_DCPR_CORRECTION;
rl_data->max_tp[ADF_SVC_ASYM] = ADF_4XXX_RL_MAX_TP_ASYM;
rl_data->max_tp[ADF_SVC_SYM] = ADF_4XXX_RL_MAX_TP_SYM;
rl_data->max_tp[ADF_SVC_DC] = ADF_4XXX_RL_MAX_TP_DC;
rl_data->scan_interval = ADF_4XXX_RL_SCANS_PER_SEC;
rl_data->scale_ref = ADF_4XXX_RL_SLICE_REF;
}

static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
{
struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_4XXX_PMISC_BAR];
Expand Down Expand Up @@ -594,12 +612,14 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id)
hw_data->stop_timer = adf_gen4_timer_stop;
hw_data->get_hb_clock = get_heartbeat_clock;
hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE;
hw_data->clock_frequency = ADF_4XXX_AE_FREQ;

adf_gen4_set_err_mask(&hw_data->dev_err_mask);
adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
adf_gen4_init_pf_pfvf_ops(&hw_data->pfvf_ops);
adf_gen4_init_dc_ops(&hw_data->dc_ops);
adf_gen4_init_ras_ops(&hw_data->ras_ops);
adf_init_rl_data(&hw_data->rl_data);
}

void adf_clean_hw_data_4xxx(struct adf_hw_device_data *hw_data)
Expand Down
13 changes: 12 additions & 1 deletion drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,19 @@
#define ADF_402XX_ASYM_OBJ "qat_402xx_asym.bin"
#define ADF_402XX_ADMIN_OBJ "qat_402xx_admin.bin"

/* RL constants */
#define ADF_4XXX_RL_PCIE_SCALE_FACTOR_DIV 100
#define ADF_4XXX_RL_PCIE_SCALE_FACTOR_MUL 102
#define ADF_4XXX_RL_DCPR_CORRECTION 1
#define ADF_4XXX_RL_SCANS_PER_SEC 954
#define ADF_4XXX_RL_MAX_TP_ASYM 173750UL
#define ADF_4XXX_RL_MAX_TP_SYM 95000UL
#define ADF_4XXX_RL_MAX_TP_DC 45000UL
#define ADF_4XXX_RL_SLICE_REF 1000UL

/* Clocks frequency */
#define ADF_4XXX_KPT_COUNTER_FREQ (100 * HZ_PER_MHZ)
#define ADF_4XXX_KPT_COUNTER_FREQ (100 * HZ_PER_MHZ)
#define ADF_4XXX_AE_FREQ (1000 * HZ_PER_MHZ)

/* qat_4xxx fuse bits are different from old GENs, redefine them */
enum icp_qat_4xxx_slice_mask {
Expand Down
2 changes: 2 additions & 0 deletions drivers/crypto/intel/qat/qat_common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ intel_qat-objs := adf_cfg.o \
qat_algs.o \
qat_asym_algs.o \
qat_algs_send.o \
adf_rl.o \
adf_rl_admin.o \
qat_uclo.o \
qat_hal.o \
qat_bl.o
Expand Down
3 changes: 3 additions & 0 deletions drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/ratelimit.h>
#include <linux/types.h>
#include "adf_cfg_common.h"
#include "adf_rl.h"
#include "adf_pfvf_msg.h"

#define ADF_DH895XCC_DEVICE_NAME "dh895xcc"
Expand Down Expand Up @@ -247,6 +248,7 @@ struct adf_hw_device_data {
struct adf_dc_ops dc_ops;
struct adf_ras_ops ras_ops;
struct adf_dev_err_mask dev_err_mask;
struct adf_rl_hw_data rl_data;
const char *fw_name;
const char *fw_mmp_name;
u32 fuses;
Expand Down Expand Up @@ -358,6 +360,7 @@ struct adf_accel_dev {
struct adf_accel_pci accel_pci_dev;
struct adf_timer *timer;
struct adf_heartbeat *heartbeat;
struct adf_rl *rate_limiting;
union {
struct {
/* protects VF2PF interrupts access */
Expand Down
47 changes: 47 additions & 0 deletions drivers/crypto/intel/qat/qat_common/adf_admin.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,53 @@ static int adf_get_fw_capabilities(struct adf_accel_dev *accel_dev, u16 *caps)
return 0;
}

int adf_send_admin_rl_init(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_slice_cnt *slices)
{
u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };
int ret;

req.cmd_id = ICP_QAT_FW_RL_INIT;

ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
if (ret)
return ret;

memcpy(slices, &resp.slices, sizeof(*slices));

return 0;
}

int adf_send_admin_rl_add_update(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_req *req)
{
u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
struct icp_qat_fw_init_admin_resp resp = { };

/*
* req struct filled in rl implementation. Used commands
* ICP_QAT_FW_RL_ADD for a new SLA
* ICP_QAT_FW_RL_UPDATE for update SLA
*/
return adf_send_admin(accel_dev, req, &resp, ae_mask);
}

int adf_send_admin_rl_delete(struct adf_accel_dev *accel_dev, u16 node_id,
u8 node_type)
{
u32 ae_mask = accel_dev->hw_device->admin_ae_mask;
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };

req.cmd_id = ICP_QAT_FW_RL_REMOVE;
req.node_id = node_id;
req.node_type = node_type;

return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}

/**
* adf_send_admin_init() - Function sends init message to FW
* @accel_dev: Pointer to acceleration device.
Expand Down
8 changes: 8 additions & 0 deletions drivers/crypto/intel/qat/qat_common/adf_admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#ifndef ADF_ADMIN
#define ADF_ADMIN

#include "icp_qat_fw_init_admin.h"

struct adf_accel_dev;

int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
Expand All @@ -12,6 +14,12 @@ int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u
int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay);
int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt);
int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks);
int adf_send_admin_rl_init(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_slice_cnt *slices);
int adf_send_admin_rl_add_update(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_req *req);
int adf_send_admin_rl_delete(struct adf_accel_dev *accel_dev, u16 node_id,
u8 node_type);
int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp);
int adf_get_pm_info(struct adf_accel_dev *accel_dev, dma_addr_t p_state_addr, size_t buff_size);
int adf_get_cnv_stats(struct adf_accel_dev *accel_dev, u16 ae, u16 *err_cnt, u16 *latest_err);
Expand Down
7 changes: 7 additions & 0 deletions drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ do { \
/* Number of heartbeat counter pairs */
#define ADF_NUM_HB_CNT_PER_AE ADF_NUM_THREADS_PER_AE

/* Rate Limiting */
#define ADF_GEN4_RL_R2L_OFFSET 0x508000
#define ADF_GEN4_RL_L2C_OFFSET 0x509000
#define ADF_GEN4_RL_C2S_OFFSET 0x508818
#define ADF_GEN4_RL_TOKEN_PCIEIN_BUCKET_OFFSET 0x508800
#define ADF_GEN4_RL_TOKEN_PCIEOUT_BUCKET_OFFSET 0x508804

void adf_gen4_set_ssm_wdtimer(struct adf_accel_dev *accel_dev);
void adf_gen4_init_hw_csr_ops(struct adf_hw_csr_ops *csr_ops);
int adf_gen4_ring_pair_reset(struct adf_accel_dev *accel_dev, u32 bank_number);
Expand Down
10 changes: 10 additions & 0 deletions drivers/crypto/intel/qat/qat_common/adf_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "adf_common_drv.h"
#include "adf_dbgfs.h"
#include "adf_heartbeat.h"
#include "adf_rl.h"
#include "adf_sysfs_ras_counters.h"

static LIST_HEAD(service_table);
Expand Down Expand Up @@ -137,6 +138,9 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev)
}

adf_heartbeat_init(accel_dev);
ret = adf_rl_init(accel_dev);
if (ret && ret != -EOPNOTSUPP)
return ret;

/*
* Subservice initialisation is divided into two stages: init and start.
Expand Down Expand Up @@ -212,6 +216,9 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev)
}

adf_heartbeat_start(accel_dev);
ret = adf_rl_start(accel_dev);
if (ret && ret != -EOPNOTSUPP)
return ret;

list_for_each_entry(service, &service_table, list) {
if (service->event_hld(accel_dev, ADF_EVENT_START)) {
Expand Down Expand Up @@ -272,6 +279,7 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev)
!test_bit(ADF_STATUS_STARTING, &accel_dev->status))
return;

adf_rl_stop(accel_dev);
adf_dbgfs_rm(accel_dev);
adf_sysfs_stop_ras(accel_dev);

Expand Down Expand Up @@ -359,6 +367,8 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
clear_bit(accel_dev->accel_id, service->init_status);
}

adf_rl_exit(accel_dev);

if (hw_data->ras_ops.disable_ras_errors)
hw_data->ras_ops.disable_ras_errors(accel_dev);

Expand Down
Loading

0 comments on commit d9fb840

Please sign in to comment.