Merge branch 'char-misc-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc into fpga-dfl-for-5.4

This commit is contained in:
Moritz Fischer 2019-09-03 19:35:07 -07:00
commit af9ca4b0bd
1971 changed files with 22326 additions and 14084 deletions

View file

@ -40,6 +40,7 @@ config ALTERA_PR_IP_CORE_PLAT
config FPGA_MGR_ALTERA_PS_SPI
tristate "Altera FPGA Passive Serial over SPI"
depends on SPI
select BITREVERSE
help
FPGA manager driver support for Altera Arria/Cyclone/Stratix
using the passive serial interface over SPI.

View file

@ -210,7 +210,7 @@ static int altera_ps_write_complete(struct fpga_manager *mgr,
return -EIO;
}
if (!IS_ERR(conf->confd)) {
if (conf->confd) {
if (!gpiod_get_raw_value_cansleep(conf->confd)) {
dev_err(&mgr->dev, "CONF_DONE is inactive!\n");
return -EIO;
@ -289,10 +289,13 @@ static int altera_ps_probe(struct spi_device *spi)
return PTR_ERR(conf->status);
}
conf->confd = devm_gpiod_get(&spi->dev, "confd", GPIOD_IN);
conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN);
if (IS_ERR(conf->confd)) {
dev_warn(&spi->dev, "Not using confd gpio: %ld\n",
PTR_ERR(conf->confd));
dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
PTR_ERR(conf->confd));
return PTR_ERR(conf->confd);
} else if (!conf->confd) {
dev_warn(&spi->dev, "Not using confd gpio");
}
/* Register manager with unique name */

View file

