From patchwork Fri Apr 21 19:22:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Li, Yi" X-Patchwork-Id: 9693595 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 36A0A601D4 for ; Fri, 21 Apr 2017 19:28:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 24A2928654 for ; Fri, 21 Apr 2017 19:28:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 198602865C; Fri, 21 Apr 2017 19:28:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AA74E28654 for ; Fri, 21 Apr 2017 19:28:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1424987AbdDUT1r (ORCPT ); Fri, 21 Apr 2017 15:27:47 -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 Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Apr 2017 12:27:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.37,230,1488873600"; d="scan'208";a="959722771" Received: from yi-patch.an.intel.com ([10.122.105.158]) by orsmga003.jf.intel.com with ESMTP; 21 Apr 2017 12:27:42 -0700 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-fpga-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fpga@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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);