|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | +#include "nvme.h" |
| 3 | +#include "plugin.h" |
| 4 | +#include "nvme-print.h" |
| 5 | + |
| 6 | +#define CREATE_CMD |
| 7 | +#include "feat-nvme.h" |
| 8 | + |
| 9 | +static const char *power_mgmt_feat = "power management feature"; |
| 10 | +static const char *sel = "[0-3]: current/default/saved/supported"; |
| 11 | +static const char *save = "Specifies that the controller shall save the attribute"; |
| 12 | + |
| 13 | +static int power_mgmt_get(struct nvme_dev *dev, const __u8 fid, __u8 sel) |
| 14 | +{ |
| 15 | + __u32 result; |
| 16 | + int err; |
| 17 | + |
| 18 | + struct nvme_get_features_args args = { |
| 19 | + .args_size = sizeof(args), |
| 20 | + .fd = dev_fd(dev), |
| 21 | + .fid = fid, |
| 22 | + .sel = sel, |
| 23 | + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, |
| 24 | + .result = &result, |
| 25 | + }; |
| 26 | + |
| 27 | + err = nvme_get_features(&args); |
| 28 | + if (!err) { |
| 29 | + if (NVME_CHECK(sel, GET_FEATURES_SEL, SUPPORTED)) |
| 30 | + nvme_show_select_result(fid, result); |
| 31 | + else |
| 32 | + nvme_feature_show_fields(fid, result, NULL); |
| 33 | + } else { |
| 34 | + nvme_show_error("Get %s", power_mgmt_feat); |
| 35 | + } |
| 36 | + |
| 37 | + return err; |
| 38 | +} |
| 39 | + |
| 40 | +static int power_mgmt_set(struct nvme_dev *dev, const __u8 fid, __u8 ps, __u8 wh, bool save) |
| 41 | +{ |
| 42 | + __u32 result; |
| 43 | + int err; |
| 44 | + |
| 45 | + struct nvme_set_features_args args = { |
| 46 | + .args_size = sizeof(args), |
| 47 | + .fd = dev_fd(dev), |
| 48 | + .fid = fid, |
| 49 | + .cdw11 = NVME_SET(ps, FEAT_PWRMGMT_PS) | NVME_SET(wh, FEAT_PWRMGMT_WH), |
| 50 | + .save = save, |
| 51 | + .timeout = NVME_DEFAULT_IOCTL_TIMEOUT, |
| 52 | + .result = &result, |
| 53 | + }; |
| 54 | + |
| 55 | + err = nvme_set_features(&args); |
| 56 | + |
| 57 | + nvme_show_init(); |
| 58 | + |
| 59 | + if (err > 0) { |
| 60 | + nvme_show_status(err); |
| 61 | + } else if (err < 0) { |
| 62 | + nvme_show_perror("Set %s", power_mgmt_feat); |
| 63 | + } else { |
| 64 | + nvme_show_result("Set %s: 0x%04x (%s)", power_mgmt_feat, args.cdw11, |
| 65 | + save ? "Save" : "Not save"); |
| 66 | + nvme_feature_show_fields(fid, args.cdw11, NULL); |
| 67 | + } |
| 68 | + |
| 69 | + nvme_show_finish(); |
| 70 | + |
| 71 | + return err; |
| 72 | +} |
| 73 | + |
| 74 | +static int feat_power_mgmt(int argc, char **argv, struct command *cmd, struct plugin *plugin) |
| 75 | +{ |
| 76 | + const char *ps = "power state"; |
| 77 | + const char *wh = "workload hint"; |
| 78 | + const __u8 fid = NVME_FEAT_FID_POWER_MGMT; |
| 79 | + |
| 80 | + _cleanup_nvme_dev_ struct nvme_dev *dev = NULL; |
| 81 | + int err; |
| 82 | + |
| 83 | + struct config { |
| 84 | + __u8 ps; |
| 85 | + __u8 wh; |
| 86 | + bool save; |
| 87 | + __u8 sel; |
| 88 | + }; |
| 89 | + |
| 90 | + struct config cfg = { 0 }; |
| 91 | + |
| 92 | + NVME_ARGS(opts, |
| 93 | + OPT_BYTE("ps", 'p', &cfg.ps, ps), |
| 94 | + OPT_BYTE("wh", 'w', &cfg.wh, wh), |
| 95 | + OPT_FLAG("save", 's', &cfg.save, save), |
| 96 | + OPT_BYTE("sel", 'S', &cfg.sel, sel)); |
| 97 | + |
| 98 | + err = parse_and_open(&dev, argc, argv, POWER_MGMT_DESC, opts); |
| 99 | + if (err) |
| 100 | + return err; |
| 101 | + |
| 102 | + if (argconfig_parse_seen(opts, "ps")) |
| 103 | + err = power_mgmt_set(dev, fid, cfg.ps, cfg.wh, cfg.save); |
| 104 | + else |
| 105 | + err = power_mgmt_get(dev, fid, cfg.sel); |
| 106 | + |
| 107 | + return err; |
| 108 | +} |
0 commit comments