From patchwork Fri Jun 18 08:53:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 12330617 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64C5EC48BE8 for ; Fri, 18 Jun 2021 08:53:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D7A1613E7 for ; Fri, 18 Jun 2021 08:53:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233478AbhFRIzy (ORCPT ); Fri, 18 Jun 2021 04:55:54 -0400 Received: from smtp05.smtpout.orange.fr ([80.12.242.127]:18098 "EHLO smtp.smtpout.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232422AbhFRIzx (ORCPT ); Fri, 18 Jun 2021 04:55:53 -0400 Received: from localhost.localdomain ([114.149.34.46]) by mwinf5d28 with ME id JYtR2500E0zjR6y03Ythcp; Fri, 18 Jun 2021 10:53:43 +0200 X-ME-Helo: localhost.localdomain X-ME-Auth: bWFpbGhvbC52aW5jZW50QHdhbmFkb28uZnI= X-ME-Date: Fri, 18 Jun 2021 10:53:43 +0200 X-ME-IP: 114.149.34.46 From: Vincent Mailhol To: Marc Kleine-Budde , Stephen Hemminger , linux-can@vger.kernel.org Cc: Oliver Hartkopp , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 1/4] iplink_can: fix configuration ranges in print_usage() Date: Fri, 18 Jun 2021 17:53:19 +0900 Message-Id: <20210618085322.147462-2-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> References: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The configuration ranges in print_usage() are taken from "Table 8 - Time segments' minimum configuration ranges" in section 11.3.1.2 "Configuration of the bit time parameters" of ISO 11898-1. The standard clearly specifies that "implementations may allow time segments that exceed the minimum required configuration ranges specified in Table 8". Because no maximum ranges are given, all given ranges { a..b } are simply replaced with { NUMBER }. The actual ranges are specific to earch device and should be confirmed doing: $ ip --details link show can0 1: can0: mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 minmtu 0 maxmtu 0 can state STOPPED restart-ms 0 ES582.1/ES584.1: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp-inc 1 ES582.1/ES584.1: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 dbrp-inc 1 clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 Signed-off-by: Vincent Mailhol --- ip/iplink_can.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 6a26f3ff..2736f3ab 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -44,13 +44,13 @@ static void print_usage(FILE *f) "\n" "\t[ termination { 0..65535 } ]\n" "\n" - "\tWhere: BITRATE := { 1..1000000 }\n" + "\tWhere: BITRATE := { NUMBER }\n" "\t SAMPLE-POINT := { 0.000..0.999 }\n" "\t TQ := { NUMBER }\n" - "\t PROP-SEG := { 1..8 }\n" - "\t PHASE-SEG1 := { 1..8 }\n" - "\t PHASE-SEG2 := { 1..8 }\n" - "\t SJW := { 1..4 }\n" + "\t PROP-SEG := { NUMBER }\n" + "\t PHASE-SEG1 := { NUMBER }\n" + "\t PHASE-SEG2 := { NUMBER }\n" + "\t SJW := { NUMBER }\n" "\t RESTART-MS := { 0 | NUMBER }\n" ); } From patchwork Fri Jun 18 08:53:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 12330619 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3D1CC48BE8 for ; Fri, 18 Jun 2021 08:54:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7B5E7613B9 for ; Fri, 18 Jun 2021 08:54:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233357AbhFRI4L (ORCPT ); Fri, 18 Jun 2021 04:56:11 -0400 Received: from smtp05.smtpout.orange.fr ([80.12.242.127]:22707 "EHLO smtp.smtpout.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232250AbhFRI4G (ORCPT ); Fri, 18 Jun 2021 04:56:06 -0400 Received: from localhost.localdomain ([114.149.34.46]) by mwinf5d28 with ME id JYtR2500E0zjR6y03Ytue3; Fri, 18 Jun 2021 10:53:56 +0200 X-ME-Helo: localhost.localdomain X-ME-Auth: bWFpbGhvbC52aW5jZW50QHdhbmFkb28uZnI= X-ME-Date: Fri, 18 Jun 2021 10:53:56 +0200 X-ME-IP: 114.149.34.46 From: Vincent Mailhol To: Marc Kleine-Budde , Stephen Hemminger , linux-can@vger.kernel.org Cc: Oliver Hartkopp , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 2/4] iplink_can: use PRINT_ANY to factorize code and fix signedness Date: Fri, 18 Jun 2021 17:53:20 +0900 Message-Id: <20210618085322.147462-3-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> References: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Current implementation heavily relies on some "if (is_json_context())" switches to decide the context and then does some print_*(PRINT_JSON, ...) when in json context and some fprintf(...) else. Furthermore, current implementation uses either print_int() or the conversion specifier %d to print unsigned integers. This patch factorizes each pairs of print_*(PRINT_JSON, ...) and fprintf into a signle print_*(PRINT_ANY, ...) call. While doing this replacement, it uses proper unsigned function print_uint() as well as the conversion specifier %u when the parameter is an unsigned integer. Signed-off-by: Vincent Mailhol --- ip/iplink_can.c | 341 ++++++++++++++++++++---------------------------- 1 file changed, 141 insertions(+), 200 deletions(-) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 2736f3ab..ec4e122f 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -266,14 +266,34 @@ static const char *can_state_names[CAN_STATE_MAX] = { [CAN_STATE_SLEEPING] = "SLEEPING" }; -static void can_print_json_timing_min_max(const char *attr, int min, int max) +static void can_print_nl_indent(void) +{ + print_nl(); + print_string(PRINT_FP, NULL, "%s", "\t "); +} + +static void can_print_timing_min_max(const char *attr, int min, int max) { open_json_object(attr); - print_int(PRINT_JSON, "min", NULL, min); - print_int(PRINT_JSON, "max", NULL, max); + print_uint(PRINT_ANY, "min", " %u", min); + print_uint(PRINT_ANY, "max", "..%u", max); close_json_object(); } +/* Print nominal bittiming */ +static void can_print_nom_timing_min_max(const char *attr, int min, int max) +{ + print_string(PRINT_FP, NULL, " %s", attr); + can_print_timing_min_max(attr, min, max); +} + +/* Print data bittiming: use a "d" prefix when printing to the file pointer */ +static void can_print_data_timing_min_max(const char *attr, int min, int max) +{ + print_string(PRINT_FP, NULL, " d%s", attr); + can_print_timing_min_max(attr, min, max); +} + static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { if (!tb) @@ -297,56 +317,38 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) struct can_berr_counter *bc = RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]); - if (is_json_context()) { - open_json_object("berr_counter"); - print_int(PRINT_JSON, "tx", NULL, bc->txerr); - print_int(PRINT_JSON, "rx", NULL, bc->rxerr); - close_json_object(); - } else { - fprintf(f, "(berr-counter tx %d rx %d) ", - bc->txerr, bc->rxerr); - } + open_json_object("berr_counter"); + print_uint(PRINT_ANY, "tx", "(berr-counter tx %u", bc->txerr); + print_uint(PRINT_ANY, "rx", " rx %u) ", bc->rxerr); + close_json_object(); } if (tb[IFLA_CAN_RESTART_MS]) { __u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]); - print_int(PRINT_ANY, - "restart_ms", - "restart-ms %d ", - *restart_ms); + print_uint(PRINT_ANY, "restart_ms", "restart-ms %u ", + *restart_ms); } /* bittiming is irrelevant if fixed bitrate is defined */ if (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) { struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]); - - if (is_json_context()) { - json_writer_t *jw; - - open_json_object("bittiming"); - print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate); - jw = get_json_writer(); - jsonw_name(jw, "sample_point"); - jsonw_printf(jw, "%.3f", - (float) bt->sample_point / 1000); - print_int(PRINT_ANY, "tq", NULL, bt->tq); - print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg); - print_int(PRINT_ANY, "phase_seg1", - NULL, bt->phase_seg1); - print_int(PRINT_ANY, "phase_seg2", - NULL, bt->phase_seg2); - print_int(PRINT_ANY, "sjw", NULL, bt->sjw); - close_json_object(); - } else { - fprintf(f, "\n bitrate %d sample-point %.3f ", - bt->bitrate, (float) bt->sample_point / 1000.); - fprintf(f, - "\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d", - bt->tq, bt->prop_seg, - bt->phase_seg1, bt->phase_seg2, - bt->sjw); - } + char sp[6]; + + open_json_object("bittiming"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bitrate", " bitrate %u", bt->bitrate); + snprintf(sp, sizeof(sp), "%.3f", bt->sample_point / 1000.); + print_string(PRINT_ANY, "sample_point", " sample-point %s", sp); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tq", " tq %u", bt->tq); + print_uint(PRINT_ANY, "prop_seg", " prop-seg %u", bt->prop_seg); + print_uint(PRINT_ANY, "phase_seg1", " phase-seg1 %u", + bt->phase_seg1); + print_uint(PRINT_ANY, "phase_seg2", "phase-seg2 %u ", + bt->phase_seg2); + print_uint(PRINT_ANY, "sjw", " sjw %u", bt->sjw); + close_json_object(); } /* bittiming const is irrelevant if fixed bitrate is defined */ @@ -354,28 +356,18 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) struct can_bittiming_const *btc = RTA_DATA(tb[IFLA_CAN_BITTIMING_CONST]); - if (is_json_context()) { - open_json_object("bittiming_const"); - print_string(PRINT_JSON, "name", NULL, btc->name); - can_print_json_timing_min_max("tseg1", - btc->tseg1_min, - btc->tseg1_max); - can_print_json_timing_min_max("tseg2", - btc->tseg2_min, - btc->tseg2_max); - can_print_json_timing_min_max("sjw", 1, btc->sjw_max); - can_print_json_timing_min_max("brp", - btc->brp_min, - btc->brp_max); - print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc); - close_json_object(); - } else { - fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d " - "sjw 1..%d brp %d..%d brp-inc %d", - btc->name, btc->tseg1_min, btc->tseg1_max, - btc->tseg2_min, btc->tseg2_max, btc->sjw_max, - btc->brp_min, btc->brp_max, btc->brp_inc); - } + open_json_object("bittiming_const"); + can_print_nl_indent(); + print_string(PRINT_ANY, "name", " %s:", btc->name); + can_print_nom_timing_min_max("tseg1", + btc->tseg1_min, btc->tseg1_max); + can_print_nom_timing_min_max("tseg2", + btc->tseg2_min, btc->tseg2_max); + can_print_nom_timing_min_max("sjw", 1, btc->sjw_max); + can_print_nom_timing_min_max("brp", + btc->brp_min, btc->brp_max); + print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", btc->brp_inc); + close_json_object(); } if (tb[IFLA_CAN_BITRATE_CONST]) { @@ -391,64 +383,47 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) bitrate = bt->bitrate; } - if (is_json_context()) { - print_uint(PRINT_JSON, - "bittiming_bitrate", - NULL, bitrate); - open_json_array(PRINT_JSON, "bitrate_const"); - for (i = 0; i < bitrate_cnt; ++i) - print_uint(PRINT_JSON, NULL, NULL, - bitrate_const[i]); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n bitrate %u", bitrate); - fprintf(f, "\n ["); - - for (i = 0; i < bitrate_cnt - 1; ++i) { - /* This will keep lines below 80 signs */ - if (!(i % 6) && i) - fprintf(f, "\n "); - - fprintf(f, "%8u, ", bitrate_const[i]); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bittiming_bitrate", " bitrate %u", + bitrate); + can_print_nl_indent(); + open_json_array(PRINT_ANY, is_json_context() ? + "bitrate_const" : " ["); + for (i = 0; i < bitrate_cnt; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) { + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", " "); } - - if (!(i % 6) && i) - fprintf(f, "\n "); - fprintf(f, "%8u ]", bitrate_const[i]); + print_uint(PRINT_ANY, NULL, + i < bitrate_cnt - 1 ? "%8u, " : "%8u", + bitrate_const[i]); } + close_json_array(PRINT_JSON, " ]"); } /* data bittiming is irrelevant if fixed bitrate is defined */ if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) { struct can_bittiming *dbt = RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]); - - if (is_json_context()) { - json_writer_t *jw; - - open_json_object("data_bittiming"); - print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate); - jw = get_json_writer(); - jsonw_name(jw, "sample_point"); - jsonw_printf(jw, "%.3f", - (float) dbt->sample_point / 1000.); - print_int(PRINT_JSON, "tq", NULL, dbt->tq); - print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg); - print_int(PRINT_JSON, "phase_seg1", - NULL, dbt->phase_seg1); - print_int(PRINT_JSON, "phase_seg2", - NULL, dbt->phase_seg2); - print_int(PRINT_JSON, "sjw", NULL, dbt->sjw); - close_json_object(); - } else { - fprintf(f, "\n dbitrate %d dsample-point %.3f ", - dbt->bitrate, - (float) dbt->sample_point / 1000.); - fprintf(f, "\n dtq %d dprop-seg %d dphase-seg1 %d " - "dphase-seg2 %d dsjw %d", - dbt->tq, dbt->prop_seg, dbt->phase_seg1, - dbt->phase_seg2, dbt->sjw); - } + char dsp[6]; + + open_json_object("data_bittiming"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bitrate", " dbitrate %u", dbt->bitrate); + snprintf(dsp, sizeof(dsp), "%.3f", dbt->sample_point / 1000.); + print_string(PRINT_ANY, "sample_point", " dsample-point %s", + dsp); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tq", " dtq %u", dbt->tq); + print_uint(PRINT_ANY, "prop_seg", " dprop-seg %u", + dbt->prop_seg); + print_uint(PRINT_ANY, "phase_seg1", " dphase-seg1 %u", + dbt->phase_seg1); + print_uint(PRINT_ANY, "phase_seg2", " dphase-seg2 %u", + dbt->phase_seg2); + print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw); + close_json_object(); } /* data bittiming const is irrelevant if fixed bitrate is defined */ @@ -457,29 +432,18 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) struct can_bittiming_const *dbtc = RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING_CONST]); - if (is_json_context()) { - open_json_object("data_bittiming_const"); - print_string(PRINT_JSON, "name", NULL, dbtc->name); - can_print_json_timing_min_max("tseg1", - dbtc->tseg1_min, - dbtc->tseg1_max); - can_print_json_timing_min_max("tseg2", - dbtc->tseg2_min, - dbtc->tseg2_max); - can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max); - can_print_json_timing_min_max("brp", - dbtc->brp_min, - dbtc->brp_max); - - print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc); - close_json_object(); - } else { - fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d " - "dsjw 1..%d dbrp %d..%d dbrp-inc %d", - dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max, - dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max, - dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc); - } + open_json_object("data_bittiming_const"); + can_print_nl_indent(); + print_string(PRINT_ANY, "name", " %s:", dbtc->name); + can_print_data_timing_min_max("tseg1", + dbtc->tseg1_min, dbtc->tseg1_max); + can_print_data_timing_min_max("tseg2", + dbtc->tseg2_min, dbtc->tseg2_max); + can_print_data_timing_min_max("sjw", 1, dbtc->sjw_max); + can_print_data_timing_min_max("brp", + dbtc->brp_min, dbtc->brp_max); + print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", dbtc->brp_inc); + close_json_object(); } if (tb[IFLA_CAN_DATA_BITRATE_CONST]) { @@ -497,30 +461,23 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) dbitrate = dbt->bitrate; } - if (is_json_context()) { - print_uint(PRINT_JSON, "data_bittiming_bitrate", - NULL, dbitrate); - open_json_array(PRINT_JSON, "data_bitrate_const"); - for (i = 0; i < dbitrate_cnt; ++i) - print_uint(PRINT_JSON, NULL, NULL, - dbitrate_const[i]); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n dbitrate %u", dbitrate); - fprintf(f, "\n ["); - - for (i = 0; i < dbitrate_cnt - 1; ++i) { - /* This will keep lines below 80 signs */ - if (!(i % 6) && i) - fprintf(f, "\n "); - - fprintf(f, "%8u, ", dbitrate_const[i]); + can_print_nl_indent(); + print_uint(PRINT_ANY, "data_bittiming_bitrate", " dbitrate %u", + dbitrate); + can_print_nl_indent(); + open_json_array(PRINT_ANY, is_json_context() ? + "data_bitrate_const" : " ["); + for (i = 0; i < dbitrate_cnt; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) { + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", " "); } - - if (!(i % 6) && i) - fprintf(f, "\n "); - fprintf(f, "%8u ]", dbitrate_const[i]); + print_uint(PRINT_ANY, NULL, + i < dbitrate_cnt - 1 ? "%8u, " : "%8u", + dbitrate_const[i]); } + close_json_array(PRINT_JSON, " ]"); } if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) { @@ -530,29 +487,21 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) sizeof(*trm_const); int i; - if (is_json_context()) { - print_hu(PRINT_JSON, "termination", NULL, *trm); - open_json_array(PRINT_JSON, "termination_const"); - for (i = 0; i < trm_cnt; ++i) - print_hu(PRINT_JSON, NULL, NULL, trm_const[i]); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n termination %hu [ ", *trm); - - for (i = 0; i < trm_cnt - 1; ++i) - fprintf(f, "%hu, ", trm_const[i]); - - fprintf(f, "%hu ]", trm_const[i]); - } + can_print_nl_indent(); + print_hu(PRINT_ANY, "termination", " termination %hu [ ", *trm); + open_json_array(PRINT_JSON, "termination_const"); + for (i = 0; i < trm_cnt; ++i) + print_hu(PRINT_ANY, NULL, + i < trm_cnt - 1 ? "%hu, " : "%hu", + trm_const[i]); + close_json_array(PRINT_JSON, " ]"); } if (tb[IFLA_CAN_CLOCK]) { struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]); - print_int(PRINT_ANY, - "clock", - "\n clock %d ", - clock->freq); + can_print_nl_indent(); + print_uint(PRINT_ANY, "clock", " clock %u ", clock->freq); } } @@ -565,31 +514,23 @@ static void can_print_xstats(struct link_util *lu, if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) { stats = RTA_DATA(xstats); - if (is_json_context()) { - print_int(PRINT_JSON, "restarts", - NULL, stats->restarts); - print_int(PRINT_JSON, "bus_error", - NULL, stats->bus_error); - print_int(PRINT_JSON, "arbitration_lost", - NULL, stats->arbitration_lost); - print_int(PRINT_JSON, "error_warning", - NULL, stats->error_warning); - print_int(PRINT_JSON, "error_passive", - NULL, stats->error_passive); - print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off); - } else { - fprintf(f, "\n re-started bus-errors arbit-lost " - "error-warn error-pass bus-off"); - fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d", - stats->restarts, stats->bus_error, - stats->arbitration_lost, stats->error_warning, - stats->error_passive, stats->bus_off); - } + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", + " re-started bus-errors arbit-lost error-warn error-pass bus-off"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "restarts", " %-10u", stats->restarts); + print_uint(PRINT_ANY, "bus_error", " %-10u", stats->bus_error); + print_uint(PRINT_ANY, "arbitration_lost", " %-10u", + stats->arbitration_lost); + print_uint(PRINT_ANY, "error_warning", " %-10u", + stats->error_warning); + print_uint(PRINT_ANY, "error_passive", " %-10u", + stats->error_passive); + print_uint(PRINT_ANY, "bus_off", " %-10u", stats->bus_off); } } -static void can_print_help(struct link_util *lu, int argc, char **argv, - FILE *f) +static void can_print_help(struct link_util *lu, int argc, char **argv, FILE *f) { print_usage(f); } From patchwork Fri Jun 18 08:53:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 12330621 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40ADCC48BE8 for ; Fri, 18 Jun 2021 08:54:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2826F61260 for ; Fri, 18 Jun 2021 08:54:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233632AbhFRI4T (ORCPT ); Fri, 18 Jun 2021 04:56:19 -0400 Received: from smtp05.smtpout.orange.fr ([80.12.242.127]:35382 "EHLO smtp.smtpout.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233545AbhFRI4O (ORCPT ); Fri, 18 Jun 2021 04:56:14 -0400 Received: from localhost.localdomain ([114.149.34.46]) by mwinf5d28 with ME id JYtR2500E0zjR6y03Yu2f0; Fri, 18 Jun 2021 10:54:04 +0200 X-ME-Helo: localhost.localdomain X-ME-Auth: bWFpbGhvbC52aW5jZW50QHdhbmFkb28uZnI= X-ME-Date: Fri, 18 Jun 2021 10:54:04 +0200 X-ME-IP: 114.149.34.46 From: Vincent Mailhol To: Marc Kleine-Budde , Stephen Hemminger , linux-can@vger.kernel.org Cc: Oliver Hartkopp , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 3/4] iplink_can: print brp and dbrp bittiming variables Date: Fri, 18 Jun 2021 17:53:21 +0900 Message-Id: <20210618085322.147462-4-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> References: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Report the value of the bit-rate prescaler (brp) for both the nominal and the data bittiming. Currently, only the constant brp values (brp_{min,max,inc}) are being reported. Also, brp is the only member of struct can_bittiming not being reported. Although brp is not used as an input for bittiming calculation, it makes sense to output it. Signed-off-by: Vincent Mailhol --- ip/iplink_can.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ip/iplink_can.c b/ip/iplink_can.c index ec4e122f..311c097d 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -348,6 +348,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_uint(PRINT_ANY, "phase_seg2", "phase-seg2 %u ", bt->phase_seg2); print_uint(PRINT_ANY, "sjw", " sjw %u", bt->sjw); + print_uint(PRINT_ANY, "brp", " brp %u", bt->brp); close_json_object(); } @@ -423,6 +424,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) print_uint(PRINT_ANY, "phase_seg2", " dphase-seg2 %u", dbt->phase_seg2); print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw); + print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp); close_json_object(); } From patchwork Fri Jun 18 08:53:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vincent Mailhol X-Patchwork-Id: 12330623 X-Patchwork-Delegate: dsahern@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-14.0 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B67C7C48BDF for ; Fri, 18 Jun 2021 08:54:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C776613B9 for ; Fri, 18 Jun 2021 08:54:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233552AbhFRI42 (ORCPT ); Fri, 18 Jun 2021 04:56:28 -0400 Received: from smtp05.smtpout.orange.fr ([80.12.242.127]:59206 "EHLO smtp.smtpout.orange.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233511AbhFRI4V (ORCPT ); Fri, 18 Jun 2021 04:56:21 -0400 Received: from localhost.localdomain ([114.149.34.46]) by mwinf5d28 with ME id JYtR2500E0zjR6y03Yu8fi; Fri, 18 Jun 2021 10:54:10 +0200 X-ME-Helo: localhost.localdomain X-ME-Auth: bWFpbGhvbC52aW5jZW50QHdhbmFkb28uZnI= X-ME-Date: Fri, 18 Jun 2021 10:54:10 +0200 X-ME-IP: 114.149.34.46 From: Vincent Mailhol To: Marc Kleine-Budde , Stephen Hemminger , linux-can@vger.kernel.org Cc: Oliver Hartkopp , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Vincent Mailhol Subject: [PATCH v3 4/4] iplink_can: add new CAN FD bittiming parameters: Transmitter Delay Compensation (TDC) Date: Fri, 18 Jun 2021 17:53:22 +0900 Message-Id: <20210618085322.147462-5-mailhol.vincent@wanadoo.fr> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> References: <20210618085322.147462-1-mailhol.vincent@wanadoo.fr> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org At high bit rates, the propagation delay from the TX pin to the RX pin of the transceiver causes measurement errors: the sample point on the RX pin might occur on the previous bit. This issue is addressed in ISO 11898-1 section 11.3.3 "Transmitter delay compensation" (TDC). This patch brings command line support to six TDC parameters which were recently added to the kernel's CAN netlink interface in order to implement TDC: - IFLA_CAN_TDC_TDCV_MAX: Transmitter Delay Compensation Value maximum value - IFLA_CAN_TDC_TDCO_MAX: Transmitter Delay Compensation Offset maximum value - IFLA_CAN_TDC_TDCF_MAX: Transmitter Delay Compensation Filter window maximum value - IFLA_CAN_TDC_TDCV: Transmitter Delay Compensation Value - IFLA_CAN_TDC_TDCO: Transmitter Delay Compensation Offset - IFLA_CAN_TDC_TDCF: Transmitter Delay Compensation Filter window All those new parameters are nested together into the attribute IFLA_CAN_TDC. Zero has a special meaning for both tdcv and tdco: * tdcv: zero means that tdcv is automatically calculated by the transmitter. * tdco: zero means that tdc is disabled and that all parameters (tdcv, tdco and tdcf) should be ignored. In that case, tdc variables are not reported. Please refer to the documentation of struct can_tdc for more details. For reference, here are a few samples of how the output looks like: $ ip link set can0 type can bitrate 1000000 dbitrate 8000000 fd on tdcv 0 tdco 7 tdcf 8 $ ip --details link show can0 1: can0: mtu 72 qdisc noop state DOWN mode DEFAULT group default qlen 10 link/can promiscuity 0 minmtu 0 maxmtu 0 can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0 bitrate 1000000 sample-point 0.750 tq 12 prop-seg 29 phase-seg1 30phase-seg2 20 sjw 1 brp 1 ES582.1/ES584.1: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1 dbitrate 8000000 dsample-point 0.700 dtq 12 dprop-seg 3 dphase-seg1 3 dphase-seg2 3 dsjw 1 dbrp 1 tdcv 0 tdco 7 tdcf 8 ES582.1/ES584.1: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 brp_inc 1 tdcv_max 0 tdco_max 127 tdcf_max 127 clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 $ ip --details --json --pretty link show can0 [ { "ifindex": 1, "ifname": "can0", "flags": [ "NOARP","ECHO" ], "mtu": 72, "qdisc": "noop", "operstate": "DOWN", "linkmode": "DEFAULT", "group": "default", "txqlen": 10, "link_type": "can", "promiscuity": 0, "min_mtu": 0, "max_mtu": 0, "linkinfo": { "info_kind": "can", "info_data": { "ctrlmode": [ "FD" ], "state": "STOPPED", "berr_counter": { "tx": 0, "rx": 0 }, "restart_ms": 0, "bittiming": { "bitrate": 1000000, "sample_point": "0.750", "tq": 12, "prop_seg": 29, "phase_seg1": 30, "phase_seg2": 20, "sjw": 1, "brp": 1 }, "bittiming_const": { "name": "ES582.1/ES584.1", "tseg1": { "min": 2, "max": 256 }, "tseg2": { "min": 2, "max": 128 }, "sjw": { "min": 1, "max": 128 }, "brp": { "min": 1, "max": 512 }, "brp_inc": 1 }, "data_bittiming": { "bitrate": 8000000, "sample_point": "0.700", "tq": 12, "prop_seg": 3, "phase_seg1": 3, "phase_seg2": 3, "sjw": 1, "brp": 1, "tdc": { "tdcv": 0, "tdco": 7, "tdcf": 8 } }, "data_bittiming_const": { "name": "ES582.1/ES584.1", "tseg1": { "min": 2, "max": 32 }, "tseg2": { "min": 1, "max": 16 }, "sjw": { "min": 1, "max": 8 }, "brp": { "min": 1, "max": 32 }, "brp_inc": 1, "tdc": { "tdcv_max": 0, "tdco_max": 127, "tdcf_max": 127 } }, "clock": 80000000 } }, "num_tx_queues": 1, "num_rx_queues": 1, "gso_max_size": 65536, "gso_max_segs": 65535 } ] Signed-off-by: Vincent Mailhol --- include/uapi/linux/can/netlink.h | 25 +++++++++-- ip/iplink_can.c | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h index 00c763df..d5cc2761 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -134,12 +134,31 @@ enum { IFLA_CAN_BITRATE_CONST, IFLA_CAN_DATA_BITRATE_CONST, IFLA_CAN_BITRATE_MAX, - __IFLA_CAN_MAX -}; + IFLA_CAN_TDC, -#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) + /* add new constants above here */ + __IFLA_CAN_MAX, + IFLA_CAN_MAX = __IFLA_CAN_MAX - 1 +}; /* u16 termination range: 1..65535 Ohms */ #define CAN_TERMINATION_DISABLED 0 +/* + * CAN FD Transmitter Delay Compensation (TDC) + */ +enum { + IFLA_CAN_TDC_UNSPEC, + IFLA_CAN_TDC_TDCV_MAX, /* u32 */ + IFLA_CAN_TDC_TDCO_MAX, /* u32 */ + IFLA_CAN_TDC_TDCF_MAX, /* u32 */ + IFLA_CAN_TDC_TDCV, /* u32 */ + IFLA_CAN_TDC_TDCO, /* u32 */ + IFLA_CAN_TDC_TDCF, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_TDC, + IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 +}; + #endif /* !_UAPI_CAN_NETLINK_H */ diff --git a/ip/iplink_can.c b/ip/iplink_can.c index 311c097d..ea049999 100644 --- a/ip/iplink_can.c +++ b/ip/iplink_can.c @@ -28,6 +28,7 @@ static void print_usage(FILE *f) "\n" "\t[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |\n" "\t[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]\n" + "\t[ tdcv TDCV tdco TDCO tdcf TDCF ]\n" "\n" "\t[ loopback { on | off } ]\n" "\t[ listen-only { on | off } ]\n" @@ -51,6 +52,9 @@ static void print_usage(FILE *f) "\t PHASE-SEG1 := { NUMBER }\n" "\t PHASE-SEG2 := { NUMBER }\n" "\t SJW := { NUMBER }\n" + "\t TDCV := { 0 | NUMBER }\n" + "\t TDCO := { 0 | NUMBER }\n" + "\t TDCF := { NUMBER }\n" "\t RESTART-MS := { 0 | NUMBER }\n" ); } @@ -116,6 +120,8 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, { struct can_bittiming bt = {}, dbt = {}; struct can_ctrlmode cm = {0, 0}; + struct rtattr *tdc; + __u32 tdcv = -1, tdco = -1, tdcf = -1; while (argc > 0) { if (matches(*argv, "bitrate") == 0) { @@ -181,6 +187,18 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); if (get_u32(&dbt.sjw, *argv, 0)) invarg("invalid \"dsjw\" value\n", *argv); + } else if (matches(*argv, "tdcv") == 0) { + NEXT_ARG(); + if (get_u32(&tdcv, *argv, 0)) + invarg("invalid \"tdcv\" value\n", *argv); + } else if (matches(*argv, "tdco") == 0) { + NEXT_ARG(); + if (get_u32(&tdco, *argv, 0)) + invarg("invalid \"tdco\" value\n", *argv); + } else if (matches(*argv, "tdcf") == 0) { + NEXT_ARG(); + if (get_u32(&tdcf, *argv, 0)) + invarg("invalid \"tdcf\" value\n", *argv); } else if (matches(*argv, "loopback") == 0) { NEXT_ARG(); set_ctrlmode("loopback", *argv, &cm, @@ -254,6 +272,17 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv, if (cm.mask) addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); + if (tdcv != -1 || tdco != -1 || tdcf != -1) { + tdc = addattr_nest(n, 1024, IFLA_CAN_TDC | NLA_F_NESTED); + if (tdcv != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCV, tdcv); + if (tdco != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCO, tdco); + if (tdcf != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCF, tdcf); + addattr_nest_end(n, tdc); + } + return 0; } @@ -294,6 +323,46 @@ static void can_print_data_timing_min_max(const char *attr, int min, int max) can_print_timing_min_max(attr, min, max); } +static void can_print_tdc_opt(FILE *f, struct rtattr *tdc_attr) +{ + struct rtattr *tb[IFLA_CAN_TDC_MAX + 1]; + + parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); + if (tb[IFLA_CAN_TDC_TDCV] && tb[IFLA_CAN_TDC_TDCO] && + tb[IFLA_CAN_TDC_TDCF]) { + __u32 *tdcv = RTA_DATA(tb[IFLA_CAN_TDC_TDCV]); + __u32 *tdco = RTA_DATA(tb[IFLA_CAN_TDC_TDCO]); + __u32 *tdcf = RTA_DATA(tb[IFLA_CAN_TDC_TDCF]); + + open_json_object("tdc"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv); + print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco); + print_uint(PRINT_ANY, "tdcf", " tdcf %u", *tdcf); + close_json_object(); + } +} + +static void can_print_tdc_const_opt(FILE *f, struct rtattr *tdc_attr) +{ + struct rtattr *tb[IFLA_CAN_TDC_MAX + 1]; + + parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); + if (tb[IFLA_CAN_TDC_TDCV_MAX] && tb[IFLA_CAN_TDC_TDCO_MAX] && + tb[IFLA_CAN_TDC_TDCF_MAX]) { + __u32 *tdcv_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MAX]); + __u32 *tdco_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MAX]); + __u32 *tdcf_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MAX]); + + open_json_object("tdc"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tdcv_max", " tdcv_max %u", *tdcv_max); + print_uint(PRINT_ANY, "tdco_max", " tdco_max %u", *tdco_max); + print_uint(PRINT_ANY, "tdcf_max", " tdcf_max %u", *tdcf_max); + close_json_object(); + } +} + static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { if (!tb) @@ -425,6 +494,10 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) dbt->phase_seg2); print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw); print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp); + + if (tb[IFLA_CAN_TDC]) + can_print_tdc_opt(f, tb[IFLA_CAN_TDC]); + close_json_object(); } @@ -445,6 +518,10 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) can_print_data_timing_min_max("brp", dbtc->brp_min, dbtc->brp_max); print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", dbtc->brp_inc); + + if (tb[IFLA_CAN_TDC]) + can_print_tdc_const_opt(f, tb[IFLA_CAN_TDC]); + close_json_object(); }