diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2011-10-27 14:17:59 +0100 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2012-06-02 01:31:10 +0100 |
commit | 5bebf1ee71990a00fb7973702e3ed19b3fa71027 (patch) | |
tree | cd0bd6148b9b486df12ffc0248dd757e87bd4a31 /ethtool.c | |
parent | e5c984ac501788d668e8aed1f7b1fd79ce1d93c5 (diff) | |
download | ethtool-5bebf1ee71990a00fb7973702e3ed19b3fa71027.tar.gz |
Report when offload feature changes are not exactly as requested
When an offload feature is enabled or disabled, this can change the
state of other features that depend on it, or may itself be deferred
if it depends on a feature that is disabled. Report when this
happens, and fail if no offload features could be changed.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'ethtool.c')
-rw-r--r-- | ethtool.c | 65 |
1 files changed, 45 insertions, 20 deletions
@@ -1069,13 +1069,15 @@ static int dump_coalesce(const struct ethtool_coalesce *ecoal) return 0; } -static int dump_offload(u32 active) +static int dump_offload(u32 active, u32 mask) { u32 value; int i; for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) { value = off_flag_def[i].value; + if (!(mask & value)) + continue; printf("%s: %s\n", off_flag_def[i].long_name, (active & value) ? "on" : "off"); @@ -1647,17 +1649,14 @@ static int do_scoalesce(struct cmd_context *ctx) return 0; } -static int do_goffload(struct cmd_context *ctx) +static int get_offload(struct cmd_context *ctx, u32 *flags) { struct ethtool_value eval; int err, allfail = 1; - u32 flags = 0, value; + u32 value; int i; - if (ctx->argc != 0) - exit_bad_args(); - - fprintf(stdout, "Offload parameters for %s:\n", ctx->devname); + *flags = 0; for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) { value = off_flag_def[i].value; @@ -1671,7 +1670,7 @@ static int do_goffload(struct cmd_context *ctx) off_flag_def[i].long_name); } else { if (eval.data) - flags |= value; + *flags |= value; allfail = 0; } } @@ -1681,16 +1680,28 @@ static int do_goffload(struct cmd_context *ctx) if (err) { perror("Cannot get device flags"); } else { - flags |= eval.data & ETH_FLAG_EXT_MASK; + *flags |= eval.data & ETH_FLAG_EXT_MASK; allfail = 0; } - if (allfail) { + return allfail; +} + +static int do_goffload(struct cmd_context *ctx) +{ + u32 flags; + + if (ctx->argc != 0) + exit_bad_args(); + + fprintf(stdout, "Offload parameters for %s:\n", ctx->devname); + + if (get_offload(ctx, &flags)) { fprintf(stdout, "no offload info available\n"); return 83; } - return dump_offload(flags); + return dump_offload(flags, ~(u32)0); } static int do_soffload(struct cmd_context *ctx) @@ -1699,6 +1710,7 @@ static int do_soffload(struct cmd_context *ctx) u32 off_flags_wanted = 0; u32 off_flags_mask = 0; struct cmdline_info cmdline_offload[ARRAY_SIZE(off_flag_def)]; + u32 old_flags, new_flags, diff; struct ethtool_value eval; int err; int i; @@ -1712,6 +1724,11 @@ static int do_soffload(struct cmd_context *ctx) parse_generic_cmdline(ctx, &goffload_changed, cmdline_offload, ARRAY_SIZE(cmdline_offload)); + if (get_offload(ctx, &old_flags)) { + fprintf(stderr, "no offload info available\n"); + return 1; + } + for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) { if (!off_flag_def[i].set_cmd) continue; @@ -1729,16 +1746,8 @@ static int do_soffload(struct cmd_context *ctx) } } if (off_flags_mask & ETH_FLAG_EXT_MASK) { - eval.cmd = ETHTOOL_GFLAGS; - eval.data = 0; - err = send_ioctl(ctx, &eval); - if (err) { - perror("Cannot get device flag settings"); - return 91; - } - eval.cmd = ETHTOOL_SFLAGS; - eval.data &= ~(off_flags_mask & ETH_FLAG_EXT_MASK); + eval.data = old_flags & ~off_flags_mask & ETH_FLAG_EXT_MASK; eval.data |= off_flags_wanted & ETH_FLAG_EXT_MASK; err = send_ioctl(ctx, &eval); @@ -1750,6 +1759,22 @@ static int do_soffload(struct cmd_context *ctx) if (off_flags_mask == 0) { fprintf(stdout, "no offload settings changed\n"); + return 0; + } + + /* Compare new state with requested state */ + if (get_offload(ctx, &new_flags)) { + fprintf(stderr, "no offload info available\n"); + return 1; + } + if (new_flags != ((old_flags & ~off_flags_mask) | off_flags_wanted)) { + if (new_flags == old_flags) { + fprintf(stderr, + "Could not change any device offload settings\n"); + return 1; + } + printf("Actual changes:\n"); + dump_offload(new_flags, new_flags ^ old_flags); } return 0; |