All of lore.kernel.org
 help / color / mirror / Atom feed
From: yi1.li@linux.intel.com
To: mcgrof@kernel.org, atull@kernel.org, gregkh@linuxfoundation.org,
	wagi@monom.org, dwmw2@infradead.org, rafal@milecki.pl,
	arend.vanspriel@broadcom.com, rjw@rjwysocki.net,
	moritz.fischer@ettus.com, pmladek@suse.com,
	johannes.berg@intel.com, emmanuel.grumbach@intel.com,
	luciano.coelho@intel.com, kvalo@codeaurora.org, luto@kernel.org,
	takahiro.akashi@linaro.org, dhowells@redhat.com,
	pjones@redhat.com
Cc: linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org,
	Yi Li <yi1.li@linux.intel.com>
Subject: [PATCHv2 3/3] fpga_mgr: Add streaming support through the new driver_data API
Date: Sat, 20 May 2017 01:49:08 -0500	[thread overview]
Message-ID: <1495262948-1106-4-git-send-email-yi1.li@linux.intel.com> (raw)
In-Reply-To: <1495262948-1106-1-git-send-email-yi1.li@linux.intel.com>

From: Yi Li <yi1.li@linux.intel.com>

Since the FPGA image are getting bigger in size, this add an new API
fpga_mgr_firmware_stream in FPGA manager, which will stream FPGA image in
4KB trunks.

Signed-off-by: Yi Li <yi1.li@linux.intel.com>
---
 drivers/fpga/fpga-mgr.c       | 111 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/fpga/fpga-mgr.h |   4 ++
 2 files changed, 115 insertions(+)

diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index 188ffef..420ee38 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -27,6 +27,8 @@
 #include <linux/slab.h>
 #include <linux/scatterlist.h>
 #include <linux/highmem.h>
+#include <linux/sizes.h>
+#include <linux/driver_data.h>
 
 static DEFINE_IDA(fpga_mgr_ida);
 static struct class *fpga_mgr_class;
@@ -196,6 +198,115 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr,
 	return fpga_mgr_write_complete(mgr, info);
 }
 
+struct fpga_mgr_streaming_priv_params {
+	struct fpga_image_info *info;
+	struct fpga_manager *mgr;
+	loff_t offset;
+	loff_t fw_size;
+};
+
+static int fpga_mgr_streaming_fw_cb(void *context, const struct firmware *fw,
+				    int err)
+{
+	int ret = -EINVAL;
+	struct fpga_mgr_streaming_priv_params *params =
+		(struct fpga_mgr_streaming_priv_params *)context;
+	struct fpga_image_info *info = params->info;
+	struct fpga_manager *mgr = params->mgr;
+	struct device *dev = &mgr->dev;
+
+	params->fw_size = fw->size;
+	/*
+	 * init.
+	 */
+	if (params->offset == 0) {
+		ret = fpga_mgr_write_init_buf(mgr, info, fw->data, fw->size);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * Write the FPGA image to the FPGA.
+	 */
+	mgr->state = FPGA_MGR_STATE_WRITE;
+	ret = mgr->mops->write(mgr, fw->data, fw->size);
+	if (ret) {
+		dev_err(dev, "Error while writing image data to FPGA\n");
+		mgr->state = FPGA_MGR_STATE_WRITE_ERR;
+		return ret;
+	}
+
+	if (fw->size < SZ_4K)
+		ret = fpga_mgr_write_complete(mgr, info);
+
+	return ret;
+}
+
+/**
+ * fpga_mgr_firmware_stream - streaming firmware and load to fpga
+ * @mgr:	fpga manager
+ * @info:	fpga image specific information
+ * @image_name:	name of image file on the firmware search path
+ *
+ * Streaming an FPGA image using the firmware class, then write out to the FPGA.
+ * Update the state before each step to provide info on what step failed if
+ * there is a failure.  This code assumes the caller got the mgr pointer
+ * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error
+ * code.
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_firmware_stream(struct fpga_manager *mgr,
+			     struct fpga_image_info *info,
+			     const char *image_name)
+{
+	int ret;
+	char *path = NULL;
+	void *buf;
+	size_t length = INT_MAX;
+	struct device *dev = &mgr->dev;
+	struct fpga_mgr_streaming_priv_params params = {
+		.info = info,
+		.mgr = mgr,
+		.fw_size = 0,
+		.offset = 0,
+	};
+
+	const struct driver_data_req_params req_params = {
+		DRIVER_DATA_DEFAULT_SYNC(fpga_mgr_streaming_fw_cb, &params),
+		.reqs = DRIVER_DATA_REQ_NO_CACHE | DRIVER_DATA_REQ_STREAMING,
+		.alloc_buf_size = SZ_4K,
+		.alloc_buf = &buf,
+		.img_offset = &params.offset,
+		.path = &path,
+	};
+
+	buf = kmalloc(SZ_4K, GFP_KERNEL);
+	if (!buf) {
+		dev_err(dev, "%s: kmalloc buf failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
+	while (length > 0) {
+		ret = driver_data_request_sync(image_name, &req_params, dev);
+		if (ret) {
+			dev_err(dev, "Error reading firmware %d\n", ret);
+			mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
+			return ret;
+		}
+
+		length -= params.fw_size;
+		params.offset += params.fw_size;
+		if (params.fw_size < SZ_4K)
+			break;
+	}
+
+	kfree(buf);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_firmware_stream);
+
 /**
  * fpga_mgr_buf_load - load fpga from image in buffer
  * @mgr:	fpga manager
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index b4ac24c..083e091 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -143,6 +143,10 @@ int fpga_mgr_firmware_load(struct fpga_manager *mgr,
 			   struct fpga_image_info *info,
 			   const char *image_name);
 
+int fpga_mgr_firmware_stream(struct fpga_manager *mgr,
+			     struct fpga_image_info *info,
+			     const char *image_name);
+
 struct fpga_manager *of_fpga_mgr_get(struct device_node *node);
 
 struct fpga_manager *fpga_mgr_get(struct device *dev);
-- 
2.7.4

  parent reply	other threads:[~2017-05-20  6:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-20  6:49 [PATCHv2 0/3] Add streaming support to driver_data API yi1.li
2017-05-20  6:49 ` [PATCHv2 1/3] firmware: Add streaming support for driver_data_request_sync API yi1.li
2017-05-20  6:49 ` [PATCHv2 2/3] test: add streaming test to driver_data tester yi1.li
2017-05-20  6:49 ` yi1.li [this message]
2017-05-22 21:09   ` [PATCHv2 3/3] fpga_mgr: Add streaming support through the new driver_data API Alan Tull
2017-05-23  4:11     ` Li, Yi
2017-05-23 15:21       ` Alan Tull
2017-05-23 15:25         ` Alan Tull
2017-05-24 13:25           ` Li, Yi
2017-05-24 13:45           ` Li, Yi

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=1495262948-1106-4-git-send-email-yi1.li@linux.intel.com \
    --to=yi1.li@linux.intel.com \
    --cc=arend.vanspriel@broadcom.com \
    --cc=atull@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=dwmw2@infradead.org \
    --cc=emmanuel.grumbach@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=johannes.berg@intel.com \
    --cc=kvalo@codeaurora.org \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luciano.coelho@intel.com \
    --cc=luto@kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=moritz.fischer@ettus.com \
    --cc=pjones@redhat.com \
    --cc=pmladek@suse.com \
    --cc=rafal@milecki.pl \
    --cc=rjw@rjwysocki.net \
    --cc=takahiro.akashi@linaro.org \
    --cc=wagi@monom.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.