Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2018 Intel Corporation. All rights reserved. */
0003 #include <linux/libnvdimm.h>
0004 #include <linux/ndctl.h>
0005 #include <linux/acpi.h>
0006 #include <asm/smp.h>
0007 #include "intel.h"
0008 #include "nfit.h"
0009 
0010 static ssize_t firmware_activate_noidle_show(struct device *dev,
0011         struct device_attribute *attr, char *buf)
0012 {
0013     struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
0014     struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
0015     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0016 
0017     return sprintf(buf, "%s\n", acpi_desc->fwa_noidle ? "Y" : "N");
0018 }
0019 
0020 static ssize_t firmware_activate_noidle_store(struct device *dev,
0021         struct device_attribute *attr, const char *buf, size_t size)
0022 {
0023     struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
0024     struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
0025     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0026     ssize_t rc;
0027     bool val;
0028 
0029     rc = kstrtobool(buf, &val);
0030     if (rc)
0031         return rc;
0032     if (val != acpi_desc->fwa_noidle)
0033         acpi_desc->fwa_cap = NVDIMM_FWA_CAP_INVALID;
0034     acpi_desc->fwa_noidle = val;
0035     return size;
0036 }
0037 DEVICE_ATTR_RW(firmware_activate_noidle);
0038 
0039 bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus)
0040 {
0041     struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
0042     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0043     unsigned long *mask;
0044 
0045     if (!test_bit(NVDIMM_BUS_FAMILY_INTEL, &nd_desc->bus_family_mask))
0046         return false;
0047 
0048     mask = &acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL];
0049     return *mask == NVDIMM_BUS_INTEL_FW_ACTIVATE_CMDMASK;
0050 }
0051 
0052 static unsigned long intel_security_flags(struct nvdimm *nvdimm,
0053         enum nvdimm_passphrase_type ptype)
0054 {
0055     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0056     unsigned long security_flags = 0;
0057     struct {
0058         struct nd_cmd_pkg pkg;
0059         struct nd_intel_get_security_state cmd;
0060     } nd_cmd = {
0061         .pkg = {
0062             .nd_command = NVDIMM_INTEL_GET_SECURITY_STATE,
0063             .nd_family = NVDIMM_FAMILY_INTEL,
0064             .nd_size_out =
0065                 sizeof(struct nd_intel_get_security_state),
0066             .nd_fw_size =
0067                 sizeof(struct nd_intel_get_security_state),
0068         },
0069     };
0070     int rc;
0071 
0072     if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
0073         return 0;
0074 
0075     /*
0076      * Short circuit the state retrieval while we are doing overwrite.
0077      * The DSM spec states that the security state is indeterminate
0078      * until the overwrite DSM completes.
0079      */
0080     if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
0081         return BIT(NVDIMM_SECURITY_OVERWRITE);
0082 
0083     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0084     if (rc < 0 || nd_cmd.cmd.status) {
0085         pr_err("%s: security state retrieval failed (%d:%#x)\n",
0086                 nvdimm_name(nvdimm), rc, nd_cmd.cmd.status);
0087         return 0;
0088     }
0089 
0090     /* check and see if security is enabled and locked */
0091     if (ptype == NVDIMM_MASTER) {
0092         if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
0093             set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
0094         else
0095             set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
0096         if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_PLIMIT)
0097             set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
0098         return security_flags;
0099     }
0100 
0101     if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
0102         return 0;
0103 
0104     if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
0105         if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN ||
0106             nd_cmd.cmd.state & ND_INTEL_SEC_STATE_PLIMIT)
0107             set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
0108 
0109         if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
0110             set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
0111         else
0112             set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
0113     } else
0114         set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
0115 
0116     return security_flags;
0117 }
0118 
0119 static int intel_security_freeze(struct nvdimm *nvdimm)
0120 {
0121     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0122     struct {
0123         struct nd_cmd_pkg pkg;
0124         struct nd_intel_freeze_lock cmd;
0125     } nd_cmd = {
0126         .pkg = {
0127             .nd_command = NVDIMM_INTEL_FREEZE_LOCK,
0128             .nd_family = NVDIMM_FAMILY_INTEL,
0129             .nd_size_out = ND_INTEL_STATUS_SIZE,
0130             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0131         },
0132     };
0133     int rc;
0134 
0135     if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
0136         return -ENOTTY;
0137 
0138     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0139     if (rc < 0)
0140         return rc;
0141     if (nd_cmd.cmd.status)
0142         return -EIO;
0143     return 0;
0144 }
0145 
0146 static int intel_security_change_key(struct nvdimm *nvdimm,
0147         const struct nvdimm_key_data *old_data,
0148         const struct nvdimm_key_data *new_data,
0149         enum nvdimm_passphrase_type ptype)
0150 {
0151     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0152     unsigned int cmd = ptype == NVDIMM_MASTER ?
0153         NVDIMM_INTEL_SET_MASTER_PASSPHRASE :
0154         NVDIMM_INTEL_SET_PASSPHRASE;
0155     struct {
0156         struct nd_cmd_pkg pkg;
0157         struct nd_intel_set_passphrase cmd;
0158     } nd_cmd = {
0159         .pkg = {
0160             .nd_family = NVDIMM_FAMILY_INTEL,
0161             .nd_size_in = ND_INTEL_PASSPHRASE_SIZE * 2,
0162             .nd_size_out = ND_INTEL_STATUS_SIZE,
0163             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0164             .nd_command = cmd,
0165         },
0166     };
0167     int rc;
0168 
0169     if (!test_bit(cmd, &nfit_mem->dsm_mask))
0170         return -ENOTTY;
0171 
0172     memcpy(nd_cmd.cmd.old_pass, old_data->data,
0173             sizeof(nd_cmd.cmd.old_pass));
0174     memcpy(nd_cmd.cmd.new_pass, new_data->data,
0175             sizeof(nd_cmd.cmd.new_pass));
0176     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0177     if (rc < 0)
0178         return rc;
0179 
0180     switch (nd_cmd.cmd.status) {
0181     case 0:
0182         return 0;
0183     case ND_INTEL_STATUS_INVALID_PASS:
0184         return -EINVAL;
0185     case ND_INTEL_STATUS_NOT_SUPPORTED:
0186         return -EOPNOTSUPP;
0187     case ND_INTEL_STATUS_INVALID_STATE:
0188     default:
0189         return -EIO;
0190     }
0191 }
0192 
0193 static void nvdimm_invalidate_cache(void);
0194 
0195 static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
0196         const struct nvdimm_key_data *key_data)
0197 {
0198     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0199     struct {
0200         struct nd_cmd_pkg pkg;
0201         struct nd_intel_unlock_unit cmd;
0202     } nd_cmd = {
0203         .pkg = {
0204             .nd_command = NVDIMM_INTEL_UNLOCK_UNIT,
0205             .nd_family = NVDIMM_FAMILY_INTEL,
0206             .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
0207             .nd_size_out = ND_INTEL_STATUS_SIZE,
0208             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0209         },
0210     };
0211     int rc;
0212 
0213     if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask))
0214         return -ENOTTY;
0215 
0216     memcpy(nd_cmd.cmd.passphrase, key_data->data,
0217             sizeof(nd_cmd.cmd.passphrase));
0218     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0219     if (rc < 0)
0220         return rc;
0221     switch (nd_cmd.cmd.status) {
0222     case 0:
0223         break;
0224     case ND_INTEL_STATUS_INVALID_PASS:
0225         return -EINVAL;
0226     default:
0227         return -EIO;
0228     }
0229 
0230     /* DIMM unlocked, invalidate all CPU caches before we read it */
0231     nvdimm_invalidate_cache();
0232 
0233     return 0;
0234 }
0235 
0236 static int intel_security_disable(struct nvdimm *nvdimm,
0237         const struct nvdimm_key_data *key_data)
0238 {
0239     int rc;
0240     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0241     struct {
0242         struct nd_cmd_pkg pkg;
0243         struct nd_intel_disable_passphrase cmd;
0244     } nd_cmd = {
0245         .pkg = {
0246             .nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE,
0247             .nd_family = NVDIMM_FAMILY_INTEL,
0248             .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
0249             .nd_size_out = ND_INTEL_STATUS_SIZE,
0250             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0251         },
0252     };
0253 
0254     if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask))
0255         return -ENOTTY;
0256 
0257     memcpy(nd_cmd.cmd.passphrase, key_data->data,
0258             sizeof(nd_cmd.cmd.passphrase));
0259     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0260     if (rc < 0)
0261         return rc;
0262 
0263     switch (nd_cmd.cmd.status) {
0264     case 0:
0265         break;
0266     case ND_INTEL_STATUS_INVALID_PASS:
0267         return -EINVAL;
0268     case ND_INTEL_STATUS_INVALID_STATE:
0269     default:
0270         return -ENXIO;
0271     }
0272 
0273     return 0;
0274 }
0275 
0276 static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
0277         const struct nvdimm_key_data *key,
0278         enum nvdimm_passphrase_type ptype)
0279 {
0280     int rc;
0281     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0282     unsigned int cmd = ptype == NVDIMM_MASTER ?
0283         NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE;
0284     struct {
0285         struct nd_cmd_pkg pkg;
0286         struct nd_intel_secure_erase cmd;
0287     } nd_cmd = {
0288         .pkg = {
0289             .nd_family = NVDIMM_FAMILY_INTEL,
0290             .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
0291             .nd_size_out = ND_INTEL_STATUS_SIZE,
0292             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0293             .nd_command = cmd,
0294         },
0295     };
0296 
0297     if (!test_bit(cmd, &nfit_mem->dsm_mask))
0298         return -ENOTTY;
0299 
0300     /* flush all cache before we erase DIMM */
0301     nvdimm_invalidate_cache();
0302     memcpy(nd_cmd.cmd.passphrase, key->data,
0303             sizeof(nd_cmd.cmd.passphrase));
0304     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0305     if (rc < 0)
0306         return rc;
0307 
0308     switch (nd_cmd.cmd.status) {
0309     case 0:
0310         break;
0311     case ND_INTEL_STATUS_NOT_SUPPORTED:
0312         return -EOPNOTSUPP;
0313     case ND_INTEL_STATUS_INVALID_PASS:
0314         return -EINVAL;
0315     case ND_INTEL_STATUS_INVALID_STATE:
0316     default:
0317         return -ENXIO;
0318     }
0319 
0320     /* DIMM erased, invalidate all CPU caches before we read it */
0321     nvdimm_invalidate_cache();
0322     return 0;
0323 }
0324 
0325 static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
0326 {
0327     int rc;
0328     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0329     struct {
0330         struct nd_cmd_pkg pkg;
0331         struct nd_intel_query_overwrite cmd;
0332     } nd_cmd = {
0333         .pkg = {
0334             .nd_command = NVDIMM_INTEL_QUERY_OVERWRITE,
0335             .nd_family = NVDIMM_FAMILY_INTEL,
0336             .nd_size_out = ND_INTEL_STATUS_SIZE,
0337             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0338         },
0339     };
0340 
0341     if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask))
0342         return -ENOTTY;
0343 
0344     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0345     if (rc < 0)
0346         return rc;
0347 
0348     switch (nd_cmd.cmd.status) {
0349     case 0:
0350         break;
0351     case ND_INTEL_STATUS_OQUERY_INPROGRESS:
0352         return -EBUSY;
0353     default:
0354         return -ENXIO;
0355     }
0356 
0357     /* flush all cache before we make the nvdimms available */
0358     nvdimm_invalidate_cache();
0359     return 0;
0360 }
0361 
0362 static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
0363         const struct nvdimm_key_data *nkey)
0364 {
0365     int rc;
0366     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0367     struct {
0368         struct nd_cmd_pkg pkg;
0369         struct nd_intel_overwrite cmd;
0370     } nd_cmd = {
0371         .pkg = {
0372             .nd_command = NVDIMM_INTEL_OVERWRITE,
0373             .nd_family = NVDIMM_FAMILY_INTEL,
0374             .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
0375             .nd_size_out = ND_INTEL_STATUS_SIZE,
0376             .nd_fw_size = ND_INTEL_STATUS_SIZE,
0377         },
0378     };
0379 
0380     if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
0381         return -ENOTTY;
0382 
0383     /* flush all cache before we erase DIMM */
0384     nvdimm_invalidate_cache();
0385     memcpy(nd_cmd.cmd.passphrase, nkey->data,
0386             sizeof(nd_cmd.cmd.passphrase));
0387     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0388     if (rc < 0)
0389         return rc;
0390 
0391     switch (nd_cmd.cmd.status) {
0392     case 0:
0393         return 0;
0394     case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED:
0395         return -ENOTSUPP;
0396     case ND_INTEL_STATUS_INVALID_PASS:
0397         return -EINVAL;
0398     case ND_INTEL_STATUS_INVALID_STATE:
0399     default:
0400         return -ENXIO;
0401     }
0402 }
0403 
0404 /*
0405  * TODO: define a cross arch wbinvd equivalent when/if
0406  * NVDIMM_FAMILY_INTEL command support arrives on another arch.
0407  */
0408 #ifdef CONFIG_X86
0409 static void nvdimm_invalidate_cache(void)
0410 {
0411     wbinvd_on_all_cpus();
0412 }
0413 #else
0414 static void nvdimm_invalidate_cache(void)
0415 {
0416     WARN_ON_ONCE("cache invalidation required after unlock\n");
0417 }
0418 #endif
0419 
0420 static const struct nvdimm_security_ops __intel_security_ops = {
0421     .get_flags = intel_security_flags,
0422     .freeze = intel_security_freeze,
0423     .change_key = intel_security_change_key,
0424     .disable = intel_security_disable,
0425 #ifdef CONFIG_X86
0426     .unlock = intel_security_unlock,
0427     .erase = intel_security_erase,
0428     .overwrite = intel_security_overwrite,
0429     .query_overwrite = intel_security_query_overwrite,
0430 #endif
0431 };
0432 
0433 const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;
0434 
0435 static int intel_bus_fwa_businfo(struct nvdimm_bus_descriptor *nd_desc,
0436         struct nd_intel_bus_fw_activate_businfo *info)
0437 {
0438     struct {
0439         struct nd_cmd_pkg pkg;
0440         struct nd_intel_bus_fw_activate_businfo cmd;
0441     } nd_cmd = {
0442         .pkg = {
0443             .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO,
0444             .nd_family = NVDIMM_BUS_FAMILY_INTEL,
0445             .nd_size_out =
0446                 sizeof(struct nd_intel_bus_fw_activate_businfo),
0447             .nd_fw_size =
0448                 sizeof(struct nd_intel_bus_fw_activate_businfo),
0449         },
0450     };
0451     int rc;
0452 
0453     rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
0454             NULL);
0455     *info = nd_cmd.cmd;
0456     return rc;
0457 }
0458 
0459 /* The fw_ops expect to be called with the nvdimm_bus_lock() held */
0460 static enum nvdimm_fwa_state intel_bus_fwa_state(
0461         struct nvdimm_bus_descriptor *nd_desc)
0462 {
0463     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0464     struct nd_intel_bus_fw_activate_businfo info;
0465     struct device *dev = acpi_desc->dev;
0466     enum nvdimm_fwa_state state;
0467     int rc;
0468 
0469     /*
0470      * It should not be possible for platform firmware to return
0471      * busy because activate is a synchronous operation. Treat it
0472      * similar to invalid, i.e. always refresh / poll the status.
0473      */
0474     switch (acpi_desc->fwa_state) {
0475     case NVDIMM_FWA_INVALID:
0476     case NVDIMM_FWA_BUSY:
0477         break;
0478     default:
0479         /* check if capability needs to be refreshed */
0480         if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID)
0481             break;
0482         return acpi_desc->fwa_state;
0483     }
0484 
0485     /* Refresh with platform firmware */
0486     rc = intel_bus_fwa_businfo(nd_desc, &info);
0487     if (rc)
0488         return NVDIMM_FWA_INVALID;
0489 
0490     switch (info.state) {
0491     case ND_INTEL_FWA_IDLE:
0492         state = NVDIMM_FWA_IDLE;
0493         break;
0494     case ND_INTEL_FWA_BUSY:
0495         state = NVDIMM_FWA_BUSY;
0496         break;
0497     case ND_INTEL_FWA_ARMED:
0498         if (info.activate_tmo > info.max_quiesce_tmo)
0499             state = NVDIMM_FWA_ARM_OVERFLOW;
0500         else
0501             state = NVDIMM_FWA_ARMED;
0502         break;
0503     default:
0504         dev_err_once(dev, "invalid firmware activate state %d\n",
0505                 info.state);
0506         return NVDIMM_FWA_INVALID;
0507     }
0508 
0509     /*
0510      * Capability data is available in the same payload as state. It
0511      * is expected to be static.
0512      */
0513     if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID) {
0514         if (info.capability & ND_INTEL_BUS_FWA_CAP_FWQUIESCE)
0515             acpi_desc->fwa_cap = NVDIMM_FWA_CAP_QUIESCE;
0516         else if (info.capability & ND_INTEL_BUS_FWA_CAP_OSQUIESCE) {
0517             /*
0518              * Skip hibernate cycle by default if platform
0519              * indicates that it does not need devices to be
0520              * quiesced.
0521              */
0522             acpi_desc->fwa_cap = NVDIMM_FWA_CAP_LIVE;
0523         } else
0524             acpi_desc->fwa_cap = NVDIMM_FWA_CAP_NONE;
0525     }
0526 
0527     acpi_desc->fwa_state = state;
0528 
0529     return state;
0530 }
0531 
0532 static enum nvdimm_fwa_capability intel_bus_fwa_capability(
0533         struct nvdimm_bus_descriptor *nd_desc)
0534 {
0535     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0536 
0537     if (acpi_desc->fwa_cap > NVDIMM_FWA_CAP_INVALID)
0538         return acpi_desc->fwa_cap;
0539 
0540     if (intel_bus_fwa_state(nd_desc) > NVDIMM_FWA_INVALID)
0541         return acpi_desc->fwa_cap;
0542 
0543     return NVDIMM_FWA_CAP_INVALID;
0544 }
0545 
0546 static int intel_bus_fwa_activate(struct nvdimm_bus_descriptor *nd_desc)
0547 {
0548     struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
0549     struct {
0550         struct nd_cmd_pkg pkg;
0551         struct nd_intel_bus_fw_activate cmd;
0552     } nd_cmd = {
0553         .pkg = {
0554             .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE,
0555             .nd_family = NVDIMM_BUS_FAMILY_INTEL,
0556             .nd_size_in = sizeof(nd_cmd.cmd.iodev_state),
0557             .nd_size_out =
0558                 sizeof(struct nd_intel_bus_fw_activate),
0559             .nd_fw_size =
0560                 sizeof(struct nd_intel_bus_fw_activate),
0561         },
0562         /*
0563          * Even though activate is run from a suspended context,
0564          * for safety, still ask platform firmware to force
0565          * quiesce devices by default. Let a module
0566          * parameter override that policy.
0567          */
0568         .cmd = {
0569             .iodev_state = acpi_desc->fwa_noidle
0570                 ? ND_INTEL_BUS_FWA_IODEV_OS_IDLE
0571                 : ND_INTEL_BUS_FWA_IODEV_FORCE_IDLE,
0572         },
0573     };
0574     int rc;
0575 
0576     switch (intel_bus_fwa_state(nd_desc)) {
0577     case NVDIMM_FWA_ARMED:
0578     case NVDIMM_FWA_ARM_OVERFLOW:
0579         break;
0580     default:
0581         return -ENXIO;
0582     }
0583 
0584     rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
0585             NULL);
0586 
0587     /*
0588      * Whether the command succeeded, or failed, the agent checking
0589      * for the result needs to query the DIMMs individually.
0590      * Increment the activation count to invalidate all the DIMM
0591      * states at once (it's otherwise not possible to take
0592      * acpi_desc->init_mutex in this context)
0593      */
0594     acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
0595     acpi_desc->fwa_count++;
0596 
0597     dev_dbg(acpi_desc->dev, "result: %d\n", rc);
0598 
0599     return rc;
0600 }
0601 
0602 static const struct nvdimm_bus_fw_ops __intel_bus_fw_ops = {
0603     .activate_state = intel_bus_fwa_state,
0604     .capability = intel_bus_fwa_capability,
0605     .activate = intel_bus_fwa_activate,
0606 };
0607 
0608 const struct nvdimm_bus_fw_ops *intel_bus_fw_ops = &__intel_bus_fw_ops;
0609 
0610 static int intel_fwa_dimminfo(struct nvdimm *nvdimm,
0611         struct nd_intel_fw_activate_dimminfo *info)
0612 {
0613     struct {
0614         struct nd_cmd_pkg pkg;
0615         struct nd_intel_fw_activate_dimminfo cmd;
0616     } nd_cmd = {
0617         .pkg = {
0618             .nd_command = NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO,
0619             .nd_family = NVDIMM_FAMILY_INTEL,
0620             .nd_size_out =
0621                 sizeof(struct nd_intel_fw_activate_dimminfo),
0622             .nd_fw_size =
0623                 sizeof(struct nd_intel_fw_activate_dimminfo),
0624         },
0625     };
0626     int rc;
0627 
0628     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0629     *info = nd_cmd.cmd;
0630     return rc;
0631 }
0632 
0633 static enum nvdimm_fwa_state intel_fwa_state(struct nvdimm *nvdimm)
0634 {
0635     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0636     struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
0637     struct nd_intel_fw_activate_dimminfo info;
0638     int rc;
0639 
0640     /*
0641      * Similar to the bus state, since activate is synchronous the
0642      * busy state should resolve within the context of 'activate'.
0643      */
0644     switch (nfit_mem->fwa_state) {
0645     case NVDIMM_FWA_INVALID:
0646     case NVDIMM_FWA_BUSY:
0647         break;
0648     default:
0649         /* If no activations occurred the old state is still valid */
0650         if (nfit_mem->fwa_count == acpi_desc->fwa_count)
0651             return nfit_mem->fwa_state;
0652     }
0653 
0654     rc = intel_fwa_dimminfo(nvdimm, &info);
0655     if (rc)
0656         return NVDIMM_FWA_INVALID;
0657 
0658     switch (info.state) {
0659     case ND_INTEL_FWA_IDLE:
0660         nfit_mem->fwa_state = NVDIMM_FWA_IDLE;
0661         break;
0662     case ND_INTEL_FWA_BUSY:
0663         nfit_mem->fwa_state = NVDIMM_FWA_BUSY;
0664         break;
0665     case ND_INTEL_FWA_ARMED:
0666         nfit_mem->fwa_state = NVDIMM_FWA_ARMED;
0667         break;
0668     default:
0669         nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
0670         break;
0671     }
0672 
0673     switch (info.result) {
0674     case ND_INTEL_DIMM_FWA_NONE:
0675         nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NONE;
0676         break;
0677     case ND_INTEL_DIMM_FWA_SUCCESS:
0678         nfit_mem->fwa_result = NVDIMM_FWA_RESULT_SUCCESS;
0679         break;
0680     case ND_INTEL_DIMM_FWA_NOTSTAGED:
0681         nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NOTSTAGED;
0682         break;
0683     case ND_INTEL_DIMM_FWA_NEEDRESET:
0684         nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NEEDRESET;
0685         break;
0686     case ND_INTEL_DIMM_FWA_MEDIAFAILED:
0687     case ND_INTEL_DIMM_FWA_ABORT:
0688     case ND_INTEL_DIMM_FWA_NOTSUPP:
0689     case ND_INTEL_DIMM_FWA_ERROR:
0690     default:
0691         nfit_mem->fwa_result = NVDIMM_FWA_RESULT_FAIL;
0692         break;
0693     }
0694 
0695     nfit_mem->fwa_count = acpi_desc->fwa_count;
0696 
0697     return nfit_mem->fwa_state;
0698 }
0699 
0700 static enum nvdimm_fwa_result intel_fwa_result(struct nvdimm *nvdimm)
0701 {
0702     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0703     struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
0704 
0705     if (nfit_mem->fwa_count == acpi_desc->fwa_count
0706             && nfit_mem->fwa_result > NVDIMM_FWA_RESULT_INVALID)
0707         return nfit_mem->fwa_result;
0708 
0709     if (intel_fwa_state(nvdimm) > NVDIMM_FWA_INVALID)
0710         return nfit_mem->fwa_result;
0711 
0712     return NVDIMM_FWA_RESULT_INVALID;
0713 }
0714 
0715 static int intel_fwa_arm(struct nvdimm *nvdimm, enum nvdimm_fwa_trigger arm)
0716 {
0717     struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
0718     struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
0719     struct {
0720         struct nd_cmd_pkg pkg;
0721         struct nd_intel_fw_activate_arm cmd;
0722     } nd_cmd = {
0723         .pkg = {
0724             .nd_command = NVDIMM_INTEL_FW_ACTIVATE_ARM,
0725             .nd_family = NVDIMM_FAMILY_INTEL,
0726             .nd_size_in = sizeof(nd_cmd.cmd.activate_arm),
0727             .nd_size_out =
0728                 sizeof(struct nd_intel_fw_activate_arm),
0729             .nd_fw_size =
0730                 sizeof(struct nd_intel_fw_activate_arm),
0731         },
0732         .cmd = {
0733             .activate_arm = arm == NVDIMM_FWA_ARM
0734                 ? ND_INTEL_DIMM_FWA_ARM
0735                 : ND_INTEL_DIMM_FWA_DISARM,
0736         },
0737     };
0738     int rc;
0739 
0740     switch (intel_fwa_state(nvdimm)) {
0741     case NVDIMM_FWA_INVALID:
0742         return -ENXIO;
0743     case NVDIMM_FWA_BUSY:
0744         return -EBUSY;
0745     case NVDIMM_FWA_IDLE:
0746         if (arm == NVDIMM_FWA_DISARM)
0747             return 0;
0748         break;
0749     case NVDIMM_FWA_ARMED:
0750         if (arm == NVDIMM_FWA_ARM)
0751             return 0;
0752         break;
0753     default:
0754         return -ENXIO;
0755     }
0756 
0757     /*
0758      * Invalidate the bus-level state, now that we're committed to
0759      * changing the 'arm' state.
0760      */
0761     acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
0762     nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
0763 
0764     rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
0765 
0766     dev_dbg(acpi_desc->dev, "%s result: %d\n", arm == NVDIMM_FWA_ARM
0767             ? "arm" : "disarm", rc);
0768     return rc;
0769 }
0770 
0771 static const struct nvdimm_fw_ops __intel_fw_ops = {
0772     .activate_state = intel_fwa_state,
0773     .activate_result = intel_fwa_result,
0774     .arm = intel_fwa_arm,
0775 };
0776 
0777 const struct nvdimm_fw_ops *intel_fw_ops = &__intel_fw_ops;