@ -141,10 +141,148 @@ id_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR_RO(id);
static const struct attribute *port_hdr_attrs[] = {
static ssize_t
ltr_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
v = readq(base + PORT_HDR_CTRL);
mutex_unlock(&pdata->lock);
return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v));
}
static ssize_t
ltr_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
bool ltr;
u64 v;
if (kstrtobool(buf, &ltr))
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
v = readq(base + PORT_HDR_CTRL);
v &= ~PORT_CTRL_LATENCY;
v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0);
writeq(v, base + PORT_HDR_CTRL);
mutex_unlock(&pdata->lock);
return count;
}
static DEVICE_ATTR_RW(ltr);
static ssize_t
ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
v = readq(base + PORT_HDR_STS);
mutex_unlock(&pdata->lock);
return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v));
}
static ssize_t
ap1_event_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
bool clear;
if (kstrtobool(buf, &clear) || !clear)
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS);
mutex_unlock(&pdata->lock);
return count;
}
static DEVICE_ATTR_RW(ap1_event);
static ssize_t
ap2_event_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
v = readq(base + PORT_HDR_STS);
mutex_unlock(&pdata->lock);
return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v));
}
static ssize_t
ap2_event_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
bool clear;
if (kstrtobool(buf, &clear) || !clear)
return -EINVAL;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS);
mutex_unlock(&pdata->lock);
return count;
}
static DEVICE_ATTR_RW(ap2_event);
static ssize_t
power_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(dev);
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER);
mutex_lock(&pdata->lock);
v = readq(base + PORT_HDR_STS);
mutex_unlock(&pdata->lock);
return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v));
}
static DEVICE_ATTR_RO(power_state);
static struct attribute *port_hdr_attrs[] = {
&dev_attr_id.attr,
&dev_attr_ltr.attr,
&dev_attr_ap1_event.attr,
&dev_attr_ap2_event.attr,
&dev_attr_power_state.attr,
NULL,
};
ATTRIBUTE_GROUPS(port_hdr);
static int port_hdr_init(struct platform_device *pdev,
struct dfl_feature *feature)
@ -153,7 +291,7 @@ static int port_hdr_init(struct platform_device *pdev,
port_reset(pdev);
return sysfs_create_files(&pdev->dev.kobj, port_hdr_attrs);
return device_add_groups(&pdev->dev, port_hdr_groups);
}
static void port_hdr_uinit(struct platform_device *pdev,
@ -161,7 +299,7 @@ static void port_hdr_uinit(struct platform_device *pdev,
{
dev_dbg(&pdev->dev, "PORT HDR UInit.\n");
sysfs_remove_files(&pdev->dev.kobj, port_hdr_attrs);
device_remove_groups(&pdev->dev, port_hdr_groups);
}
static long
@ -185,6 +323,11 @@ port_hdr_ioctl(struct platform_device *pdev, struct dfl_feature *feature,
return ret;
}
static const struct dfl_feature_id port_hdr_id_table[] = {
{.id = PORT_FEATURE_ID_HEADER,},
{0,}
};
static const struct dfl_feature_ops port_hdr_ops = {
.init = port_hdr_init,
.uinit = port_hdr_uinit,
@ -214,10 +357,11 @@ afu_id_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR_RO(afu_id);
static const struct attribute *port_afu_attrs[] = {
static struct attribute *port_afu_attrs[] = {
&dev_attr_afu_id.attr,
NULL
};
ATTRIBUTE_GROUPS(port_afu);
static int port_afu_init(struct platform_device *pdev,
struct dfl_feature *feature)
@ -234,7 +378,7 @@ static int port_afu_init(struct platform_device *pdev,
if (ret)
return ret;
return sysfs_create_files(&pdev->dev.kobj, port_afu_attrs);
return device_add_groups(&pdev->dev, port_afu_groups);
}
static void port_afu_uinit(struct platform_device *pdev,
@ -242,9 +386,14 @@ static void port_afu_uinit(struct platform_device *pdev,
{
dev_dbg(&pdev->dev, "PORT AFU UInit.\n");
sysfs_remove_files(&pdev->dev.kobj, port_afu_attrs);
device_remove_groups(&pdev->dev, port_afu_groups);
}
static const struct dfl_feature_id port_afu_id_table[] = {
{.id = PORT_FEATURE_ID_AFU,},
{0,}
};
static const struct dfl_feature_ops port_afu_ops = {
.init = port_afu_init,
.uinit = port_afu_uinit,
@ -252,11 +401,11 @@ static const struct dfl_feature_ops port_afu_ops = {
static struct dfl_feature_driver port_feature_drvs[] = {
{
.id = PORT_FEATURE_ID_HEADER,
.id_table = port_hdr_id_table,
.ops = &port_hdr_ops,
},
{
.id = PORT_FEATURE_ID_AFU,
.id_table = port_afu_id_table,
.ops = &port_afu_ops,
},
{

View file

@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/fpga-dfl.h>
#include "dfl.h"
@ -72,12 +73,61 @@ static ssize_t bitstream_metadata_show(struct device *dev,
}
static DEVICE_ATTR_RO(bitstream_metadata);
static const struct attribute *fme_hdr_attrs[] = {
static ssize_t cache_size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_CACHE_SIZE, v));
}
static DEVICE_ATTR_RO(cache_size);
static ssize_t fabric_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_FABRIC_VERID, v));
}
static DEVICE_ATTR_RO(fabric_version);
static ssize_t socket_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_CAP);
return sprintf(buf, "%u\n",
(unsigned int)FIELD_GET(FME_CAP_SOCKET_ID, v));
}
static DEVICE_ATTR_RO(socket_id);
static struct attribute *fme_hdr_attrs[] = {
&dev_attr_ports_num.attr,
&dev_attr_bitstream_id.attr,
&dev_attr_bitstream_metadata.attr,
&dev_attr_cache_size.attr,
&dev_attr_fabric_version.attr,
&dev_attr_socket_id.attr,
NULL,
};
ATTRIBUTE_GROUPS(fme_hdr);
static int fme_hdr_init(struct platform_device *pdev,
struct dfl_feature *feature)
@ -89,7 +139,7 @@ static int fme_hdr_init(struct platform_device *pdev,
dev_dbg(&pdev->dev, "FME cap %llx.\n",
(unsigned long long)readq(base + FME_HDR_CAP));
ret = sysfs_create_files(&pdev->dev.kobj, fme_hdr_attrs);
ret = device_add_groups(&pdev->dev, fme_hdr_groups);
if (ret)
return ret;
@ -100,22 +150,68 @@ static void fme_hdr_uinit(struct platform_device *pdev,
struct dfl_feature *feature)
{
dev_dbg(&pdev->dev, "FME HDR UInit.\n");
sysfs_remove_files(&pdev->dev.kobj, fme_hdr_attrs);
device_remove_groups(&pdev->dev, fme_hdr_groups);
}
static long fme_hdr_ioctl_release_port(struct dfl_feature_platform_data *pdata,
unsigned long arg)
{
struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
int port_id;
if (get_user(port_id, (int __user *)arg))
return -EFAULT;
return dfl_fpga_cdev_release_port(cdev, port_id);
}
static long fme_hdr_ioctl_assign_port(struct dfl_feature_platform_data *pdata,
unsigned long arg)
{
struct dfl_fpga_cdev *cdev = pdata->dfl_cdev;
int port_id;
if (get_user(port_id, (int __user *)arg))
return -EFAULT;
return dfl_fpga_cdev_assign_port(cdev, port_id);
}
static long fme_hdr_ioctl(struct platform_device *pdev,
struct dfl_feature *feature,
unsigned int cmd, unsigned long arg)
{
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
switch (cmd) {
case DFL_FPGA_FME_PORT_RELEASE:
return fme_hdr_ioctl_release_port(pdata, arg);
case DFL_FPGA_FME_PORT_ASSIGN:
return fme_hdr_ioctl_assign_port(pdata, arg);
}
return -ENODEV;
}
static const struct dfl_feature_id fme_hdr_id_table[] = {
{.id = FME_FEATURE_ID_HEADER,},
{0,}
};
static const struct dfl_feature_ops fme_hdr_ops = {
.init = fme_hdr_init,
.uinit = fme_hdr_uinit,
.ioctl = fme_hdr_ioctl,
};
static struct dfl_feature_driver fme_feature_drvs[] = {
{
.id = FME_FEATURE_ID_HEADER,
.id_table = fme_hdr_id_table,
.ops = &fme_hdr_ops,
},
{
.id = FME_FEATURE_ID_PR_MGMT,
.ops = &pr_mgmt_ops,
.id_table = fme_pr_mgmt_id_table,
.ops = &fme_pr_mgmt_ops,
},
{
.ops = NULL,

View file

@ -470,7 +470,12 @@ static long fme_pr_ioctl(struct platform_device *pdev,
return ret;
}
const struct dfl_feature_ops pr_mgmt_ops = {
const struct dfl_feature_id fme_pr_mgmt_id_table[] = {
{.id = FME_FEATURE_ID_PR_MGMT,},
{0}
};
const struct dfl_feature_ops fme_pr_mgmt_ops = {
.init = pr_mgmt_init,
.uinit = pr_mgmt_uinit,
.ioctl = fme_pr_ioctl,

View file

@ -33,6 +33,7 @@ struct dfl_fme {
struct dfl_feature_platform_data *pdata;
};
extern const struct dfl_feature_ops pr_mgmt_ops;
extern const struct dfl_feature_ops fme_pr_mgmt_ops;
extern const struct dfl_feature_id fme_pr_mgmt_id_table[];
#endif /* __DFL_FME_H */

View file

@ -223,8 +223,43 @@ disable_error_report_exit:
return ret;
}
static int cci_pci_sriov_configure(struct pci_dev *pcidev, int num_vfs)
{
struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
struct dfl_fpga_cdev *cdev = drvdata->cdev;
int ret = 0;
if (!num_vfs) {
/*
* disable SRIOV and then put released ports back to default
* PF access mode.
*/
pci_disable_sriov(pcidev);
dfl_fpga_cdev_config_ports_pf(cdev);
} else {
/*
* before enable SRIOV, put released ports into VF access mode
* first of all.
*/
ret = dfl_fpga_cdev_config_ports_vf(cdev, num_vfs);
if (ret)
return ret;
ret = pci_enable_sriov(pcidev, num_vfs);
if (ret)
dfl_fpga_cdev_config_ports_pf(cdev);
}
return ret;
}
static void cci_pci_remove(struct pci_dev *pcidev)
{
if (dev_is_pf(&pcidev->dev))
cci_pci_sriov_configure(pcidev, 0);
cci_remove_feature_devs(pcidev);
pci_disable_pcie_error_reporting(pcidev);
}
@ -234,6 +269,7 @@ static struct pci_driver cci_pci_driver = {
.id_table = cci_pcie_id_tbl,
.probe = cci_pci_probe,
.remove = cci_pci_remove,
.sriov_configure = cci_pci_sriov_configure,
};
module_pci_driver(cci_pci_driver);

View file

@ -231,16 +231,20 @@ EXPORT_SYMBOL_GPL(dfl_fpga_port_ops_del);
*/
int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id)
{
struct dfl_fpga_port_ops *port_ops = dfl_fpga_port_ops_get(pdev);
int port_id;
struct dfl_feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dfl_fpga_port_ops *port_ops;
if (pdata->id != FEATURE_DEV_ID_UNUSED)
return pdata->id == *(int *)pport_id;
port_ops = dfl_fpga_port_ops_get(pdev);
if (!port_ops || !port_ops->get_id)
return 0;
port_id = port_ops->get_id(pdev);
pdata->id = port_ops->get_id(pdev);
dfl_fpga_port_ops_put(port_ops);
return port_id == *(int *)pport_id;
return pdata->id == *(int *)pport_id;
}
EXPORT_SYMBOL_GPL(dfl_fpga_check_port_id);
@ -255,7 +259,8 @@ void dfl_fpga_dev_feature_uinit(struct platform_device *pdev)
dfl_fpga_dev_for_each_feature(pdata, feature)
if (feature->ops) {
feature->ops->uinit(pdev, feature);
if (feature->ops->uinit)
feature->ops->uinit(pdev, feature);
feature->ops = NULL;
}
}
@ -277,6 +282,21 @@ static int dfl_feature_instance_init(struct platform_device *pdev,
return ret;
}
static bool dfl_feature_drv_match(struct dfl_feature *feature,
struct dfl_feature_driver *driver)
{
const struct dfl_feature_id *ids = driver->id_table;
if (ids) {
while (ids->id) {
if (ids->id == feature->id)
return true;
ids++;
}
}
return false;
}
/**
* dfl_fpga_dev_feature_init - init for sub features of dfl feature device
* @pdev: feature device.
@ -297,8 +317,7 @@ int dfl_fpga_dev_feature_init(struct platform_device *pdev,
while (drv->ops) {
dfl_fpga_dev_for_each_feature(pdata, feature) {
/* match feature and drv using id */
if (feature->id == drv->id) {
if (dfl_feature_drv_match(feature, drv)) {
ret = dfl_feature_instance_init(pdev, pdata,
feature, drv);
if (ret)
@ -474,6 +493,7 @@ static int build_info_commit_dev(struct build_feature_devs_info *binfo)
pdata->dev = fdev;
pdata->num = binfo->feature_num;
pdata->dfl_cdev = binfo->cdev;
pdata->id = FEATURE_DEV_ID_UNUSED;
mutex_init(&pdata->lock);
lockdep_set_class_and_name(&pdata->lock, &dfl_pdata_keys[type],
dfl_pdata_key_strings[type]);
@ -973,25 +993,27 @@ void dfl_fpga_feature_devs_remove(struct dfl_fpga_cdev *cdev)
{
struct dfl_feature_platform_data *pdata, *ptmp;
remove_feature_devs(cdev);
mutex_lock(&cdev->lock);
if (cdev->fme_dev) {
/* the fme should be unregistered. */
WARN_ON(device_is_registered(cdev->fme_dev));
if (cdev->fme_dev)
put_device(cdev->fme_dev);
}
list_for_each_entry_safe(pdata, ptmp, &cdev->port_dev_list, node) {
struct platform_device *port_dev = pdata->dev;
/* the port should be unregistered. */
WARN_ON(device_is_registered(&port_dev->dev));
/* remove released ports */
if (!device_is_registered(&port_dev->dev)) {
dfl_id_free(feature_dev_id_type(port_dev),
port_dev->id);
platform_device_put(port_dev);
}
list_del(&pdata->node);
put_device(&port_dev->dev);
}
mutex_unlock(&cdev->lock);
remove_feature_devs(cdev);
fpga_region_unregister(cdev->region);
devm_kfree(cdev->parent, cdev);
}
@ -1042,6 +1064,170 @@ static int __init dfl_fpga_init(void)
return ret;
}
/**
* dfl_fpga_cdev_release_port - release a port platform device
*
* @cdev: parent container device.
* @port_id: id of the port platform device.
*
* This function allows user to release a port platform device. This is a
* mandatory step before turn a port from PF into VF for SRIOV support.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id)
{
struct platform_device *port_pdev;
int ret = -ENODEV;
mutex_lock(&cdev->lock);
port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
dfl_fpga_check_port_id);
if (!port_pdev)
goto unlock_exit;
if (!device_is_registered(&port_pdev->dev)) {
ret = -EBUSY;
goto put_dev_exit;
}
ret = dfl_feature_dev_use_begin(dev_get_platdata(&port_pdev->dev));
if (ret)
goto put_dev_exit;
platform_device_del(port_pdev);
cdev->released_port_num++;
put_dev_exit:
put_device(&port_pdev->dev);
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_release_port);
/**
* dfl_fpga_cdev_assign_port - assign a port platform device back
*
* @cdev: parent container device.
* @port_id: id of the port platform device.
*
* This function allows user to assign a port platform device back. This is
* a mandatory step after disable SRIOV support.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id)
{
struct platform_device *port_pdev;
int ret = -ENODEV;
mutex_lock(&cdev->lock);
port_pdev = __dfl_fpga_cdev_find_port(cdev, &port_id,
dfl_fpga_check_port_id);
if (!port_pdev)
goto unlock_exit;
if (device_is_registered(&port_pdev->dev)) {
ret = -EBUSY;
goto put_dev_exit;
}
ret = platform_device_add(port_pdev);
if (ret)
goto put_dev_exit;
dfl_feature_dev_use_end(dev_get_platdata(&port_pdev->dev));
cdev->released_port_num--;
put_dev_exit:
put_device(&port_pdev->dev);
unlock_exit:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_assign_port);
static void config_port_access_mode(struct device *fme_dev, int port_id,
bool is_vf)
{
void __iomem *base;
u64 v;
base = dfl_get_feature_ioaddr_by_id(fme_dev, FME_FEATURE_ID_HEADER);
v = readq(base + FME_HDR_PORT_OFST(port_id));
v &= ~FME_PORT_OFST_ACC_CTRL;
v |= FIELD_PREP(FME_PORT_OFST_ACC_CTRL,
is_vf ? FME_PORT_OFST_ACC_VF : FME_PORT_OFST_ACC_PF);
writeq(v, base + FME_HDR_PORT_OFST(port_id));
}
#define config_port_vf_mode(dev, id) config_port_access_mode(dev, id, true)
#define config_port_pf_mode(dev, id) config_port_access_mode(dev, id, false)
/**
* dfl_fpga_cdev_config_ports_pf - configure ports to PF access mode
*
* @cdev: parent container device.
*
* This function is needed in sriov configuration routine. It could be used to
* configure the all released ports from VF access mode to PF.
*/
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev)
{
struct dfl_feature_platform_data *pdata;
mutex_lock(&cdev->lock);
list_for_each_entry(pdata, &cdev->port_dev_list, node) {
if (device_is_registered(&pdata->dev->dev))
continue;
config_port_pf_mode(cdev->fme_dev, pdata->id);
}
mutex_unlock(&cdev->lock);
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_pf);
/**
* dfl_fpga_cdev_config_ports_vf - configure ports to VF access mode
*
* @cdev: parent container device.
* @num_vfs: VF device number.
*
* This function is needed in sriov configuration routine. It could be used to
* configure the released ports from PF access mode to VF.
*
* Return: 0 on success, negative error code otherwise.
*/
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vfs)
{
struct dfl_feature_platform_data *pdata;
int ret = 0;
mutex_lock(&cdev->lock);
/*
* can't turn multiple ports into 1 VF device, only 1 port for 1 VF
* device, so if released port number doesn't match VF device number,
* then reject the request with -EINVAL error code.
*/
if (cdev->released_port_num != num_vfs) {
ret = -EINVAL;
goto done;
}
list_for_each_entry(pdata, &cdev->port_dev_list, node) {
if (device_is_registered(&pdata->dev->dev))
continue;
config_port_vf_mode(cdev->fme_dev, pdata->id);
}
done:
mutex_unlock(&cdev->lock);
return ret;
}
EXPORT_SYMBOL_GPL(dfl_fpga_cdev_config_ports_vf);
static void __exit dfl_fpga_exit(void)
{
dfl_chardev_uinit();

View file

@ -30,8 +30,8 @@
/* plus one for fme device */
#define MAX_DFL_FEATURE_DEV_NUM (MAX_DFL_FPGA_PORT_NUM + 1)
/* Reserved 0x0 for Header Group Register and 0xff for AFU */
#define FEATURE_ID_FIU_HEADER 0x0
/* Reserved 0xfe for Header Group Register and 0xff for AFU */
#define FEATURE_ID_FIU_HEADER 0xfe
#define FEATURE_ID_AFU 0xff
#define FME_FEATURE_ID_HEADER FEATURE_ID_FIU_HEADER
@ -119,6 +119,7 @@
#define PORT_HDR_NEXT_AFU NEXT_AFU
#define PORT_HDR_CAP 0x30
#define PORT_HDR_CTRL 0x38
#define PORT_HDR_STS 0x40
/* Port Capability Register Bitfield */
#define PORT_CAP_PORT_NUM GENMASK_ULL(1, 0) /* ID of this port */
@ -130,6 +131,16 @@
/* Latency tolerance reporting. '1' >= 40us, '0' < 40us.*/
#define PORT_CTRL_LATENCY BIT_ULL(2)
#define PORT_CTRL_SFTRST_ACK BIT_ULL(4) /* HW ack for reset */
/* Port Status Register Bitfield */
#define PORT_STS_AP2_EVT BIT_ULL(13) /* AP2 event detected */
#define PORT_STS_AP1_EVT BIT_ULL(12) /* AP1 event detected */
#define PORT_STS_PWR_STATE GENMASK_ULL(11, 8) /* AFU power states */
#define PORT_STS_PWR_STATE_NORM 0
#define PORT_STS_PWR_STATE_AP1 1 /* 50% throttling */
#define PORT_STS_PWR_STATE_AP2 2 /* 90% throttling */
#define PORT_STS_PWR_STATE_AP6 6 /* 100% throttling */
/**
* struct dfl_fpga_port_ops - port ops
*
@ -154,13 +165,22 @@ void dfl_fpga_port_ops_put(struct dfl_fpga_port_ops *ops);
int dfl_fpga_check_port_id(struct platform_device *pdev, void *pport_id);
/**
* struct dfl_feature_driver - sub feature's driver
* struct dfl_feature_id - dfl private feature id
*
* @id: sub feature id.
* @ops: ops of this sub feature.
* @id: unique dfl private feature id.
*/
struct dfl_feature_id {
u64 id;
};
/**
* struct dfl_feature_driver - dfl private feature driver
*
* @id_table: id_table for dfl private features supported by this driver.
* @ops: ops of this dfl private feature driver.
*/
struct dfl_feature_driver {
u64 id;
const struct dfl_feature_id *id_table;
const struct dfl_feature_ops *ops;
};
@ -183,6 +203,8 @@ struct dfl_feature {
#define DEV_STATUS_IN_USE 0
#define FEATURE_DEV_ID_UNUSED (-1)
/**
* struct dfl_feature_platform_data - platform data for feature devices
*
@ -191,6 +213,7 @@ struct dfl_feature {
* @cdev: cdev of feature dev.
* @dev: ptr to platform device linked with this platform data.
* @dfl_cdev: ptr to container device.
* @id: id used for this feature device.
* @disable_count: count for port disable.
* @num: number for sub features.
* @dev_status: dev status (e.g. DEV_STATUS_IN_USE).
@ -203,6 +226,7 @@ struct dfl_feature_platform_data {
struct cdev cdev;
struct platform_device *dev;
struct dfl_fpga_cdev *dfl_cdev;
int id;
unsigned int disable_count;
unsigned long dev_status;
void *private;
@ -373,6 +397,7 @@ void dfl_fpga_enum_info_free(struct dfl_fpga_enum_info *info);
* @fme_dev: FME feature device under this container device.
* @lock: mutex lock to protect the port device list.
* @port_dev_list: list of all port feature devices under this container device.
* @released_port_num: released port number under this container device.
*/
struct dfl_fpga_cdev {
struct device *parent;
@ -380,6 +405,7 @@ struct dfl_fpga_cdev {
struct device *fme_dev;
struct mutex lock;
struct list_head port_dev_list;
int released_port_num;
};
struct dfl_fpga_cdev *
@ -407,4 +433,9 @@ dfl_fpga_cdev_find_port(struct dfl_fpga_cdev *cdev, void *data,
return pdev;
}
int dfl_fpga_cdev_release_port(struct dfl_fpga_cdev *cdev, int port_id);
int dfl_fpga_cdev_assign_port(struct dfl_fpga_cdev *cdev, int port_id);
void dfl_fpga_cdev_config_ports_pf(struct dfl_fpga_cdev *cdev);
int dfl_fpga_cdev_config_ports_vf(struct dfl_fpga_cdev *cdev, int num_vf);
#endif /* __FPGA_DFL_H */