linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alan Tull <atull@kernel.org>
To: Moritz Fischer <moritz.fischer@ettus.com>,
	Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
Cc: Alan Tull <atull@kernel.org>,
	linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org
Subject: [RFC 7/8] fpga-region: add sysfs interface
Date: Wed, 15 Feb 2017 10:14:20 -0600	[thread overview]
Message-ID: <1487175261-7051-8-git-send-email-atull@kernel.org> (raw)
In-Reply-To: <1487175261-7051-1-git-send-email-atull@kernel.org>

Add a sysfs interface to control programming FPGA.

Each fpga-region will get the following files which set values
in the fpga_image_info struct for that region.  More files will
need to be added as fpga_image_info expands.

firmware_name
* writing a name of a FPGA image file to firmware_name causes the
  FPGA region to write the FPGA

partial_config
* 0 : full reconfiguration
* 1 : partial reconfiguration

unfreeze_timeout
* Timeout for waiting for a freeze bridge to enable traffic

freeze_timeout
* Timeout for waiting for a freeze bridge to disable traffic

Signed-off-by: Alan Tull <atull@kernel.org>
---
 drivers/fpga/Kconfig       |   8 ++
 drivers/fpga/fpga-region.c | 241 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 249 insertions(+)

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index be9c23d..6455e02 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -21,6 +21,14 @@ config FPGA_REGION
 	  and the FPGA Bridges associated with either a reconfigurable
 	  region of an FPGA or a whole FPGA.
 
+config FPGA_REGION_SYSFS
+       bool "FPGA Region Sysfs"
+	depends on FPGA_REGION
+	help
+	  FPGA Region sysfs interface.  This creates sysfs file for each
+	  FPGA Region under /sys/class/fpga_region/ to show status and
+	  control programming FPGA regions.
+
 config OF_FPGA_REGION
 	tristate "FPGA Region Device Tree Overlay Support"
 	depends on FPGA_REGION
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c
index 5690237..a63bc6c 100644
--- a/drivers/fpga/fpga-region.c
+++ b/drivers/fpga/fpga-region.c
@@ -105,6 +105,243 @@ EXPORT_SYMBOL_GPL(fpga_region_ovl_image_info);
 
 #endif /* CONFIG_OF_FPGA_REGION */
 
