Commit e5745f34 authored by Wojciech Ziemba's avatar Wojciech Ziemba Committed by Herbert Xu
Browse files

crypto: qat - enable power management for QAT GEN4



Add support for HW QAT Power Management (PM) feature.
This feature is enabled at init time (1) by sending an admin message to
the firmware, targeting the admin AE, that sets the idle time before
the device changes state and (2) by unmasking the PM source of interrupt
in ERRMSK2.

The interrupt handler is extended to handle a PM interrupt which
is triggered by HW when a PM transition occurs. In this case, the
driver responds acknowledging the transaction using the HOST_MSG
mailbox.

Signed-off-by: default avatarWojciech Ziemba <wojciech.ziemba@intel.com>
Co-developed-by: default avatarMarcinx Malinowski <marcinx.malinowski@intel.com>
Signed-off-by: default avatarMarcinx Malinowski <marcinx.malinowski@intel.com>
Reviewed-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: default avatarMarco Chiappero <marco.chiappero@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent f734409c
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <adf_common_drv.h>
#include <adf_gen4_hw_data.h>
#include <adf_gen4_pfvf.h>
#include <adf_gen4_pm.h>
#include "adf_4xxx_hw_data.h"
#include "icp_qat_hw.h"

@@ -257,18 +258,18 @@ static int adf_init_device(struct adf_accel_dev *accel_dev)

	/* Temporarily mask PM interrupt */
	csr = ADF_CSR_RD(addr, ADF_GEN4_ERRMSK2);
	csr |= ADF_4XXX_PM_SOU;
	csr |= ADF_GEN4_PM_SOU;
	ADF_CSR_WR(addr, ADF_GEN4_ERRMSK2, csr);

	/* Set DRV_ACTIVE bit to power up the device */
	ADF_CSR_WR(addr, ADF_4XXX_PM_INTERRUPT, ADF_4XXX_PM_DRV_ACTIVE);
	ADF_CSR_WR(addr, ADF_GEN4_PM_INTERRUPT, ADF_GEN4_PM_DRV_ACTIVE);

	/* Poll status register to make sure the device is powered up */
	ret = read_poll_timeout(ADF_CSR_RD, status,
				status & ADF_4XXX_PM_INIT_STATE,
				ADF_4XXX_PM_POLL_DELAY_US,
				ADF_4XXX_PM_POLL_TIMEOUT_US, true, addr,
				ADF_4XXX_PM_STATUS);
				status & ADF_GEN4_PM_INIT_STATE,
				ADF_GEN4_PM_POLL_DELAY_US,
				ADF_GEN4_PM_POLL_TIMEOUT_US, true, addr,
				ADF_GEN4_PM_STATUS);
	if (ret)
		dev_err(&GET_DEV(accel_dev), "Failed to power up the device\n");

@@ -354,6 +355,8 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data)
	hw_data->set_ssm_wdtimer = adf_gen4_set_ssm_wdtimer;
	hw_data->disable_iov = adf_disable_sriov;
	hw_data->ring_pair_reset = adf_gen4_ring_pair_reset;
	hw_data->enable_pm = adf_gen4_enable_pm;
	hw_data->handle_pm_interrupt = adf_gen4_handle_pm_interrupt;

	adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
	adf_gen4_init_pf_pfvf_ops(&hw_data->pfvf_ops);
+0 −10
Original line number Diff line number Diff line
@@ -49,16 +49,6 @@
#define ADF_4XXX_ADMINMSGLR_OFFSET	(0x500578)
#define ADF_4XXX_MAILBOX_BASE_OFFSET	(0x600970)

/* Power management */
#define ADF_4XXX_PM_POLL_DELAY_US	20
#define ADF_4XXX_PM_POLL_TIMEOUT_US	USEC_PER_SEC
#define ADF_4XXX_PM_STATUS		(0x50A00C)
#define ADF_4XXX_PM_INTERRUPT		(0x50A028)
#define ADF_4XXX_PM_DRV_ACTIVE		BIT(20)
#define ADF_4XXX_PM_INIT_STATE		BIT(21)
/* Power management source in ERRSOU2 and ERRMSK2 */
#define ADF_4XXX_PM_SOU			BIT(18)

/* Firmware Binaries */
#define ADF_4XXX_FW		"qat_4xxx.bin"
#define ADF_4XXX_MMP		"qat_4xxx_mmp.bin"
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ intel_qat-objs := adf_cfg.o \
	adf_hw_arbiter.o \
	adf_gen2_hw_data.o \
	adf_gen4_hw_data.o \
	adf_gen4_pm.o \
	qat_crypto.o \
	qat_algs.o \
	qat_asym_algs.o \
+2 −0
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@ struct adf_hw_device_data {
	void (*exit_arb)(struct adf_accel_dev *accel_dev);
	const u32 *(*get_arb_mapping)(void);
	int (*init_device)(struct adf_accel_dev *accel_dev);
	int (*enable_pm)(struct adf_accel_dev *accel_dev);
	bool (*handle_pm_interrupt)(struct adf_accel_dev *accel_dev);
	void (*disable_iov)(struct adf_accel_dev *accel_dev);
	void (*configure_iov_threads)(struct adf_accel_dev *accel_dev,
				      bool enable);
+37 −0
Original line number Diff line number Diff line
@@ -251,6 +251,43 @@ int adf_send_admin_init(struct adf_accel_dev *accel_dev)
}
EXPORT_SYMBOL_GPL(adf_send_admin_init);

/**
 * adf_init_admin_pm() - Function sends PM init message to FW
 * @accel_dev: Pointer to acceleration device.
 * @idle_delay: QAT HW idle time before power gating is initiated.
 *		000 - 64us
 *		001 - 128us
 *		010 - 256us
 *		011 - 512us
 *		100 - 1ms
 *		101 - 2ms
 *		110 - 4ms
 *		111 - 8ms
 *
 * Function sends to the FW the admin init message for the PM state
 * configuration.
 *
 * Return: 0 on success, error code otherwise.
 */
int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay)
{
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	struct icp_qat_fw_init_admin_resp resp = {0};
	struct icp_qat_fw_init_admin_req req = {0};
	u32 ae_mask = hw_data->admin_ae_mask;

	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_STATE_CONFIG;
	req.idle_filter = idle_delay;

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

int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
	struct adf_admin_comms *admin;
Loading