// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
/* Copyright(c) 2014 - 2020 Intel Corporation */
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/iopoll.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include "adf_accel_devices.h"
#include "adf_admin.h"
#include "adf_common_drv.h"
#include "adf_cfg.h"
#include "adf_heartbeat.h"
#include "icp_qat_fw_init_admin.h"
#define ADF_ADMIN_MAILBOX_STRIDE 0 x1000
#define ADF_ADMINMSG_LEN 32
#define ADF_CONST_TABLE_SIZE 1024
#define ADF_ADMIN_POLL_DELAY_US 20
#define ADF_ADMIN_POLL_TIMEOUT_US (5 * USEC_PER_SEC)
#define ADF_ONE_AE 1
static const u8 const_tab[1024 ] __aligned(1024 ) = {
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x01, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x21, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x03, 0 x02, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x03, 0 x01,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x03, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x13, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x13, 0 x02, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x13, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x13,
0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x23, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x33, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x06, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x06, 0 x02, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x02, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x01, 0 x23, 0 x45, 0 x67, 0 x89, 0 xab, 0 xcd, 0 xef, 0 xfe, 0 xdc, 0 xba, 0 x98, 0 x76,
0 x54, 0 x32, 0 x10, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x67, 0 x45, 0 x23, 0 x01, 0 xef, 0 xcd, 0 xab,
0 x89, 0 x98, 0 xba, 0 xdc, 0 xfe, 0 x10, 0 x32, 0 x54, 0 x76, 0 xc3, 0 xd2, 0 xe1, 0 xf0,
0 x00, 0 x00, 0 x00, 0 x00, 0 x11, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x40, 0 x00, 0 x00, 0 x00, 0 x00, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 xc1, 0 x05, 0 x9e,
0 xd8, 0 x36, 0 x7c, 0 xd5, 0 x07, 0 x30, 0 x70, 0 xdd, 0 x17, 0 xf7, 0 x0e, 0 x59, 0 x39,
0 xff, 0 xc0, 0 x0b, 0 x31, 0 x68, 0 x58, 0 x15, 0 x11, 0 x64, 0 xf9, 0 x8f, 0 xa7, 0 xbe,
0 xfa, 0 x4f, 0 xa4, 0 x04, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x6a, 0 x09, 0 xe6, 0 x67, 0 xbb, 0 x67, 0 xae,
0 x85, 0 x3c, 0 x6e, 0 xf3, 0 x72, 0 xa5, 0 x4f, 0 xf5, 0 x3a, 0 x51, 0 x0e, 0 x52, 0 x7f,
0 x9b, 0 x05, 0 x68, 0 x8c, 0 x1f, 0 x83, 0 xd9, 0 xab, 0 x5b, 0 xe0, 0 xcd, 0 x19, 0 x05,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 xcb, 0 xbb, 0 x9d, 0 x5d, 0 xc1, 0 x05, 0 x9e, 0 xd8, 0 x62, 0 x9a, 0 x29,
0 x2a, 0 x36, 0 x7c, 0 xd5, 0 x07, 0 x91, 0 x59, 0 x01, 0 x5a, 0 x30, 0 x70, 0 xdd, 0 x17,
0 x15, 0 x2f, 0 xec, 0 xd8, 0 xf7, 0 x0e, 0 x59, 0 x39, 0 x67, 0 x33, 0 x26, 0 x67, 0 xff,
0 xc0, 0 x0b, 0 x31, 0 x8e, 0 xb4, 0 x4a, 0 x87, 0 x68, 0 x58, 0 x15, 0 x11, 0 xdb, 0 x0c,
0 x2e, 0 x0d, 0 x64, 0 xf9, 0 x8f, 0 xa7, 0 x47, 0 xb5, 0 x48, 0 x1d, 0 xbe, 0 xfa, 0 x4f,
0 xa4, 0 x06, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x6a, 0 x09, 0 xe6, 0 x67, 0 xf3, 0 xbc, 0 xc9, 0 x08, 0 xbb,
0 x67, 0 xae, 0 x85, 0 x84, 0 xca, 0 xa7, 0 x3b, 0 x3c, 0 x6e, 0 xf3, 0 x72, 0 xfe, 0 x94,
0 xf8, 0 x2b, 0 xa5, 0 x4f, 0 xf5, 0 x3a, 0 x5f, 0 x1d, 0 x36, 0 xf1, 0 x51, 0 x0e, 0 x52,
0 x7f, 0 xad, 0 xe6, 0 x82, 0 xd1, 0 x9b, 0 x05, 0 x68, 0 x8c, 0 x2b, 0 x3e, 0 x6c, 0 x1f,
0 x1f, 0 x83, 0 xd9, 0 xab, 0 xfb, 0 x41, 0 xbd, 0 x6b, 0 x5b, 0 xe0, 0 xcd, 0 x19, 0 x13,
0 x7e, 0 x21, 0 x79, 0 x14, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x40, 0 x00, 0 x00, 0 x00, 0 x00, 0 x16, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x80, 0 x00, 0 x00, 0 x00, 0 x00, 0 x12, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x40, 0 x00, 0 x00, 0 x00, 0 x00, 0 x18,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x14, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x14, 0 x01, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x15, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x15, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x14, 0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x14, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x15, 0 x02,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x15, 0 x03, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x24, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x25, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x24, 0 x02, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x25,
0 x02, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x12, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x12, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x43, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x43, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x45, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x45, 0 x01, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x44, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x44, 0 x01,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x2B, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x2B, 0 x01, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x20, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x15, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x80, 0 x00, 0 x00, 0 x00, 0 x00, 0 x17, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x10, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00,
0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00};
struct adf_admin_comms {
dma_addr_t phy_addr;
dma_addr_t const_tbl_addr;
void *virt_addr;
void *virt_tbl_addr;
void __iomem *mailbox_addr;
struct mutex lock; /* protects adf_admin_comms struct */
};
static int adf_put_admin_msg_sync(struct adf_accel_dev *accel_dev, u32 ae,
void *in, void *out)
{
int ret;
u32 status;
struct adf_admin_comms *admin = accel_dev->admin;
int offset = ae * ADF_ADMINMSG_LEN * 2 ;
void __iomem *mailbox = admin->mailbox_addr;
int mb_offset = ae * ADF_ADMIN_MAILBOX_STRIDE;
struct icp_qat_fw_init_admin_req *request = in;
mutex_lock(&admin->lock);
if (ADF_CSR_RD(mailbox, mb_offset) == 1 ) {
mutex_unlock(&admin->lock);
return -EAGAIN;
}
memcpy(admin->virt_addr + offset, in, ADF_ADMINMSG_LEN);
ADF_CSR_WR(mailbox, mb_offset, 1 );
ret = read_poll_timeout(ADF_CSR_RD, status, status == 0 ,
ADF_ADMIN_POLL_DELAY_US,
ADF_ADMIN_POLL_TIMEOUT_US, true ,
mailbox, mb_offset);
if (ret < 0 ) {
/* Response timeout */
dev_err(&GET_DEV(accel_dev),
"Failed to send admin msg %d to accelerator %d\n" ,
request->cmd_id, ae);
} else {
/* Response received from admin message, we can now
* make response data available in "out" parameter.
*/
memcpy(out, admin->virt_addr + offset +
ADF_ADMINMSG_LEN, ADF_ADMINMSG_LEN);
}
mutex_unlock(&admin->lock);
return ret;
}
static int adf_send_admin(struct adf_accel_dev *accel_dev,
struct icp_qat_fw_init_admin_req *req,
struct icp_qat_fw_init_admin_resp *resp,
const unsigned long ae_mask)
{
u32 ae;
for_each_set_bit(ae, &ae_mask, ICP_QAT_HW_AE_DELIMITER)
if (adf_put_admin_msg_sync(accel_dev, ae, req, resp) ||
resp->status)
return -EFAULT;
return 0 ;
}
static int adf_init_ae(struct adf_accel_dev *accel_dev)
{
struct icp_qat_fw_init_admin_req req;
struct icp_qat_fw_init_admin_resp resp;
struct adf_hw_device_data *hw_device = accel_dev->hw_device;
u32 ae_mask = hw_device->ae_mask;
memset(&req, 0 , sizeof (req));
memset(&resp, 0 , sizeof (resp));
req.cmd_id = ICP_QAT_FW_INIT_AE;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
static int adf_set_fw_constants(struct adf_accel_dev *accel_dev)
{
struct icp_qat_fw_init_admin_req req;
struct icp_qat_fw_init_admin_resp resp;
struct adf_hw_device_data *hw_device = accel_dev->hw_device;
u32 ae_mask = hw_device->admin_ae_mask ?: hw_device->ae_mask;
memset(&req, 0 , sizeof (req));
memset(&resp, 0 , sizeof (resp));
req.cmd_id = ICP_QAT_FW_CONSTANTS_CFG;
req.init_cfg_sz = ADF_CONST_TABLE_SIZE;
req.init_cfg_ptr = accel_dev->admin->const_tbl_addr;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp)
{
struct icp_qat_fw_init_admin_req req = { };
struct icp_qat_fw_init_admin_resp resp;
unsigned int ae_mask = ADF_ONE_AE;
int ret;
req.cmd_id = ICP_QAT_FW_TIMER_GET;
ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
if (ret)
return ret;
*timestamp = resp.timestamp;
return 0 ;
}
static int adf_set_chaining(struct adf_accel_dev *accel_dev)
{
u32 ae_mask = GET_HW_DATA(accel_dev)->ae_mask;
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };
req.cmd_id = ICP_QAT_FW_DC_CHAIN_INIT;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
static int adf_get_dc_capabilities(struct adf_accel_dev *accel_dev,
u32 *capabilities)
{
struct adf_hw_device_data *hw_device = accel_dev->hw_device;
struct icp_qat_fw_init_admin_resp resp;
struct icp_qat_fw_init_admin_req req;
unsigned long ae_mask;
unsigned long ae;
int ret;
/* Target only service accelerator engines */
ae_mask = hw_device->ae_mask & ~hw_device->admin_ae_mask;
memset(&req, 0 , sizeof (req));
memset(&resp, 0 , sizeof (resp));
req.cmd_id = ICP_QAT_FW_COMP_CAPABILITY_GET;
*capabilities = 0 ;
for_each_set_bit(ae, &ae_mask, GET_MAX_ACCELENGINES(accel_dev)) {
ret = adf_send_admin(accel_dev, &req, &resp, 1 ULL << ae);
if (ret)
return ret;
*capabilities |= resp.extended_features;
}
return 0 ;
}
int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u64 *resps)
{
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };
int ret;
req.cmd_id = ICP_QAT_FW_COUNTERS_GET;
ret = adf_put_admin_msg_sync(accel_dev, ae, &req, &resp);
if (ret || resp.status)
return -EFAULT;
*reqs = resp.req_rec_count;
*resps = resp.resp_sent_count;
return 0 ;
}
int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt)
{
u32 ae_mask = accel_dev->hw_device->ae_mask;
struct icp_qat_fw_init_admin_req req = { };
struct icp_qat_fw_init_admin_resp resp = { };
req.cmd_id = ICP_QAT_FW_SYNC;
req.int_timer_ticks = cnt;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks)
{
u32 ae_mask = accel_dev->hw_device->ae_mask;
struct icp_qat_fw_init_admin_req req = { };
struct icp_qat_fw_init_admin_resp resp;
req.cmd_id = ICP_QAT_FW_HEARTBEAT_TIMER_SET;
req.init_cfg_ptr = accel_dev->heartbeat->dma.phy_addr;
req.heartbeat_ticks = ticks;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
static bool is_dcc_enabled(struct adf_accel_dev *accel_dev)
{
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0 };
int ret;
ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
ADF_SERVICES_ENABLED, services);
if (ret)
return false ;
return !strcmp(services, "dcc" );
}
static int adf_get_fw_capabilities(struct adf_accel_dev *accel_dev, u16 *caps)
{
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;
if (!ae_mask)
return 0 ;
req.cmd_id = ICP_QAT_FW_CAPABILITIES_GET;
ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
if (ret)
return ret;
*caps = resp.fw_capabilities;
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.
*
* Function sends admin init message to the FW
*
* Return: 0 on success, error code otherwise.
*/
int adf_send_admin_init(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
u32 dc_capabilities = 0 ;
int ret;
ret = adf_set_fw_constants(accel_dev);
if (ret)
return ret;
if (is_dcc_enabled(accel_dev)) {
ret = adf_set_chaining(accel_dev);
if (ret)
return ret;
}
ret = adf_get_dc_capabilities(accel_dev, &dc_capabilities);
if (ret) {
dev_err(&GET_DEV(accel_dev), "Cannot get dc capabilities\n" );
return ret;
}
accel_dev->hw_device->extended_dc_capabilities = dc_capabilities;
adf_get_fw_capabilities(accel_dev, &hw_data->fw_capabilities);
return adf_init_ae(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_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_get_cnv_stats(struct adf_accel_dev *accel_dev, u16 ae, u16 *err_cnt,
u16 *latest_err)
{
struct icp_qat_fw_init_admin_req req = { };
struct icp_qat_fw_init_admin_resp resp;
int ret;
req.cmd_id = ICP_QAT_FW_CNV_STATS_GET;
ret = adf_put_admin_msg_sync(accel_dev, ae, &req, &resp);
if (ret)
return ret;
if (resp.status)
return -EPROTONOSUPPORT;
*err_cnt = resp.error_count;
*latest_err = resp.latest_error;
return ret;
}
int adf_send_admin_tl_start(struct adf_accel_dev *accel_dev,
dma_addr_t tl_dma_addr, size_t layout_sz, u8 *rp_indexes,
struct icp_qat_fw_init_admin_slice_cnt *slice_count)
{
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;
req.cmd_id = ICP_QAT_FW_TL_START;
req.init_cfg_ptr = tl_dma_addr;
req.init_cfg_sz = layout_sz;
if (rp_indexes)
memcpy(&req.rp_indexes, rp_indexes, sizeof (req.rp_indexes));
ret = adf_send_admin(accel_dev, &req, &resp, ae_mask);
if (ret)
return ret;
memcpy(slice_count, &resp.slices, sizeof (*slice_count));
return 0 ;
}
int adf_send_admin_tl_stop(struct adf_accel_dev *accel_dev)
{
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
struct icp_qat_fw_init_admin_resp resp = { };
struct icp_qat_fw_init_admin_req req = { };
u32 ae_mask = hw_data->admin_ae_mask;
req.cmd_id = ICP_QAT_FW_TL_STOP;
return adf_send_admin(accel_dev, &req, &resp, ae_mask);
}
int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
{
struct adf_admin_comms *admin;
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
void __iomem *pmisc_addr = adf_get_pmisc_base(accel_dev);
struct admin_info admin_csrs_info;
u32 mailbox_offset, adminmsg_u, adminmsg_l;
void __iomem *mailbox;
u64 reg_val;
admin = kzalloc_node(sizeof (*accel_dev->admin), GFP_KERNEL,
dev_to_node(&GET_DEV(accel_dev)));
if (!admin)
return -ENOMEM;
admin->virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
&admin->phy_addr, GFP_KERNEL);
if (!admin->virt_addr) {
dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n" );
kfree(admin);
return -ENOMEM;
}
admin->virt_tbl_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
PAGE_SIZE,
&admin->const_tbl_addr,
GFP_KERNEL);
if (!admin->virt_tbl_addr) {
dev_err(&GET_DEV(accel_dev), "Failed to allocate const_tbl\n" );
dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
admin->virt_addr, admin->phy_addr);
kfree(admin);
return -ENOMEM;
}
memcpy(admin->virt_tbl_addr, const_tab, sizeof (const_tab));
hw_data->get_admin_info(&admin_csrs_info);
mailbox_offset = admin_csrs_info.mailbox_offset;
mailbox = pmisc_addr + mailbox_offset;
adminmsg_u = admin_csrs_info.admin_msg_ur;
adminmsg_l = admin_csrs_info.admin_msg_lr;
reg_val = (u64)admin->phy_addr;
ADF_CSR_WR(pmisc_addr, adminmsg_u, upper_32_bits(reg_val));
ADF_CSR_WR(pmisc_addr, adminmsg_l, lower_32_bits(reg_val));
mutex_init(&admin->lock);
admin->mailbox_addr = mailbox;
accel_dev->admin = admin;
return 0 ;
}
EXPORT_SYMBOL_GPL(adf_init_admin_comms);
void adf_exit_admin_comms(struct adf_accel_dev *accel_dev)
{
struct adf_admin_comms *admin = accel_dev->admin;
if (!admin)
return ;
if (admin->virt_addr)
dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
admin->virt_addr, admin->phy_addr);
if (admin->virt_tbl_addr)
dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
admin->virt_tbl_addr, admin->const_tbl_addr);
mutex_destroy(&admin->lock);
kfree(admin);
accel_dev->admin = NULL;
}
EXPORT_SYMBOL_GPL(adf_exit_admin_comms);
Messung V0.5 in Prozent C=97 H=94 G=95
¤ Dauer der Verarbeitung: 0.38 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland