Merge tag 'libnvdimm-for-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm...
[sfrench/cifs-2.6.git] / drivers / acpi / nfit / core.c
index e18ade5d74e9ecf38126bce5301f027073779bc3..df8979008dd4ec6496c1e5600ec856a300dec08f 100644 (file)
@@ -55,6 +55,10 @@ static bool no_init_ars;
 module_param(no_init_ars, bool, 0644);
 MODULE_PARM_DESC(no_init_ars, "Skip ARS run at nfit init time");
 
+static bool force_labels;
+module_param(force_labels, bool, 0444);
+MODULE_PARM_DESC(force_labels, "Opt-in to labels despite missing methods");
+
 LIST_HEAD(acpi_descs);
 DEFINE_MUTEX(acpi_desc_lock);
 
@@ -415,7 +419,7 @@ static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
        if (call_pkg) {
                int i;
 
-               if (nfit_mem->family != call_pkg->nd_family)
+               if (nfit_mem && nfit_mem->family != call_pkg->nd_family)
                        return -ENOTTY;
 
                for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
@@ -424,6 +428,10 @@ static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
                return call_pkg->nd_command;
        }
 
+       /* In the !call_pkg case, bus commands == bus functions */
+       if (!nfit_mem)
+               return cmd;
+
        /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
        if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
                return cmd;
@@ -454,17 +462,18 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        if (cmd_rc)
                *cmd_rc = -EINVAL;
 
+       if (cmd == ND_CMD_CALL)
+               call_pkg = buf;
+       func = cmd_to_func(nfit_mem, cmd, call_pkg);
+       if (func < 0)
+               return func;
+
        if (nvdimm) {
                struct acpi_device *adev = nfit_mem->adev;
 
                if (!adev)
                        return -ENOTTY;
 
-               if (cmd == ND_CMD_CALL)
-                       call_pkg = buf;
-               func = cmd_to_func(nfit_mem, cmd, call_pkg);
-               if (func < 0)
-                       return func;
                dimm_name = nvdimm_name(nvdimm);
                cmd_name = nvdimm_cmd_name(cmd);
                cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -475,12 +484,9 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        } else {
                struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
-               func = cmd;
                cmd_name = nvdimm_bus_cmd_name(cmd);
                cmd_mask = nd_desc->cmd_mask;
-               dsm_mask = cmd_mask;
-               if (cmd == ND_CMD_CALL)
-                       dsm_mask = nd_desc->bus_dsm_mask;
+               dsm_mask = nd_desc->bus_dsm_mask;
                desc = nd_cmd_bus_desc(cmd);
                guid = to_nfit_uuid(NFIT_DEV_BUS);
                handle = adev->handle;
@@ -554,6 +560,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                return -EINVAL;
        }
 
+       if (out_obj->type != ACPI_TYPE_BUFFER) {
+               dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
+                               dimm_name, cmd_name, out_obj->type);
+               rc = -EINVAL;
+               goto out;
+       }
+
        if (call_pkg) {
                call_pkg->nd_fw_size = out_obj->buffer.length;
                memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
@@ -572,13 +585,6 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                return 0;
        }
 
-       if (out_obj->package.type != ACPI_TYPE_BUFFER) {
-               dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
-                               dimm_name, cmd_name, out_obj->type);
-               rc = -EINVAL;
-               goto out;
-       }
-
        dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name,
                        cmd_name, out_obj->buffer.length);
        print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4,
@@ -1317,19 +1323,30 @@ static ssize_t scrub_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
        struct nvdimm_bus_descriptor *nd_desc;
+       struct acpi_nfit_desc *acpi_desc;
        ssize_t rc = -ENXIO;
+       bool busy;
 
        device_lock(dev);
        nd_desc = dev_get_drvdata(dev);
-       if (nd_desc) {
-               struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
+       if (!nd_desc) {
+               device_unlock(dev);
+               return rc;
+       }
+       acpi_desc = to_acpi_desc(nd_desc);
 
-               mutex_lock(&acpi_desc->init_mutex);
-               rc = sprintf(buf, "%d%s", acpi_desc->scrub_count,
-                               acpi_desc->scrub_busy
-                               && !acpi_desc->cancel ? "+\n" : "\n");
-               mutex_unlock(&acpi_desc->init_mutex);
+       mutex_lock(&acpi_desc->init_mutex);
+       busy = test_bit(ARS_BUSY, &acpi_desc->scrub_flags)
+               && !test_bit(ARS_CANCEL, &acpi_desc->scrub_flags);
+       rc = sprintf(buf, "%d%s", acpi_desc->scrub_count, busy ? "+\n" : "\n");
+       /* Allow an admin to poll the busy state at a higher rate */
+       if (busy && capable(CAP_SYS_RAWIO) && !test_and_set_bit(ARS_POLL,
+                               &acpi_desc->scrub_flags)) {
+               acpi_desc->scrub_tmo = 1;
+               mod_delayed_work(nfit_wq, &acpi_desc->dwork, HZ);
        }
+
+       mutex_unlock(&acpi_desc->init_mutex);
        device_unlock(dev);
        return rc;
 }
@@ -1759,14 +1776,14 @@ static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
 
 __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
 {
+       struct device *dev = &nfit_mem->adev->dev;
        struct nd_intel_smart smart = { 0 };
        union acpi_object in_buf = {
-               .type = ACPI_TYPE_BUFFER,
-               .buffer.pointer = (char *) &smart,
-               .buffer.length = sizeof(smart),
+               .buffer.type = ACPI_TYPE_BUFFER,
+               .buffer.length = 0,
        };
        union acpi_object in_obj = {
-               .type = ACPI_TYPE_PACKAGE,
+               .package.type = ACPI_TYPE_PACKAGE,
                .package.count = 1,
                .package.elements = &in_buf,
        };
@@ -1781,8 +1798,15 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
                return;
 
        out_obj = acpi_evaluate_dsm(handle, guid, revid, func, &in_obj);
-       if (!out_obj)
+       if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER
+                       || out_obj->buffer.length < sizeof(smart)) {
+               dev_dbg(dev->parent, "%s: failed to retrieve initial health\n",
+                               dev_name(dev));
+               ACPI_FREE(out_obj);
                return;
+       }
+       memcpy(&smart, out_obj->buffer.pointer, sizeof(smart));
+       ACPI_FREE(out_obj);
 
        if (smart.flags & ND_INTEL_SMART_SHUTDOWN_VALID) {
                if (smart.shutdown_state)
@@ -1793,7 +1817,6 @@ __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem)
                set_bit(NFIT_MEM_DIRTY_COUNT, &nfit_mem->flags);
                nfit_mem->dirty_shutdown = smart.shutdown_count;
        }
-       ACPI_FREE(out_obj);
 }
 
 static void populate_shutdown_status(struct nfit_mem *nfit_mem)
@@ -1861,9 +1884,17 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
        dev_set_drvdata(&adev_dimm->dev, nfit_mem);
 
        /*
-        * Until standardization materializes we need to consider 4
-        * different command sets.  Note, that checking for function0 (bit0)
-        * tells us if any commands are reachable through this GUID.
+        * There are 4 "legacy" NVDIMM command sets
+        * (NVDIMM_FAMILY_{INTEL,MSFT,HPE1,HPE2}) that were created before
+        * an EFI working group was established to constrain this
+        * proliferation. The nfit driver probes for the supported command
+        * set by GUID. Note, if you're a platform developer looking to add
+        * a new command set to this probe, consider using an existing set,
+        * or otherwise seek approval to publish the command set at
+        * http://www.uefi.org/RFIC_LIST.
+        *
+        * Note, that checking for function0 (bit0) tells us if any commands
+        * are reachable through this GUID.
         */
        for (i = 0; i <= NVDIMM_FAMILY_MAX; i++)
                if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
@@ -1886,6 +1917,8 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                        dsm_mask &= ~(1 << 8);
        } else if (nfit_mem->family == NVDIMM_FAMILY_MSFT) {
                dsm_mask = 0xffffffff;
+       } else if (nfit_mem->family == NVDIMM_FAMILY_HYPERV) {
+               dsm_mask = 0x1f;
        } else {
                dev_dbg(dev, "unknown dimm command family\n");
                nfit_mem->family = -1;
@@ -1915,18 +1948,32 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                | 1 << ND_CMD_SET_CONFIG_DATA;
        if (family == NVDIMM_FAMILY_INTEL
                        && (dsm_mask & label_mask) == label_mask)
-               return 0;
+               /* skip _LS{I,R,W} enabling */;
+       else {
+               if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
+                               && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
+                       dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
+                       set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
+               }
 
-       if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
-                       && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
-               dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
-               set_bit(NFIT_MEM_LSR, &nfit_mem->flags);
-       }
+               if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
+                               && acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
+                       dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
+                       set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
+               }
 
-       if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)
-                       && acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
-               dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
-               set_bit(NFIT_MEM_LSW, &nfit_mem->flags);
+               /*
+                * Quirk read-only label configurations to preserve
+                * access to label-less namespaces by default.
+                */
+               if (!test_bit(NFIT_MEM_LSW, &nfit_mem->flags)
+                               && !force_labels) {
+                       dev_dbg(dev, "%s: No _LSW, disable labels\n",
+                                       dev_name(&adev_dimm->dev));
+                       clear_bit(NFIT_MEM_LSR, &nfit_mem->flags);
+               } else
+                       dev_dbg(dev, "%s: Force enable labels\n",
+                                       dev_name(&adev_dimm->dev));
        }
 
        populate_shutdown_status(nfit_mem);
@@ -2027,6 +2074,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                        cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
                }
 
+               /* Quirk to ignore LOCAL for labels on HYPERV DIMMs */
+               if (nfit_mem->family == NVDIMM_FAMILY_HYPERV)
+                       set_bit(NDD_NOBLK, &flags);
+
                if (test_bit(NFIT_MEM_LSR, &nfit_mem->flags)) {
                        set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
                        set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
@@ -2050,7 +2101,7 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
                        continue;
 
-               dev_info(acpi_desc->dev, "%s flags:%s%s%s%s%s\n",
+               dev_err(acpi_desc->dev, "Error found in NVDIMM %s flags:%s%s%s%s%s\n",
                                nvdimm_name(nvdimm),
                  mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
                  mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
@@ -2641,7 +2692,10 @@ static int ars_start(struct acpi_nfit_desc *acpi_desc,
 
        if (rc < 0)
                return rc;
-       return cmd_rc;
+       if (cmd_rc < 0)
+               return cmd_rc;
+       set_bit(ARS_VALID, &acpi_desc->scrub_flags);
+       return 0;
 }
 
 static int ars_continue(struct acpi_nfit_desc *acpi_desc)
@@ -2651,11 +2705,11 @@ static int ars_continue(struct acpi_nfit_desc *acpi_desc)
        struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
        struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
 
-       memset(&ars_start, 0, sizeof(ars_start));
-       ars_start.address = ars_status->restart_address;
-       ars_start.length = ars_status->restart_length;
-       ars_start.type = ars_status->type;
-       ars_start.flags = acpi_desc->ars_start_flags;
+       ars_start = (struct nd_cmd_ars_start) {
+               .address = ars_status->restart_address,
+               .length = ars_status->restart_length,
+               .type = ars_status->type,
+       };
        rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_START, &ars_start,
                        sizeof(ars_start), &cmd_rc);
        if (rc < 0)
@@ -2734,6 +2788,17 @@ static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc)
         */
        if (ars_status->out_length < 44)
                return 0;
+
+       /*
+        * Ignore potentially stale results that are only refreshed
+        * after a start-ARS event.
+        */
+       if (!test_and_clear_bit(ARS_VALID, &acpi_desc->scrub_flags)) {
+               dev_dbg(acpi_desc->dev, "skip %d stale records\n",
+                               ars_status->num_records);
+               return 0;
+       }
+
        for (i = 0; i < ars_status->num_records; i++) {
                /* only process full records */
                if (ars_status->out_length
@@ -3004,14 +3069,16 @@ static int ars_register(struct acpi_nfit_desc *acpi_desc,
 {
        int rc;
 
-       if (no_init_ars || test_bit(ARS_FAILED, &nfit_spa->ars_state))
+       if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
                return acpi_nfit_register_region(acpi_desc, nfit_spa);
 
        set_bit(ARS_REQ_SHORT, &nfit_spa->ars_state);
-       set_bit(ARS_REQ_LONG, &nfit_spa->ars_state);
+       if (!no_init_ars)
+               set_bit(ARS_REQ_LONG, &nfit_spa->ars_state);
 
        switch (acpi_nfit_query_poison(acpi_desc)) {
        case 0:
+       case -ENOSPC:
        case -EAGAIN:
                rc = ars_start(acpi_desc, nfit_spa, ARS_REQ_SHORT);
                /* shouldn't happen, try again later */
@@ -3036,7 +3103,6 @@ static int ars_register(struct acpi_nfit_desc *acpi_desc,
                break;
        case -EBUSY:
        case -ENOMEM:
-       case -ENOSPC:
                /*
                 * BIOS was using ARS, wait for it to complete (or
                 * resources to become available) and then perform our
@@ -3071,7 +3137,7 @@ static unsigned int __acpi_nfit_scrub(struct acpi_nfit_desc *acpi_desc,
 
        lockdep_assert_held(&acpi_desc->init_mutex);
 
-       if (acpi_desc->cancel)
+       if (test_bit(ARS_CANCEL, &acpi_desc->scrub_flags))
                return 0;
 
        if (query_rc == -EBUSY) {
@@ -3145,7 +3211,7 @@ static void __sched_ars(struct acpi_nfit_desc *acpi_desc, unsigned int tmo)
 {
        lockdep_assert_held(&acpi_desc->init_mutex);
 
-       acpi_desc->scrub_busy = 1;
+       set_bit(ARS_BUSY, &acpi_desc->scrub_flags);
        /* note this should only be set from within the workqueue */
        if (tmo)
                acpi_desc->scrub_tmo = tmo;
@@ -3161,7 +3227,7 @@ static void notify_ars_done(struct acpi_nfit_desc *acpi_desc)
 {
        lockdep_assert_held(&acpi_desc->init_mutex);
 
-       acpi_desc->scrub_busy = 0;
+       clear_bit(ARS_BUSY, &acpi_desc->scrub_flags);
        acpi_desc->scrub_count++;
        if (acpi_desc->scrub_count_state)
                sysfs_notify_dirent(acpi_desc->scrub_count_state);
@@ -3182,6 +3248,7 @@ static void acpi_nfit_scrub(struct work_struct *work)
        else
                notify_ars_done(acpi_desc);
        memset(acpi_desc->ars_status, 0, acpi_desc->max_ars);
+       clear_bit(ARS_POLL, &acpi_desc->scrub_flags);
        mutex_unlock(&acpi_desc->init_mutex);
 }
 
@@ -3216,6 +3283,7 @@ static int acpi_nfit_register_regions(struct acpi_nfit_desc *acpi_desc)
        struct nfit_spa *nfit_spa;
        int rc;
 
+       set_bit(ARS_VALID, &acpi_desc->scrub_flags);
        list_for_each_entry(nfit_spa, &acpi_desc->spas, list) {
                switch (nfit_spa_type(nfit_spa->spa)) {
                case NFIT_SPA_VOLATILE:
@@ -3450,7 +3518,7 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc,
        struct nfit_spa *nfit_spa;
 
        mutex_lock(&acpi_desc->init_mutex);
-       if (acpi_desc->cancel) {
+       if (test_bit(ARS_CANCEL, &acpi_desc->scrub_flags)) {
                mutex_unlock(&acpi_desc->init_mutex);
                return 0;
        }
@@ -3529,7 +3597,7 @@ void acpi_nfit_shutdown(void *data)
        mutex_unlock(&acpi_desc_lock);
 
        mutex_lock(&acpi_desc->init_mutex);
-       acpi_desc->cancel = 1;
+       set_bit(ARS_CANCEL, &acpi_desc->scrub_flags);
        cancel_delayed_work_sync(&acpi_desc->dwork);
        mutex_unlock(&acpi_desc->init_mutex);
 
@@ -3729,6 +3797,7 @@ static __init int nfit_init(void)
        guid_parse(UUID_NFIT_DIMM_N_HPE1, &nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
        guid_parse(UUID_NFIT_DIMM_N_HPE2, &nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
        guid_parse(UUID_NFIT_DIMM_N_MSFT, &nfit_uuid[NFIT_DEV_DIMM_N_MSFT]);
+       guid_parse(UUID_NFIT_DIMM_N_HYPERV, &nfit_uuid[NFIT_DEV_DIMM_N_HYPERV]);
 
        nfit_wq = create_singlethread_workqueue("nfit");
        if (!nfit_wq)