+#if IS_ENABLED(CONFIG_FPGA_REGION_SYSFS)
+
+struct fpga_image_info *image_info_from_region(struct fpga_region *region)
+{
+	struct fpga_image_info *image_info;
+
+	/* If region has an overlay, display image_info from overlay. */
+	image_info = fpga_region_ovl_image_info(region);
+	if (!image_info)
+		image_info = region->image_info;
+
+	return image_info;
+}
+
+/*
+ * Controlling a region both by sysfs and by device tree overlays is
+ * not supported.
+ */
+static ssize_t firmware_name_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	struct fpga_image_info *image_info;
+
+	image_info = image_info_from_region(region);
+
+	if (image_info && image_info->firmware_name)
+		return sprintf(buf, "%s\n", image_info->firmware_name);
+
+	return 0;
+}
+
+static ssize_t firmware_name_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	char *firmware_name;
+	size_t len;
+	int ret;
+
+	/*
+	 * Controlling a region both by sysfs and by device tree overlays is
+	 * not supported.
+	 */
+	if (fpga_region_ovl_image_info(region))
+		return -EINVAL;
+
+	if (!region->image_info) {
+		region->image_info = fpga_region_alloc_image_info(region);
+		if (!region->image_info)
+			return -ENOMEM;
+	}
+
+	firmware_name = devm_kzalloc(dev, count, GFP_KERNEL);
+	if (!firmware_name)
+		return -ENOMEM;
+	pr_err("count = %d\n", count);
+	/* lose terminating \n */
+	strcpy(firmware_name, buf);
+	len = strlen(firmware_name);
+	if (firmware_name[len - 1] == '\n')
+		firmware_name[len - 1] = 0;
+	if (firmware_name[0] == 0) {
+		devm_kfree(dev, firmware_name);
+		firmware_name = NULL;
+	}
+
+	/* Release previous firmware name (if any). Save current one. */
+	if (region->image_info->firmware_name)
+		devm_kfree(dev, region->image_info->firmware_name);
+	region->image_info->firmware_name = firmware_name;
+
+	if (firmware_name) {
+		ret = fpga_region_program_fpga(region, region->image_info);
+		if (ret)
+			dev_err(dev,
+				"FPGA programming failed with value %d\n", ret);
+	} else {
+		/*
+		 * Writing null string to firmware_name will disable and put
+		 * the bridges (if there were any bridges in the bridge list).
+		 */
+		fpga_bridges_disable(&region->bridge_list);
+		if (region->get_bridges)
+			fpga_bridges_put(&region->bridge_list);
+		fpga_region_free_image_info(region, region->image_info);
+		region->image_info = NULL;
+	}
+
+	return count;
+}
+
+static ssize_t partial_config_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	struct fpga_image_info *image_info;
+	int partial;
+
+	image_info = image_info_from_region(region);
+	if (!image_info)
+		return 0;
+
+	partial = !!(image_info->flags & FPGA_MGR_PARTIAL_RECONFIG);
+
+	return sprintf(buf, "%d\n", partial);
+}
+
+static ssize_t partial_config_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	unsigned long val;
+	int ret;
+
+	if (fpga_region_ovl_image_info(region))
+		return -EINVAL;
+
+	if (!region->image_info) {
+		region->image_info = fpga_region_alloc_image_info(region);
+		if (!region->image_info)
+			return -ENOMEM;
+	}
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	if (val == 1)
+		region->image_info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
+	else if (val == 0)
+		region->image_info->flags &= ~FPGA_MGR_PARTIAL_RECONFIG;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t unfreeze_timeout_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	struct fpga_image_info *image_info;
+
+	image_info = image_info_from_region(region);
+	if (!image_info)
+		return 0;
+
+	return sprintf(buf, "%d\n", image_info->enable_timeout_us);
+}
+
+static ssize_t unfreeze_timeout_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf,
+				      size_t count)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	unsigned long val;
+	int ret;
+
+	if (fpga_region_ovl_image_info(region))
+		return -EINVAL;
+
+	if (!region->image_info) {
+		region->image_info = fpga_region_alloc_image_info(region);
+		if (!region->image_info)
+			return -ENOMEM;
+	}
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	region->image_info->enable_timeout_us = val;
+
+	return count;
+}
+
+static ssize_t freeze_timeout_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	struct fpga_image_info *image_info;
+
+	image_info = image_info_from_region(region);
+	if (!image_info)
+		return 0;
+
+	return sprintf(buf, "%d\n", image_info->disable_timeout_us);
+}
+
+static ssize_t freeze_timeout_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf,
+				    size_t count)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+	unsigned long val;
+	int ret;
+
+	if (fpga_region_ovl_image_info(region))
+		return -EINVAL;
+
+	if (!region->image_info) {
+		region->image_info = fpga_region_alloc_image_info(region);
+		if (!region->image_info)
+			return -ENOMEM;
+	}
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret)
+		return ret;
+
+	region->image_info->disable_timeout_us = val;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(firmware_name);
+static DEVICE_ATTR_RW(partial_config);
+static DEVICE_ATTR_RW(unfreeze_timeout);
+static DEVICE_ATTR_RW(freeze_timeout);
+
+static struct attribute *fpga_region_attrs[] = {
+	&dev_attr_firmware_name.attr,
+	&dev_attr_partial_config.attr,
+	&dev_attr_unfreeze_timeout.attr,
+	&dev_attr_freeze_timeout.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(fpga_region);
+
+#endif /* CONFIG_FPGA_REGION_SYSFS */
+
 /**
  * fpga_region_get - get an exclusive reference to a fpga region
  * @region: FPGA Region struct
@@ -288,6 +525,10 @@ static int __init fpga_region_init(void)
 	if (IS_ERR(fpga_region_class))
 		return PTR_ERR(fpga_region_class);
 
+#if IS_ENABLED(CONFIG_FPGA_REGION_SYSFS)
+	fpga_region_class->dev_groups = fpga_region_groups;
+#endif /* CONFIG_FPGA_REGION_SYSFS */
+
 	fpga_region_class->dev_release = fpga_region_dev_release;
 
 	return 0;
-- 
2.7.4

  parent reply	other threads:[~2017-02-15 16:14 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-15 16:14 FPGA Region enhancements and fixes Alan Tull
2017-02-15 16:14 ` [RFC 1/8] fpga-mgr: add a single function for fpga loading methods Alan Tull
2017-02-16  0:36   ` matthew.gerlach
2017-02-15 16:14 ` [RFC 2/8] fpga-region: support more than one overlay per FPGA region Alan Tull
2017-02-16 16:50   ` matthew.gerlach
2017-02-16 17:35     ` Alan Tull
2017-02-15 16:14 ` [RFC 3/8] fpga-bridge: add non-dt support Alan Tull
2017-02-15 16:14 ` [RFC 4/8] doc: fpga-mgr: separate getting/locking FPGA manager Alan Tull
2017-02-17 17:14   ` Li, Yi
2017-02-17 21:55     ` Alan Tull
2017-02-17 17:52   ` Moritz Fischer
2017-02-17 22:02     ` Alan Tull
2017-02-15 16:14 ` [RFC 5/8] " Alan Tull
2017-02-15 16:14 ` [RFC 6/8] fpga-region: separate out common code to allow non-dt support Alan Tull
2017-02-15 16:14 ` Alan Tull [this message]
2017-02-15 17:21   ` [RFC 7/8] fpga-region: add sysfs interface Jason Gunthorpe
2017-02-15 17:46     ` Alan Tull
2017-02-15 17:55       ` Moritz Fischer
2017-02-15 18:06       ` Jason Gunthorpe
2017-02-15 18:23         ` Alan Tull
2017-02-15 18:31           ` Moritz Fischer
2017-02-15 19:49           ` Jason Gunthorpe
2017-02-15 22:49             ` Alan Tull
2017-02-15 23:07               ` Jason Gunthorpe
2017-02-15 20:07           ` matthew.gerlach
2017-02-15 20:37             ` Jason Gunthorpe
2017-02-15 20:54               ` Moritz Fischer
2017-02-15 21:15                 ` Jason Gunthorpe
2017-02-15 21:36                   ` Moritz Fischer
2017-02-15 22:42                     ` Alan Tull
2017-02-16  0:16                       ` Moritz Fischer
2017-02-16 17:47                         ` Alan Tull
2017-02-16 17:56                           ` Jason Gunthorpe
2017-02-16 18:11                             ` Moritz Fischer
2017-02-17 22:28                 ` Yves Vandervennet
2017-02-18  2:30                   ` Moritz Fischer
2017-02-18 12:45                     ` Nadathur, Sundar
2017-02-18 20:10                       ` Alan Tull
2017-02-18 20:45                         ` Moritz Fischer
2017-02-19 15:00                           ` Alan Tull
2017-02-19 23:16                             ` Alan Tull
2017-02-20 23:49                               ` Moritz Fischer
2017-02-21 18:33                                 ` Alan Tull
2017-02-22  3:13                                   ` Nadathur, Sundar
2017-02-22  3:49                                     ` Moritz Fischer
2017-02-22  5:12                                       ` Jason Gunthorpe
2017-02-22  5:38                                         ` Moritz Fischer
2017-02-22  5:46                                           ` Nadathur, Sundar
2017-02-22  6:05                                             ` Moritz Fischer
2017-02-22 16:44                                               ` Jason Gunthorpe
2017-02-22 17:50                                                 ` Moritz Fischer
2017-02-22 17:54                                                   ` Jason Gunthorpe
2017-02-22 17:57                                                     ` Moritz Fischer
2017-02-22 16:33                                           ` Alan Tull
2017-02-22 16:44                                             ` Moritz Fischer
2017-02-22 16:52                                               ` Alan Tull
2017-02-27 20:09                                   ` Alan Tull
2017-02-27 22:49                                     ` Moritz Fischer
2017-02-28  0:04                                       ` matthew.gerlach
2017-02-15 21:20         ` Anatolij Gustschin
2017-02-15 16:14 ` [RFC 8/8] doc: fpga: add sysfs document for fpga region Alan Tull
2017-02-28 17:35 ` FPGA Region enhancements and fixes Alan Tull
2017-02-28 22:03   ` Alan Tull

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1487175261-7051-8-git-send-email-atull@kernel.org \
    --to=atull@kernel.org \
    --cc=jgunthorpe@obsidianresearch.com \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=moritz.fischer@ettus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).