Message ID | 20230711071019.7151-3-jehoon.park@samsung.com |
---|---|
State | Superseded |
Headers | show |
Series | add support for Set Alert Configuration mailbox command | expand |
Hi Jehoon, Thanks for adding this. A few minor comments below, otherwise these look good. On Tue, 2023-07-11 at 16:10 +0900, Jehoon Park wrote: > Add a new command: 'set-alert-config', which configures device's warning alert > > usage: cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>] > > -v, --verbose turn on debug > -S, --serial use serial numbers to id memdevs > -L, --life-used-threshold <threshold> > threshold value for life used warning alert > --life-used-alert <'on' or 'off'> > enable or disable life used warning alert > -O, --over-temperature-threshold <threshold> > threshold value for device over temperature warning alert > --over-temperature-alert <'on' or 'off'> > enable or disable device over temperature warning alert > -U, --under-temperature-threshold <threshold> > threshold value for device under temperature warning alert > --under-temperature-alert <'on' or 'off'> > enable or disable device under temperature warning alert > -V, --volatile-mem-err-threshold <threshold> > threshold value for corrected volatile mem error warning alert > --volatile-mem-err-alert <'on' or 'off'> > enable or disable corrected volatile mem error warning alert > -P, --pmem-err-threshold <threshold> > threshold value for corrected pmem error warning alert > --pmem-err-alert <'on' or 'off'> > enable or disable corrected pmem error warning alert No need to include the full usage text in the commit message - this is available in the man page. Just mention and describe what functionality is being added. > > Signed-off-by: Jehoon Park <jehoon.park@samsung.com> > --- > Documentation/cxl/cxl-set-alert-config.txt | 96 +++++++++ > Documentation/cxl/meson.build | 1 + > cxl/builtin.h | 1 + > cxl/cxl.c | 1 + > cxl/memdev.c | 219 ++++++++++++++++++++- > 5 files changed, 317 insertions(+), 1 deletion(-) > create mode 100644 Documentation/cxl/cxl-set-alert-config.txt > > diff --git a/Documentation/cxl/cxl-set-alert-config.txt b/Documentation/cxl/cxl-set-alert-config.txt > new file mode 100644 > index 0000000..a291c09 > --- /dev/null > +++ b/Documentation/cxl/cxl-set-alert-config.txt > @@ -0,0 +1,96 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +cxl-set-alert-config(1) > +======================= > + > +NAME > +---- > +cxl-set-alert-config - set the warning alert threshold on a CXL memdev > + > +SYNOPSIS > +-------- > +[verse] > +'cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]' > + > +DESCRIPTION > +----------- > +CXL device raises an alert when its health status is changed. Critical alert > +shall automatically be configured by the device after a device reset. > +If supported, programmable warning thresholds also be initialized to vendor > +recommended defaults, then could be configured by the host. s/host/user/ ? > <snip> > > +static int validate_alert_threshold(enum cxl_setalert_event event, > + int threshold) > +{ > + if (event == CXL_SETALERT_LIFE_USED) { > + if (threshold < 0 || threshold > 100) { > + log_err(&ml, "Invalid life used threshold: %d\n", > + threshold); > + return -EINVAL; > + } > + } else if (event == CXL_SETALERT_OVER_TEMP || > + event == CXL_SETALERT_UNDER_TEMP) { > + if (threshold < SHRT_MIN || threshold > SHRT_MAX) { > + log_err(&ml, > + "Invalid device temperature threshold: %d\n", > + threshold); > + return -EINVAL; > + } > + } else { > + if (threshold < 0 || threshold > USHRT_MAX) { > + log_err(&ml, > + "Invalid corrected mem error threshold: %d\n", > + threshold); > + return -EINVAL; > + } > + } > + return 0; > +} > + > +#define alert_param_set_threshold(arg, alert_event) \ > +{ \ > + if (!param.arg##_alert) { \ > + if (param.arg##_threshold) { \ > + log_err(&ml, "Action not specified\n"); \ > + return -EINVAL; \ > + } \ > + } else if (strncmp(param.arg##_alert, "on", 2) == 0) { \ I see that ndctl-inject-smart also does strncmp, but I'm wondering if we should be a little more strict and use strcmp instead. The option parser won't give us strings that are not nul-terminated, so it should be safe, and it will avoid something awkward like "--some-alert=onward". Ideally we probably want a helper similar to the kernel's kstrtobool(), which would handle all of {on,true,1,t} and different capitalization as well, but that can be a follow on patch. > + if (param.arg##_threshold) { \ > + char *endptr; \ > + alertctx.arg##_threshold = \ > + strtol(param.arg##_threshold, &endptr, 10); \ > + if (endptr[0] != '\0') { \ > + log_err(&ml, "Invalid threshold: %s\n", \ > + param.arg##_threshold); \ > + return -EINVAL; \ > + } \ > + rc = validate_alert_threshold( \ > + alert_event, alertctx.arg##_threshold); \ > + if (rc != 0) \ > + return rc; \ > + alertctx.valid_alert_actions |= 1 << alert_event; \ > + alertctx.enable_alert_actions |= 1 << alert_event; \ > + } else { \ > + log_err(&ml, "Threshold not specified\n"); \ > + return -EINVAL; \ > + } \ > + } else if (strncmp(param.arg##_alert, "off", 3) == 0) { \ > + if (!param.arg##_threshold) { \ > + alertctx.valid_alert_actions |= 1 << alert_event; \ > + alertctx.enable_alert_actions &= ~(1 << alert_event); \ > + } else { \ > + log_err(&ml, "Disable not require threshold\n"); \ > + return -EINVAL; \ > + } \ > + } else { \ > + log_err(&ml, "Invalid action: %s\n", param.arg##_alert); \ > + return -EINVAL; \ > + } \ > +} > + > <snip> > +int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx) > +{ > + int count = memdev_action( > + argc, argv, ctx, action_set_alert_config, set_alert_options, > + "cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]"); > + log_info(&ml, "set alert configuration %d mem%s\n", Maybe "set alert configuration for %d ..." > + count >= 0 ? count : 0, count > 1 ? "s" : ""); > + > + return count >= 0 ? 0 : EXIT_FAILURE; > +}
On Mon, Jul 24, 2023 at 10:07:47PM +0000, Verma, Vishal L wrote: > Hi Jehoon, > > Thanks for adding this. A few minor comments below, otherwise these > look good. > Hi, Vishal. Thank you for comments. I agree with all of them, especially the use of strcmp. I missed the awkward case you mentioned. I'll send v2 patch soon with applying those comments. Jehoon > On Tue, 2023-07-11 at 16:10 +0900, Jehoon Park wrote: > > Add a new command: 'set-alert-config', which configures device's warning alert > > > > usage: cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>] > > > > -v, --verbose turn on debug > > -S, --serial use serial numbers to id memdevs > > -L, --life-used-threshold <threshold> > > threshold value for life used warning alert > > --life-used-alert <'on' or 'off'> > > enable or disable life used warning alert > > -O, --over-temperature-threshold <threshold> > > threshold value for device over temperature warning alert > > --over-temperature-alert <'on' or 'off'> > > enable or disable device over temperature warning alert > > -U, --under-temperature-threshold <threshold> > > threshold value for device under temperature warning alert > > --under-temperature-alert <'on' or 'off'> > > enable or disable device under temperature warning alert > > -V, --volatile-mem-err-threshold <threshold> > > threshold value for corrected volatile mem error warning alert > > --volatile-mem-err-alert <'on' or 'off'> > > enable or disable corrected volatile mem error warning alert > > -P, --pmem-err-threshold <threshold> > > threshold value for corrected pmem error warning alert > > --pmem-err-alert <'on' or 'off'> > > enable or disable corrected pmem error warning alert > > No need to include the full usage text in the commit message - this is > available in the man page. Just mention and describe what functionality > is being added. > > > > > Signed-off-by: Jehoon Park <jehoon.park@samsung.com> > > --- > > Documentation/cxl/cxl-set-alert-config.txt | 96 +++++++++ > > Documentation/cxl/meson.build | 1 + > > cxl/builtin.h | 1 + > > cxl/cxl.c | 1 + > > cxl/memdev.c | 219 ++++++++++++++++++++- > > 5 files changed, 317 insertions(+), 1 deletion(-) > > create mode 100644 Documentation/cxl/cxl-set-alert-config.txt > > > > diff --git a/Documentation/cxl/cxl-set-alert-config.txt b/Documentation/cxl/cxl-set-alert-config.txt > > new file mode 100644 > > index 0000000..a291c09 > > --- /dev/null > > +++ b/Documentation/cxl/cxl-set-alert-config.txt > > @@ -0,0 +1,96 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +cxl-set-alert-config(1) > > +======================= > > + > > +NAME > > +---- > > +cxl-set-alert-config - set the warning alert threshold on a CXL memdev > > + > > +SYNOPSIS > > +-------- > > +[verse] > > +'cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]' > > + > > +DESCRIPTION > > +----------- > > +CXL device raises an alert when its health status is changed. Critical alert > > +shall automatically be configured by the device after a device reset. > > +If supported, programmable warning thresholds also be initialized to vendor > > +recommended defaults, then could be configured by the host. > > s/host/user/ ? > > > > <snip> > > > > +static int validate_alert_threshold(enum cxl_setalert_event event, > > + int threshold) > > +{ > > + if (event == CXL_SETALERT_LIFE_USED) { > > + if (threshold < 0 || threshold > 100) { > > + log_err(&ml, "Invalid life used threshold: %d\n", > > + threshold); > > + return -EINVAL; > > + } > > + } else if (event == CXL_SETALERT_OVER_TEMP || > > + event == CXL_SETALERT_UNDER_TEMP) { > > + if (threshold < SHRT_MIN || threshold > SHRT_MAX) { > > + log_err(&ml, > > + "Invalid device temperature threshold: %d\n", > > + threshold); > > + return -EINVAL; > > + } > > + } else { > > + if (threshold < 0 || threshold > USHRT_MAX) { > > + log_err(&ml, > > + "Invalid corrected mem error threshold: %d\n", > > + threshold); > > + return -EINVAL; > > + } > > + } > > + return 0; > > +} > > + > > +#define alert_param_set_threshold(arg, alert_event) \ > > +{ \ > > + if (!param.arg##_alert) { \ > > + if (param.arg##_threshold) { \ > > + log_err(&ml, "Action not specified\n"); \ > > + return -EINVAL; \ > > + } \ > > + } else if (strncmp(param.arg##_alert, "on", 2) == 0) { \ > > I see that ndctl-inject-smart also does strncmp, but I'm wondering if > we should be a little more strict and use strcmp instead. > > The option parser won't give us strings that are not nul-terminated, so > it should be safe, and it will avoid something awkward like > "--some-alert=onward". > > Ideally we probably want a helper similar to the kernel's kstrtobool(), > which would handle all of {on,true,1,t} and different capitalization as > well, but that can be a follow on patch. > > > + if (param.arg##_threshold) { \ > > + char *endptr; \ > > + alertctx.arg##_threshold = \ > > + strtol(param.arg##_threshold, &endptr, 10); \ > > + if (endptr[0] != '\0') { \ > > + log_err(&ml, "Invalid threshold: %s\n", \ > > + param.arg##_threshold); \ > > + return -EINVAL; \ > > + } \ > > + rc = validate_alert_threshold( \ > > + alert_event, alertctx.arg##_threshold); \ > > + if (rc != 0) \ > > + return rc; \ > > + alertctx.valid_alert_actions |= 1 << alert_event; \ > > + alertctx.enable_alert_actions |= 1 << alert_event; \ > > + } else { \ > > + log_err(&ml, "Threshold not specified\n"); \ > > + return -EINVAL; \ > > + } \ > > + } else if (strncmp(param.arg##_alert, "off", 3) == 0) { \ > > + if (!param.arg##_threshold) { \ > > + alertctx.valid_alert_actions |= 1 << alert_event; \ > > + alertctx.enable_alert_actions &= ~(1 << alert_event); \ > > + } else { \ > > + log_err(&ml, "Disable not require threshold\n"); \ > > + return -EINVAL; \ > > + } \ > > + } else { \ > > + log_err(&ml, "Invalid action: %s\n", param.arg##_alert); \ > > + return -EINVAL; \ > > + } \ > > +} > > + > > > > <snip> > > > +int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx) > > +{ > > + int count = memdev_action( > > + argc, argv, ctx, action_set_alert_config, set_alert_options, > > + "cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]"); > > + log_info(&ml, "set alert configuration %d mem%s\n", > > Maybe "set alert configuration for %d ..." > > > + count >= 0 ? count : 0, count > 1 ? "s" : ""); > > + > > + return count >= 0 ? 0 : EXIT_FAILURE; > > +} >
diff --git a/Documentation/cxl/cxl-set-alert-config.txt b/Documentation/cxl/cxl-set-alert-config.txt new file mode 100644 index 0000000..a291c09 --- /dev/null +++ b/Documentation/cxl/cxl-set-alert-config.txt @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 + +cxl-set-alert-config(1) +======================= + +NAME +---- +cxl-set-alert-config - set the warning alert threshold on a CXL memdev + +SYNOPSIS +-------- +[verse] +'cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]' + +DESCRIPTION +----------- +CXL device raises an alert when its health status is changed. Critical alert +shall automatically be configured by the device after a device reset. +If supported, programmable warning thresholds also be initialized to vendor +recommended defaults, then could be configured by the host. + +Use this command to configure warning alert thresholds of a device. +Having issued this command, the newly requested warning thresholds would +override the previously programmed warning thresholds. + +To enable warning alert, set both 'threshold=value' and 'alert=on'. To disable +warning alert, set only 'alert=off'. Other cases would cause errors. + +Use "cxl list -m <memdev> -A" to examine the programming warning threshold +capabilities of a device. + +EXAMPLES +-------- +Set warning threshold to 30 and enable alert for life used. +[verse] +cxl set-alert-config mem0 -L 30 --life-used-alert=on + +Disable warning alert for device over temperature. +[verse] +cxl set-alert-config mem0 --over-temperature-alert=off + +OPTIONS +------- +<memory device(s)>:: +include::memdev-option.txt[] + +-v:: +--verbose=:: + Turn on verbose debug messages in the library (if libcxl was built with + logging and debug enabled). + +-L:: +--life-used-threshold=:: + Set <value> for the life used warning alert threshold. + +--life-used-alert=:: + Enable or disable the life used warning alert. + Options are 'on' or 'off'. + +-O:: +--over-temperature-threshold=:: + Set <value> for the device over temperature warning alert threshold. + +--over-temperature-alert=:: + Enable or disable the device over temperature warning alert. + Options are 'on' or 'off'. + +-U:: +--under-temperature-threshold=:: + Set <value> for the device under temperature warning alert threshold. + +--under-temperature-alert=:: + Enable or disable the device under temperature warning alert. + Options are 'on' or 'off'. + +-V:: +--volatile-mem-err-threshold=:: + Set <value> for the corrected volatile memory error warning alert + threshold. + +--volatile-mem-err-alert=:: + Enable or disable the corrected volatile memory error warning alert. + Options are 'on' or 'off'. + +-P:: +--pmem-err-threshold=:: + Set <value> for the corrected persistent memory error warning alert + threshold. + +--pmem-err-alert=:: + Enable or disable the corrected persistent memory error warning alert. + Options are 'on' or 'off'. + +SEE ALSO +-------- +CXL-3.0 8.2.9.8.3.3 diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build index a6d77ab..3ea412d 100644 --- a/Documentation/cxl/meson.build +++ b/Documentation/cxl/meson.build @@ -46,6 +46,7 @@ cxl_manpages = [ 'cxl-enable-region.txt', 'cxl-destroy-region.txt', 'cxl-monitor.txt', + 'cxl-set-alert-config.txt', ] foreach man : cxl_manpages diff --git a/cxl/builtin.h b/cxl/builtin.h index 9baa43b..7b2274c 100644 --- a/cxl/builtin.h +++ b/cxl/builtin.h @@ -32,4 +32,5 @@ static inline int cmd_monitor(int argc, const char **argv, struct cxl_ctx *ctx) return EXIT_FAILURE; } #endif +int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx); #endif /* _CXL_BUILTIN_H_ */ diff --git a/cxl/cxl.c b/cxl/cxl.c index 3be7026..15eb1e6 100644 --- a/cxl/cxl.c +++ b/cxl/cxl.c @@ -77,6 +77,7 @@ static struct cmd_struct commands[] = { { "disable-region", .c_fn = cmd_disable_region }, { "destroy-region", .c_fn = cmd_destroy_region }, { "monitor", .c_fn = cmd_monitor }, + { "set-alert-config", .c_fn = cmd_set_alert_config }, }; int main(int argc, const char **argv) diff --git a/cxl/memdev.c b/cxl/memdev.c index 0b3ad02..2587189 100644 --- a/cxl/memdev.c +++ b/cxl/memdev.c @@ -34,10 +34,38 @@ static struct parameters { const char *type; const char *size; const char *decoder_filter; + const char *life_used_threshold; + const char *dev_over_temperature_threshold; + const char *dev_under_temperature_threshold; + const char *corrected_volatile_mem_err_threshold; + const char *corrected_pmem_err_threshold; + const char *life_used_alert; + const char *dev_over_temperature_alert; + const char *dev_under_temperature_alert; + const char *corrected_volatile_mem_err_alert; + const char *corrected_pmem_err_alert; } param; static struct log_ctx ml; +struct alert_context { + int valid_alert_actions; + int enable_alert_actions; + int life_used_threshold; + int dev_over_temperature_threshold; + int dev_under_temperature_threshold; + int corrected_volatile_mem_err_threshold; + int corrected_pmem_err_threshold; +}; + +enum cxl_setalert_event { + CXL_SETALERT_LIFE_USED, + CXL_SETALERT_OVER_TEMP, + CXL_SETALERT_UNDER_TEMP, + CXL_SETALERT_VOLATILE_MEM_ERROR, + CXL_SETALERT_PMEM_ERROR, +}; + enum cxl_setpart_type { CXL_SETPART_PMEM, CXL_SETPART_VOLATILE, @@ -85,6 +113,36 @@ OPT_STRING('t', "type", ¶m.type, "type", \ OPT_BOOLEAN('f', "force", ¶m.force, \ "Attempt 'expected to fail' operations") +#define SET_ALERT_OPTIONS() \ +OPT_STRING('L', "life-used-threshold", ¶m.life_used_threshold, \ + "threshold", "threshold value for life used warning alert"), \ +OPT_STRING('\0', "life-used-alert", ¶m.life_used_alert, \ + "'on' or 'off'", "enable or disable life used warning alert"), \ +OPT_STRING('O', "over-temperature-threshold", \ + ¶m.dev_over_temperature_threshold, "threshold", \ + "threshold value for device over temperature warning alert"), \ +OPT_STRING('\0', "over-temperature-alert", \ + ¶m.dev_over_temperature_alert, "'on' or 'off'", \ + "enable or disable device over temperature warning alert"), \ +OPT_STRING('U', "under-temperature-threshold", \ + ¶m.dev_under_temperature_threshold, "threshold", \ + "threshold value for device under temperature warning alert"), \ +OPT_STRING('\0', "under-temperature-alert", \ + ¶m.dev_under_temperature_alert, "'on' or 'off'", \ + "enable or disable device under temperature warning alert"), \ +OPT_STRING('V', "volatile-mem-err-threshold", \ + ¶m.corrected_volatile_mem_err_threshold, "threshold", \ + "threshold value for corrected volatile mem error warning alert"), \ +OPT_STRING('\0', "volatile-mem-err-alert", \ + ¶m.corrected_volatile_mem_err_alert, "'on' or 'off'", \ + "enable or disable corrected volatile mem error warning alert"), \ +OPT_STRING('P', "pmem-err-threshold", \ + ¶m.corrected_pmem_err_threshold, "threshold", \ + "threshold value for corrected pmem error warning alert"), \ +OPT_STRING('\0', "pmem-err-alert", \ + ¶m.corrected_pmem_err_alert, "'on' or 'off'", \ + "enable or disable corrected pmem error warning alert") + static const struct option read_options[] = { BASE_OPTIONS(), LABEL_OPTIONS(), @@ -135,6 +193,12 @@ static const struct option free_dpa_options[] = { OPT_END(), }; +static const struct option set_alert_options[] = { + BASE_OPTIONS(), + SET_ALERT_OPTIONS(), + OPT_END(), +}; + enum reserve_dpa_mode { DPA_ALLOC, DPA_FREE, @@ -653,6 +717,148 @@ out_err: return rc; } +static int validate_alert_threshold(enum cxl_setalert_event event, + int threshold) +{ + if (event == CXL_SETALERT_LIFE_USED) { + if (threshold < 0 || threshold > 100) { + log_err(&ml, "Invalid life used threshold: %d\n", + threshold); + return -EINVAL; + } + } else if (event == CXL_SETALERT_OVER_TEMP || + event == CXL_SETALERT_UNDER_TEMP) { + if (threshold < SHRT_MIN || threshold > SHRT_MAX) { + log_err(&ml, + "Invalid device temperature threshold: %d\n", + threshold); + return -EINVAL; + } + } else { + if (threshold < 0 || threshold > USHRT_MAX) { + log_err(&ml, + "Invalid corrected mem error threshold: %d\n", + threshold); + return -EINVAL; + } + } + return 0; +} + +#define alert_param_set_threshold(arg, alert_event) \ +{ \ + if (!param.arg##_alert) { \ + if (param.arg##_threshold) { \ + log_err(&ml, "Action not specified\n"); \ + return -EINVAL; \ + } \ + } else if (strncmp(param.arg##_alert, "on", 2) == 0) { \ + if (param.arg##_threshold) { \ + char *endptr; \ + alertctx.arg##_threshold = \ + strtol(param.arg##_threshold, &endptr, 10); \ + if (endptr[0] != '\0') { \ + log_err(&ml, "Invalid threshold: %s\n", \ + param.arg##_threshold); \ + return -EINVAL; \ + } \ + rc = validate_alert_threshold( \ + alert_event, alertctx.arg##_threshold); \ + if (rc != 0) \ + return rc; \ + alertctx.valid_alert_actions |= 1 << alert_event; \ + alertctx.enable_alert_actions |= 1 << alert_event; \ + } else { \ + log_err(&ml, "Threshold not specified\n"); \ + return -EINVAL; \ + } \ + } else if (strncmp(param.arg##_alert, "off", 3) == 0) { \ + if (!param.arg##_threshold) { \ + alertctx.valid_alert_actions |= 1 << alert_event; \ + alertctx.enable_alert_actions &= ~(1 << alert_event); \ + } else { \ + log_err(&ml, "Disable not require threshold\n"); \ + return -EINVAL; \ + } \ + } else { \ + log_err(&ml, "Invalid action: %s\n", param.arg##_alert); \ + return -EINVAL; \ + } \ +} + +#define setup_threshold_field(arg) \ +{ \ + if (param.arg##_threshold) \ + cxl_cmd_alert_config_set_##arg##_prog_warn_threshold( \ + cmd, alertctx.arg##_threshold); \ +} + +static int action_set_alert_config(struct cxl_memdev *memdev, + struct action_context *actx) +{ + const char *devname = cxl_memdev_get_devname(memdev); + struct cxl_cmd *cmd; + struct alert_context alertctx = { 0 }; + struct json_object *jmemdev; + unsigned long flags; + int rc = 0; + + alert_param_set_threshold(life_used, CXL_SETALERT_LIFE_USED) + alert_param_set_threshold(dev_over_temperature, CXL_SETALERT_OVER_TEMP) + alert_param_set_threshold(dev_under_temperature, + CXL_SETALERT_UNDER_TEMP) + alert_param_set_threshold(corrected_volatile_mem_err, + CXL_SETALERT_VOLATILE_MEM_ERROR) + alert_param_set_threshold(corrected_pmem_err, CXL_SETALERT_PMEM_ERROR) + if (alertctx.valid_alert_actions == 0) { + log_err(&ml, "No action specified\n"); + return -EINVAL; + } + + cmd = cxl_cmd_new_set_alert_config(memdev); + if (!cmd) { + rc = -ENXIO; + goto out_err; + } + + setup_threshold_field(life_used) + setup_threshold_field(dev_over_temperature) + setup_threshold_field(dev_under_temperature) + setup_threshold_field(corrected_volatile_mem_err) + setup_threshold_field(corrected_pmem_err) + cxl_cmd_alert_config_set_valid_alert_actions( + cmd, alertctx.valid_alert_actions); + cxl_cmd_alert_config_set_enable_alert_actions( + cmd, alertctx.enable_alert_actions); + + rc = cxl_cmd_submit(cmd); + if (rc < 0) { + log_err(&ml, "cmd submission failed: %s\n", strerror(-rc)); + goto out_cmd; + } + + rc = cxl_cmd_get_mbox_status(cmd); + if (rc != 0) { + log_err(&ml, "%s: mbox status: %d\n", __func__, rc); + rc = -ENXIO; + } + +out_cmd: + cxl_cmd_unref(cmd); +out_err: + if (rc) + log_err(&ml, "%s error: %s\n", devname, strerror(-rc)); + + flags = UTIL_JSON_ALERT_CONFIG; + if (actx->f_out == stdout && isatty(1)) + flags |= UTIL_JSON_HUMAN; + jmemdev = util_cxl_memdev_to_json(memdev, flags); + if (actx->jdevs && jmemdev) + json_object_array_add(actx->jdevs, jmemdev); + + return rc; +} + static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, int (*action)(struct cxl_memdev *memdev, struct action_context *actx), @@ -696,7 +902,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx, } if (action == action_setpartition || action == action_reserve_dpa || - action == action_free_dpa) + action == action_free_dpa || action == action_set_alert_config) actx.jdevs = json_object_new_array(); if (err == argc) { @@ -893,3 +1099,14 @@ int cmd_free_dpa(int argc, const char **argv, struct cxl_ctx *ctx) return count >= 0 ? 0 : EXIT_FAILURE; } + +int cmd_set_alert_config(int argc, const char **argv, struct cxl_ctx *ctx) +{ + int count = memdev_action( + argc, argv, ctx, action_set_alert_config, set_alert_options, + "cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>]"); + log_info(&ml, "set alert configuration %d mem%s\n", + count >= 0 ? count : 0, count > 1 ? "s" : ""); + + return count >= 0 ? 0 : EXIT_FAILURE; +}
Add a new command: 'set-alert-config', which configures device's warning alert usage: cxl set-alert-config <mem0> [<mem1>..<memN>] [<options>] -v, --verbose turn on debug -S, --serial use serial numbers to id memdevs -L, --life-used-threshold <threshold> threshold value for life used warning alert --life-used-alert <'on' or 'off'> enable or disable life used warning alert -O, --over-temperature-threshold <threshold> threshold value for device over temperature warning alert --over-temperature-alert <'on' or 'off'> enable or disable device over temperature warning alert -U, --under-temperature-threshold <threshold> threshold value for device under temperature warning alert --under-temperature-alert <'on' or 'off'> enable or disable device under temperature warning alert -V, --volatile-mem-err-threshold <threshold> threshold value for corrected volatile mem error warning alert --volatile-mem-err-alert <'on' or 'off'> enable or disable corrected volatile mem error warning alert -P, --pmem-err-threshold <threshold> threshold value for corrected pmem error warning alert --pmem-err-alert <'on' or 'off'> enable or disable corrected pmem error warning alert Signed-off-by: Jehoon Park <jehoon.park@samsung.com> --- Documentation/cxl/cxl-set-alert-config.txt | 96 +++++++++ Documentation/cxl/meson.build | 1 + cxl/builtin.h | 1 + cxl/cxl.c | 1 + cxl/memdev.c | 219 ++++++++++++++++++++- 5 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 Documentation/cxl/cxl-set-alert-config.txt