From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756883AbdETGyc (ORCPT ); Sat, 20 May 2017 02:54:32 -0400 Received: from mga09.intel.com ([134.134.136.24]:19230 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751336AbdETGyY (ORCPT ); Sat, 20 May 2017 02:54:24 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,367,1491289200"; d="scan'208";a="1132798943" 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 Subject: [PATCHv2 3/3] fpga_mgr: Add streaming support through the new driver_data API Date: Sat, 20 May 2017 01:49:08 -0500 Message-Id: <1495262948-1106-4-git-send-email-yi1.li@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1495262948-1106-1-git-send-email-yi1.li@linux.intel.com> References: <1495262948-1106-1-git-send-email-yi1.li@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Yi Li 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 --- 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 #include #include +#include +#include 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, ¶ms), + .reqs = DRIVER_DATA_REQ_NO_CACHE | DRIVER_DATA_REQ_STREAMING, + .alloc_buf_size = SZ_4K, + .alloc_buf = &buf, + .img_offset = ¶ms.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