Commit e0792316 authored by Lucas Segarra Fernandez's avatar Lucas Segarra Fernandez Committed by Herbert Xu
Browse files

crypto: qat - add pm_status debugfs file



QAT devices implement a mechanism that allows them to go autonomously
to a low power state depending on the load.

Expose power management info by providing the "pm_status" file under
debugfs. This includes PM state, PM event log, PM event counters, PM HW
CSRs, per-resource type constrain counters and per-domain power gating
status specific to the QAT device.

This information is retrieved from (1) the FW by means of
ICP_QAT_FW_PM_INFO command, (2) CSRs and (3) counters collected by the
device driver.

In addition, add logic to keep track and report power management event
interrupts and acks/nacks sent to FW to allow/prevent state transitions.

Signed-off-by: default avatarLucas Segarra Fernandez <lucas.segarra.fernandez@intel.com>
Reviewed-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 756762de
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -59,3 +59,12 @@ Description: (RO) Read returns the device health status.

		The driver does not monitor for Heartbeat. It is left for a user
		to poll the status periodically.

What:		/sys/kernel/debug/qat_<device>_<BDF>/pm_status
Date:		January 2024
KernelVersion:	6.7
Contact:	qat-linux@intel.com
Description:	(RO) Read returns power management information specific to the
		QAT device.

		This attribute is only available for qat_4xxx devices.
+2 −0
Original line number Diff line number Diff line
@@ -32,8 +32,10 @@ intel_qat-objs := adf_cfg.o \

intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \
				adf_fw_counters.o \
				adf_gen4_pm_debugfs.o \
				adf_heartbeat.o \
				adf_heartbeat_dbgfs.o \
				adf_pm_dbgfs.o \
				adf_dbgfs.o

intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \
+13 −0
Original line number Diff line number Diff line
@@ -291,6 +291,18 @@ struct adf_dc_data {
	dma_addr_t ovf_buff_p;
};

struct adf_pm {
	struct dentry *debugfs_pm_status;
	bool present;
	int idle_irq_counters;
	int throttle_irq_counters;
	int fw_irq_counters;
	int host_ack_counter;
	int host_nack_counter;
	ssize_t (*print_pm_status)(struct adf_accel_dev *accel_dev,
				   char __user *buf, size_t count, loff_t *pos);
};

struct adf_accel_dev {
	struct adf_etr_data *transport;
	struct adf_hw_device_data *hw_device;
@@ -298,6 +310,7 @@ struct adf_accel_dev {
	struct adf_fw_loader_data *fw_loader;
	struct adf_admin_comms *admin;
	struct adf_dc_data *dc_data;
	struct adf_pm power_management;
	struct list_head crypto_list;
	struct list_head compression_list;
	unsigned long status;
+27 −0
Original line number Diff line number Diff line
@@ -379,6 +379,33 @@ int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay)
	return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}

int adf_get_pm_info(struct adf_accel_dev *accel_dev, dma_addr_t p_state_addr,
		    size_t buff_size)
{
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	struct icp_qat_fw_init_admin_req req = { };
	struct icp_qat_fw_init_admin_resp resp;
	u32 ae_mask = hw_data->admin_ae_mask;
	int ret;

	/* Query pm info via init/admin cmd */
	if (!accel_dev->admin) {
		dev_err(&GET_DEV(accel_dev), "adf_admin is not available\n");
		return -EFAULT;
	}

	req.cmd_id = ICP_QAT_FW_PM_INFO;
	req.init_cfg_sz = buff_size;
	req.init_cfg_ptr = p_state_addr;

	ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
	if (ret)
		dev_err(&GET_DEV(accel_dev),
			"Failed to query power-management info\n");

	return ret;
}

int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
	struct adf_admin_comms *admin;
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ 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_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_init_arb(struct adf_accel_dev *accel_dev);
void adf_exit_arb(struct adf_accel_dev *accel_dev);
void adf_update_ring_arb(struct adf_etr_ring_data *ring);
Loading