From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9AFF0C4332F for ; Wed, 2 Feb 2022 20:56:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:Subject:Message-ID:Date:From: In-Reply-To:References:MIME-Version:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=m6vd2UOgJkJGLb7lXV6kwNWgWONxn09T3BPL20UalU8=; b=fXHl46DhEqfA7V gnPyl+vxT5nnqJaI3qdvlz68u2evijyS8tUmTNKxhVEywMaZifCppw3DAH7biFMIaKNh5EhaduVCC ueJTdY5KXXNOuDniv39i40yeaBtNdw9GZc5RutUVhwnHyOtw42/FpruOAaqF8jJSQvRo56ZS7wn5U wZHB0f5rEnkliRh+HDNvGgiGCAjfgQ0anPq0sLGkwUHMccNvmGajZh2C+47hzQmzsW2E1r/0RwOyE rOr5w5JxsWEfjenL3opxLOfb90XDfiQy9Nfo7V7ACA0sJwynEuA2o1Vk58VIOd/td8jVuuRQ4UXLN gmbdaG2Gp5KU3pIDvpbw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nFMeT-00Gr5V-0h; Wed, 02 Feb 2022 20:54:53 +0000 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nFMeN-00Gr45-Ui for linux-arm-kernel@lists.infradead.org; Wed, 02 Feb 2022 20:54:50 +0000 Received: by mail-wr1-x433.google.com with SMTP id j25so152346wrb.2 for ; Wed, 02 Feb 2022 12:54:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=o7VayQf6efhpiXCN0lLNka2UC7dSOX/sS4MDR7h8jGM=; b=jnU6UbZDGW6qiaRscoP52Zz7aZCqc0sxT0h47qvZvNS3mvIhs1nDs2wpOLHU65IpHI Wuk57EHsqTVh9egqnKoemrY18wrZ9NzKFlJA8ClglISxbEucz4n/MjrpGZc5UNACSysj PaWjSQTUJ51wK6m+mIMNhKmSyGAeRdcU1xn5Jn/+nClZmwbx30xKOF/cB49sYIgoe220 ixWv//ANhFi4pDxNO3CxwpLRguhQiSWHIYG1NWd7O4czWTaUPS+anGC7lZOm3WSNNuDH lrwBQfOByoF4XsW7VynIOBTfEPBOhqt1oqjQjyTaiNkZazinMFnNXVn4jjlJwxS0+wFZ 4T0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=o7VayQf6efhpiXCN0lLNka2UC7dSOX/sS4MDR7h8jGM=; b=LrzGF7iUkCUmfGJU2XJA/w/2Dzs/q7T7sb85RnTXTed0FnMajujX+fH+G/whhzINe0 QMjNh/Epj2W6hGO8ZJj1VlwotzKutftshdh/4x0CLpjK8vqm5eESQpMJ55ewqmApdnOq PckqbSOx5lt9oQb2BUZBE1Kv4QTvJv4qo89twmSLAwGlIHWTfOBUjxHk4e/vaDuTLAbj DR37TTuR5xbeLvk8RChG/i3LXSeCBans3aF2KF0LaxxoBPZVHKG/1VMDtKUyP+1FS3v6 dygJ7VCDHH13LiHO+zmGIC8rwcd2o8ceqLsvFeurQxm1SEFoLPSkkanc4yWZIiMQlisr XPpA== X-Gm-Message-State: AOAM533FzFb19nLP5iumhJQFMKSfyxEmPdH7i05fmRZAF6Yl/XSHTHaP eaWoD8CMJWKMuJyrINdVEXMs3nlmW/d7lMJ9RrjSIA== X-Google-Smtp-Source: ABdhPJy2B3+s5kgv6RihF7aMlyAALKGkQ+ifv41MgWSls3P5TJzLs7YnW0w8fhao/sqADGCeLGxu4HyrO8drLvXV/QU= X-Received: by 2002:adf:aa8a:: with SMTP id h10mr26262297wrc.658.1643835286086; Wed, 02 Feb 2022 12:54:46 -0800 (PST) MIME-Version: 1.0 References: <20211130220100.25888-1-mike.leach@linaro.org> <20211130220100.25888-5-mike.leach@linaro.org> <20220128184333.GD2240873@p14s> In-Reply-To: <20220128184333.GD2240873@p14s> From: Mike Leach Date: Wed, 2 Feb 2022 20:54:35 +0000 Message-ID: Subject: Re: [PATCH v2 4/6] coresight: samples: Add an example config writer for configfs load To: Mathieu Poirier Cc: linux-arm-kernel@lists.infradead.org, coresight@lists.linaro.org, suzuki.poulose@arm.com, leo.yan@linaro.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220202_125448_041295_FE0B2EB2 X-CRM114-Status: GOOD ( 46.40 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi Mathieu, On Fri, 28 Jan 2022 at 18:43, Mathieu Poirier wrote: > > On Tue, Nov 30, 2021 at 10:00:58PM +0000, Mike Leach wrote: > > Add an example file generator to test loading configurations via a > > binary attribute in configfs. > > > > Provides a file buffer writer function that can be re-used in other > > userspace programs. > > > > Buffer write format matches that expected by the corresponding reader > > in the configfs driver code. > > The user space program to read and write configurations should go under > tools/coresight rather than sample/coresight. Have a look at tools/perf and tools/bpf. > There is a lot of examples in there that deals with code shared between kernel > and user space. There is even a nifty scripts that checks for diverging files > between kernel and tools when compiling the perf tools. > OK - hadn't thought of that but seems like a good idea, > You should also find how to properly deal with error codes and standard > types in a generic way rather than redefining them as in the previous patch. > Agreed - having a quick look, there appears to be suitable headers in tools/include/uapi/... > I think this patchset is holding together but needs some refactoring to conform > to what others have done when dealing with shared kernel/user space code. > Agreed. Thanks Mike > I am done reviewing this set. > > Thanks, > Mathieu > > > > > Signed-off-by: Mike Leach > > --- > > samples/coresight/Makefile | 7 + > > samples/coresight/coresight-cfg-bufw.c | 302 ++++++++++++++++++++++ > > samples/coresight/coresight-cfg-bufw.h | 24 ++ > > samples/coresight/coresight-cfg-filegen.c | 89 +++++++ > > 4 files changed, 422 insertions(+) > > create mode 100644 samples/coresight/coresight-cfg-bufw.c > > create mode 100644 samples/coresight/coresight-cfg-bufw.h > > create mode 100644 samples/coresight/coresight-cfg-filegen.c > > > > diff --git a/samples/coresight/Makefile b/samples/coresight/Makefile > > index b3fce4af2347..07bfd99d7a68 100644 > > --- a/samples/coresight/Makefile > > +++ b/samples/coresight/Makefile > > @@ -1,4 +1,11 @@ > > # SPDX-License-Identifier: GPL-2.0-only > > > > +# coresight config - loadable module configuration. > > obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight-cfg-sample.o > > ccflags-y += -I$(srctree)/drivers/hwtracing/coresight > > + > > +# coresight config - configfs loadable binary config generator > > +userprogs-always-y += coresight-cfg-filegen > > + > > +coresight-cfg-filegen-objs := coresight-cfg-filegen.o coresight-cfg-bufw.o > > +userccflags += -I$(srctree)/drivers/hwtracing/coresight > > diff --git a/samples/coresight/coresight-cfg-bufw.c b/samples/coresight/coresight-cfg-bufw.c > > new file mode 100644 > > index 000000000000..8c32a8509eef > > --- /dev/null > > +++ b/samples/coresight/coresight-cfg-bufw.c > > @@ -0,0 +1,302 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > > + * Author: Mike Leach > > + */ > > + > > +#include > > + > > +#include "coresight-cfg-bufw.h" > > + > > +/* > > + * Set of macros to make writing the buffer code easier. > > + *. > > + * Uses naming convention as 'buffer' for the buffer pointer and > > + * 'used' as the current bytes used by the encosing function. > > + */ > > +#define cscfg_write_u64(val64) { \ > > + *(u64 *)(buffer + used) = val64; \ > > + used += sizeof(u64); \ > > + } > > + > > +#define cscfg_write_u32(val32) { \ > > + *(u32 *)(buffer + used) = val32; \ > > + used += sizeof(u32); \ > > + } > > + > > +#define cscfg_write_u16(val16) { \ > > + *(u16 *)(buffer + used) = val16; \ > > + used += sizeof(u16); \ > > + } > > + > > +#define cscfg_write_u8(val8) { \ > > + *(buffer + used) = val8; \ > > + used++; \ > > + } > > + > > +#define CHECK_WRET(rval) { \ > > + if (rval < 0) \ > > + return rval; \ > > + used += rval; \ > > + } > > + > > +/* write the header at the start of the buffer */ > > +static int cscfg_file_write_fhdr(u8 *buffer, const int buflen, > > + const struct cscfg_file_header *fhdr) > > +{ > > + int used = 0; > > + > > + cscfg_write_u32(fhdr->magic_version); > > + cscfg_write_u16(fhdr->length); > > + cscfg_write_u16(fhdr->nr_features); > > + return used; > > +} > > + > > +static int cscfg_file_write_string(u8 *buffer, const int buflen, const char *string) > > +{ > > + int len, used = 0; > > + > > + len = strlen(string); > > + if (len > CSCFG_FILE_STR_MAXSIZE) > > + return -EINVAL; > > + > > + if (buflen < (len + 1 + sizeof(u16))) > > + return -EINVAL; > > + > > + cscfg_write_u16((u16)(len + 1)); > > + strcpy((char *)(buffer + used), string); > > + used += (len + 1); > > + > > + return used; > > +} > > + > > +static int cscfg_file_write_elem_hdr(u8 *buffer, const int buflen, > > + struct cscfg_file_elem_header *ehdr) > > +{ > > + int used = 0; > > + > > + if (buflen < (sizeof(u16) + sizeof(u8))) > > + return -EINVAL; > > + > > + cscfg_write_u16(ehdr->elem_length); > > + cscfg_write_u8(ehdr->elem_type); > > + > > + return used; > > +} > > + > > + > > +static int cscfg_file_write_config(u8 *buffer, const int buflen, > > + struct cscfg_config_desc *config_desc) > > +{ > > + int used = 0, bytes_w, space_req, preset_bytes, i; > > + struct cscfg_file_elem_header ehdr; > > + > > + ehdr.elem_length = 0; > > + ehdr.elem_type = CSCFG_FILE_ELEM_TYPE_CFG; > > + > > + /* write element header at current buffer location */ > > + bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr); > > + CHECK_WRET(bytes_w); > > + > > + /* write out the configuration name */ > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + config_desc->name); > > + CHECK_WRET(bytes_w); > > + > > + /* write out the description string */ > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + config_desc->description); > > + CHECK_WRET(bytes_w); > > + > > + /* > > + * calculate the space needed for variables + presets > > + * [u16 value - nr_presets] > > + * [u32 value - nr_total_params] > > + * [u16 value - nr_feat_refs] > > + * [u64 values] * (nr_presets * nr_total_params) > > + */ > > + preset_bytes = sizeof(u64) * config_desc->nr_presets * config_desc->nr_total_params; > > + space_req = (sizeof(u16) * 2) + sizeof(u32) + preset_bytes; > > + > > + if ((buflen - used) < space_req) > > + return -EINVAL; > > + > > + cscfg_write_u16((u16)config_desc->nr_presets); > > + cscfg_write_u32((u32)config_desc->nr_total_params); > > + cscfg_write_u16((u16)config_desc->nr_feat_refs); > > + if (preset_bytes) { > > + memcpy(buffer + used, (u8 *)config_desc->presets, preset_bytes); > > + used += preset_bytes; > > + } > > + > > + /* now write the feature ref names */ > > + for (i = 0; i < config_desc->nr_feat_refs; i++) { > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + config_desc->feat_ref_names[i]); > > + CHECK_WRET(bytes_w); > > + } > > + > > + /* rewrite the element header with the correct length */ > > + ehdr.elem_length = used; > > + bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr); > > + /* no CHECK_WRET as used must not be updated */ > > + if (bytes_w < 0) > > + return bytes_w; > > + > > + return used; > > +} > > + > > +/* > > + * write a parameter structure into the buffer in following format: > > + * [cscfg_file_elem_str] - parameter name. > > + * [u64 value: param_value] - initial value. > > + */ > > +static int cscfg_file_write_param(u8 *buffer, const int buflen, > > + struct cscfg_parameter_desc *param_desc) > > +{ > > + int used = 0, bytes_w; > > + > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + param_desc->name); > > + CHECK_WRET(bytes_w); > > + > > + if ((buflen - used) < sizeof(u64)) > > + return -EINVAL; > > + > > + cscfg_write_u64(param_desc->value); > > + return used; > > +} > > +/* > > + * Write a feature element from cscfg_feature_desc in following format: > > + * > > + * [cscfg_file_elem_header] - header length is total bytes to end of param structures. > > + * [cscfg_file_elem_str] - feature name. > > + * [cscfg_file_elem_str] - feature description. > > + * [u32 value: match_flags] > > + * [u16 value: nr_regs] - number of registers. > > + * [u16 value: nr_params] - number of parameters. > > + * [cscfg_regval_desc struct] * nr_regs > > + * [PARAM_ELEM] * nr_params > > + * > > + * > > + */ > > +static int cscfg_file_write_feat(u8 *buffer, const int buflen, > > + struct cscfg_feature_desc *feat_desc) > > +{ > > + struct cscfg_file_elem_header ehdr; > > + struct cscfg_regval_desc *p_reg_desc; > > + int used = 0, bytes_w, i, space_req; > > + u32 val32; > > + > > + ehdr.elem_length = 0; > > + ehdr.elem_type = CSCFG_FILE_ELEM_TYPE_FEAT; > > + > > + /* write element header at current buffer location */ > > + bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr); > > + CHECK_WRET(bytes_w); > > + > > + /* write out the name string */ > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + feat_desc->name); > > + CHECK_WRET(bytes_w) > > + > > + /* write out the description string */ > > + bytes_w = cscfg_file_write_string(buffer + used, buflen - used, > > + feat_desc->description); > > + CHECK_WRET(bytes_w); > > + > > + /* check for space for variables and register structures */ > > + space_req = (sizeof(u16) * 2) + sizeof(u32) + > > + (sizeof(struct cscfg_regval_desc) * feat_desc->nr_regs); > > + if ((buflen - used) < space_req) > > + return -EINVAL; > > + > > + /* write the variables */ > > + cscfg_write_u32((u32)feat_desc->match_flags); > > + cscfg_write_u16((u16)feat_desc->nr_regs); > > + cscfg_write_u16((u16)feat_desc->nr_params); > > + > > + /*write the registers */ > > + for (i = 0; i < feat_desc->nr_regs; i++) { > > + p_reg_desc = (struct cscfg_regval_desc *)&feat_desc->regs_desc[i]; > > + CSCFG_FILE_REG_DESC_INFO_TO_U32(val32, p_reg_desc); > > + cscfg_write_u32(val32); > > + cscfg_write_u64(feat_desc->regs_desc[i].val64); > > + } > > + > > + /* write any parameters */ > > + for (i = 0; i < feat_desc->nr_params; i++) { > > + bytes_w = cscfg_file_write_param(buffer + used, buflen - used, > > + &feat_desc->params_desc[i]); > > + CHECK_WRET(bytes_w); > > + } > > + > > + /* > > + * rewrite the element header at the start of the buffer block > > + * with the correct length > > + */ > > + ehdr.elem_length = used; > > + bytes_w = cscfg_file_write_elem_hdr(buffer, buflen, &ehdr); > > + /* no CHECK_WRET as used must not be updated */ > > + if (bytes_w < 0) > > + return bytes_w; > > + > > + return used; > > +} > > + > > +/* > > + * write a buffer from the configuration and feature > > + * descriptors to write into a file for configfs. > > + * > > + * Will only write one config, and/or a number of features, > > + * per the file standard. > > + */ > > +int cscfg_file_write_buffer(u8 *buffer, const int buflen, > > + struct cscfg_config_desc *config_desc, > > + struct cscfg_feature_desc **feat_descs) > > +{ > > + struct cscfg_file_header fhdr; > > + int used = 0, bytes_w, i; > > + > > + /* init the file header */ > > + fhdr.magic_version = CSCFG_FILE_MAGIC_VERSION; > > + fhdr.length = 0; > > + fhdr.nr_features = 0; > > + > > + /* count the features */ > > + if (feat_descs) { > > + while (feat_descs[fhdr.nr_features]) > > + fhdr.nr_features++; > > + } > > + > > + /* need a buffer and at least one config or feature */ > > + if ((!config_desc && !fhdr.nr_features) || > > + !buffer || (buflen > CSCFG_FILE_MAXSIZE)) > > + return -EINVAL; > > + > > + /* write a header at the start to get the length of the header */ > > + bytes_w = cscfg_file_write_fhdr(buffer, buflen, &fhdr); > > + CHECK_WRET(bytes_w); > > + > > + /* write a single config */ > > + if (config_desc) { > > + bytes_w = cscfg_file_write_config(buffer + used, buflen - used, > > + config_desc); > > + CHECK_WRET(bytes_w); > > + } > > + > > + /* write any features */ > > + for (i = 0; i < fhdr.nr_features; i++) { > > + bytes_w = cscfg_file_write_feat(buffer + used, buflen - used, > > + feat_descs[i]); > > + CHECK_WRET(bytes_w); > > + } > > + > > + /* finally re-write the header at the buffer start with the correct length */ > > + fhdr.length = (u16)used; > > + bytes_w = cscfg_file_write_fhdr(buffer, buflen, &fhdr); > > + /* no CHECK_WRET as used must not be updated */ > > + if (bytes_w < 0) > > + return bytes_w; > > + return used; > > +} > > diff --git a/samples/coresight/coresight-cfg-bufw.h b/samples/coresight/coresight-cfg-bufw.h > > new file mode 100644 > > index 000000000000..00b16c583cad > > --- /dev/null > > +++ b/samples/coresight/coresight-cfg-bufw.h > > @@ -0,0 +1,24 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > > + * Author: Mike Leach > > + */ > > + > > +#ifndef _CORESIGHT_CFG_BUFW_H > > +#define _CORESIGHT_CFG_BUFW_H > > + > > +#include "coresight-config-file.h" > > + > > +/* > > + * Function to take coresight configurations and features and > > + * write them into a supplied memory buffer for serialisation > > + * into a file. > > + * > > + * Resulting file can then be loaded into the coresight > > + * infrastructure via configfs. > > + */ > > +int cscfg_file_write_buffer(u8 *buffer, const int buflen, > > + struct cscfg_config_desc *config_desc, > > + struct cscfg_feature_desc **feat_descs); > > + > > +#endif /* _CORESIGHT_CFG_BUFW_H */ > > diff --git a/samples/coresight/coresight-cfg-filegen.c b/samples/coresight/coresight-cfg-filegen.c > > new file mode 100644 > > index 000000000000..c8be18ee97b6 > > --- /dev/null > > +++ b/samples/coresight/coresight-cfg-filegen.c > > @@ -0,0 +1,89 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (c) 2020 Linaro Limited, All rights reserved. > > + * Author: Mike Leach > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include "coresight-cfg-bufw.h" > > + > > +/* > > + * generate example binary coresight configuration files for loading > > + * into the coresight subsystem via configfs > > + */ > > + > > +/* create a similar configuration example as the coresight-cfg-sample.c file. */ > > + > > +/* we will provide 4 sets of preset parameter values */ > > +#define AFDO2_NR_PRESETS 4 > > +/* the total number of parameters in used features - strobing has 2 */ > > +#define AFDO2_NR_PARAM_SUM 2 > > + > > +static const char *afdo2_ref_names[] = { > > + "strobing", > > +}; > > + > > +/* > > + * set of presets leaves strobing window constant while varying period to allow > > + * experimentation with mark / space ratios for various workloads > > + */ > > +static u64 afdo2_presets[AFDO2_NR_PRESETS][AFDO2_NR_PARAM_SUM] = { > > + { 2000, 100 }, > > + { 2000, 1000 }, > > + { 2000, 5000 }, > > + { 2000, 10000 }, > > +}; > > + > > +struct cscfg_config_desc afdo3 = { > > + .name = "autofdo3", > > + .description = "Setup ETMs with strobing for autofdo\n" > > + "Supplied presets allow experimentation with mark-space ratio for various loads\n", > > + .nr_feat_refs = ARRAY_SIZE(afdo2_ref_names), > > + .feat_ref_names = afdo2_ref_names, > > + .nr_presets = AFDO2_NR_PRESETS, > > + .nr_total_params = AFDO2_NR_PARAM_SUM, > > + .presets = &afdo2_presets[0][0], > > +}; > > + > > +static struct cscfg_feature_desc *sample_feats[] = { > > + NULL > > +}; > > + > > +static struct cscfg_config_desc *sample_cfgs[] = { > > + &afdo3, > > + NULL > > +}; > > + > > + > > +#define CSCFG_BIN_FILENAME "example1.cscfg" > > + > > +int main(int argc, char **argv) > > +{ > > + u8 buffer[CSCFG_FILE_MAXSIZE]; > > + int used; > > + FILE *fp; > > + > > + printf("Coresight Configuration file Generator\n\n"); > > + > > + used = cscfg_file_write_buffer(buffer, CSCFG_FILE_MAXSIZE, > > + sample_cfgs[0], sample_feats); > > + > > + if (used < 0) { > > + printf("Error %d writing configuration %s into buffer\n", > > + used, sample_cfgs[0]->name); > > + return used; > > + } > > + > > + fp = fopen(CSCFG_BIN_FILENAME, "wb"); > > + if (fp == NULL) { > > + printf("Error opening file %s\n", CSCFG_BIN_FILENAME); > > + return -1; > > + } > > + fwrite(buffer, used, sizeof(u8), fp); > > + fclose(fp); > > + return 0; > > +} > > -- > > 2.17.1 > > -- Mike Leach Principal Engineer, ARM Ltd. Manchester Design Centre. UK _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel