mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.3 KiB
191 lines
4.3 KiB
// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) |
|
/* Copyright(c) 2022 Intel Corporation */ |
|
#include <linux/device.h> |
|
#include <linux/errno.h> |
|
#include <linux/pci.h> |
|
#include "adf_accel_devices.h" |
|
#include "adf_cfg.h" |
|
#include "adf_common_drv.h" |
|
|
|
static const char * const state_operations[] = { |
|
[DEV_DOWN] = "down", |
|
[DEV_UP] = "up", |
|
}; |
|
|
|
static ssize_t state_show(struct device *dev, struct device_attribute *attr, |
|
char *buf) |
|
{ |
|
struct adf_accel_dev *accel_dev; |
|
char *state; |
|
|
|
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); |
|
if (!accel_dev) |
|
return -EINVAL; |
|
|
|
state = adf_dev_started(accel_dev) ? "up" : "down"; |
|
return sysfs_emit(buf, "%s\n", state); |
|
} |
|
|
|
static ssize_t state_store(struct device *dev, struct device_attribute *attr, |
|
const char *buf, size_t count) |
|
{ |
|
struct adf_accel_dev *accel_dev; |
|
u32 accel_id; |
|
int ret; |
|
|
|
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); |
|
if (!accel_dev) |
|
return -EINVAL; |
|
|
|
accel_id = accel_dev->accel_id; |
|
|
|
if (adf_devmgr_in_reset(accel_dev) || adf_dev_in_use(accel_dev)) { |
|
dev_info(dev, "Device qat_dev%d is busy\n", accel_id); |
|
return -EBUSY; |
|
} |
|
|
|
ret = sysfs_match_string(state_operations, buf); |
|
if (ret < 0) |
|
return ret; |
|
|
|
switch (ret) { |
|
case DEV_DOWN: |
|
if (!adf_dev_started(accel_dev)) { |
|
dev_info(dev, "Device qat_dev%d already down\n", |
|
accel_id); |
|
return -EINVAL; |
|
} |
|
|
|
dev_info(dev, "Stopping device qat_dev%d\n", accel_id); |
|
|
|
ret = adf_dev_shutdown_cache_cfg(accel_dev); |
|
if (ret < 0) |
|
return -EINVAL; |
|
|
|
break; |
|
case DEV_UP: |
|
if (adf_dev_started(accel_dev)) { |
|
dev_info(dev, "Device qat_dev%d already up\n", |
|
accel_id); |
|
return -EINVAL; |
|
} |
|
|
|
dev_info(dev, "Starting device qat_dev%d\n", accel_id); |
|
|
|
ret = GET_HW_DATA(accel_dev)->dev_config(accel_dev); |
|
if (!ret) |
|
ret = adf_dev_init(accel_dev); |
|
if (!ret) |
|
ret = adf_dev_start(accel_dev); |
|
|
|
if (ret < 0) { |
|
dev_err(dev, "Failed to start device qat_dev%d\n", |
|
accel_id); |
|
adf_dev_shutdown_cache_cfg(accel_dev); |
|
return ret; |
|
} |
|
break; |
|
default: |
|
return -EINVAL; |
|
} |
|
|
|
return count; |
|
} |
|
|
|
static const char * const services_operations[] = { |
|
ADF_CFG_CY, |
|
ADF_CFG_DC, |
|
}; |
|
|
|
static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr, |
|
char *buf) |
|
{ |
|
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; |
|
struct adf_accel_dev *accel_dev; |
|
int ret; |
|
|
|
accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); |
|
if (!accel_dev) |
|
return -EINVAL; |
|
|
|
ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, |
|
ADF_SERVICES_ENABLED, services); |
|
if (ret) |
|
return ret; |
|
|
|
return sysfs_emit(buf, "%s\n", services); |
|
} |
|
|
|
static int adf_sysfs_update_dev_config(struct adf_accel_dev *accel_dev, |
|
const char *services) |
|
{ |
|
return adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, |
|
ADF_SERVICES_ENABLED, services, |
|
ADF_STR); |
|
} |
|
|
|
static ssize_t cfg_services_store(struct device *dev, struct device_attribute *attr, |
|
const char *buf, size_t count) |
|
{ |
|
struct adf_hw_device_data *hw_data; |
|
struct adf_accel_dev *accel_dev; |
|
int ret; |
|
|
|
ret = sysfs_match_string(services_operations, buf); |
|
if (ret < 0) |
|
return 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 to reconfigure the service.\n", |
|
accel_dev->accel_id); |
|
return -EINVAL; |
|
} |
|
|
|
ret = adf_sysfs_update_dev_config(accel_dev, services_operations[ret]); |
|
if (ret < 0) |
|
return ret; |
|
|
|
hw_data = GET_HW_DATA(accel_dev); |
|
|
|
/* Update capabilities mask after change in configuration. |
|
* A call to this function is required as capabilities are, at the |
|
* moment, tied to configuration |
|
*/ |
|
hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev); |
|
if (!hw_data->accel_capabilities_mask) |
|
return -EINVAL; |
|
|
|
return count; |
|
} |
|
|
|
static DEVICE_ATTR_RW(state); |
|
static DEVICE_ATTR_RW(cfg_services); |
|
|
|
static struct attribute *qat_attrs[] = { |
|
&dev_attr_state.attr, |
|
&dev_attr_cfg_services.attr, |
|
NULL, |
|
}; |
|
|
|
static struct attribute_group qat_group = { |
|
.attrs = qat_attrs, |
|
.name = "qat", |
|
}; |
|
|
|
int adf_sysfs_init(struct adf_accel_dev *accel_dev) |
|
{ |
|
int ret; |
|
|
|
ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_group); |
|
if (ret) { |
|
dev_err(&GET_DEV(accel_dev), |
|
"Failed to create qat attribute group: %d\n", ret); |
|
} |
|
|
|
return ret; |
|
} |
|
EXPORT_SYMBOL_GPL(adf_sysfs_init);
|
|
|