Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1425087AbdDUT1s (ORCPT ); Fri, 21 Apr 2017 15:27:48 -0400 Received: from mga04.intel.com ([192.55.52.120]:5448 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1425057AbdDUT1q (ORCPT ); Fri, 21 Apr 2017 15:27:46 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,230,1488873600"; d="scan'208";a="959722771" From: yi1.li@linux.intel.com To: 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, mcgrof@kernel.org, atull@kernel.org Cc: linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org, Yi Li Subject: [PATCHv1 2/2] fpga-mgr: add streaming support Date: Fri, 21 Apr 2017 14:22:22 -0500 Message-Id: <1492802542-1408-3-git-send-email-yi1.li@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1492802542-1408-1-git-send-email-yi1.li@linux.intel.com> References: <1492802542-1408-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 Content-Length: 4332 Lines: 143 From: Yi Li Add fpga_mgr_firmware_stream API to enable streaming/programing FPGA bitstream file from file system to FPGA manager. This code is on top of Luis R. Rodriguez's new driver_data_request_sync API. Signed-off-by: Yi Li --- drivers/fpga/fpga-mgr.c | 96 +++++++++++++++++++++++++++++++++++++++++++ include/linux/fpga/fpga-mgr.h | 4 ++ 2 files changed, 100 insertions(+) diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 188ffef..975194c 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,100 @@ static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, return fpga_mgr_write_complete(mgr, info); } +static int fpga_mgr_streaming_fw_cb(void *context, const struct firmware *fw) +{ + int ret = -EINVAL; + struct driver_data_req_params *params = + (struct driver_data_req_params *)context; + struct fpga_image_info *info = (struct fpga_image_info *) + params->streaming_reqs.opt_ctx1; + struct fpga_manager *mgr = (struct fpga_manager *) + params->streaming_reqs.opt_ctx2; + struct device *dev = &mgr->dev; + + /* + * init. + */ + if (params->streaming_reqs.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; + } + + params->streaming_reqs.offset += fw->size; + 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; + const struct firmware *fw = NULL; + char *path = NULL; + size_t length = INT_MAX; + struct device *dev = &mgr->dev; + const struct driver_data_req_params req_params = { + .streaming_reqs.streaming = true, + .streaming_reqs.offset = 0, + .streaming_reqs.driver_data = &fw, + .streaming_reqs.path = &path, + .streaming_reqs.buf_size = SZ_4K, + .streaming_reqs.opt_ctx1 = info, + .streaming_reqs.opt_ctx2 = mgr, + DRIVER_DATA_KEEP_SYNC(fpga_mgr_streaming_fw_cb, + &req_params), + }; + + 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 -= fw->size; + if (fw->size < SZ_4K) + break; + } + + __putname(*req_params.streaming_reqs.path); + release_firmware(fw); + + 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 e2ef94fd..97907f5 100644 --- a/include/linux/fpga/fpga-mgr.h +++ b/include/linux/fpga/fpga-mgr.h @@ -140,6 +140,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