Loading...
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
3#include <linux/libnvdimm.h>
4#include <linux/ndctl.h>
5#include <linux/acpi.h>
6#include <asm/smp.h>
7#include "intel.h"
8#include "nfit.h"
9
10static ssize_t firmware_activate_noidle_show(struct device *dev,
11 struct device_attribute *attr, char *buf)
12{
13 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
14 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
15 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
16
17 return sprintf(buf, "%s\n", acpi_desc->fwa_noidle ? "Y" : "N");
18}
19
20static ssize_t firmware_activate_noidle_store(struct device *dev,
21 struct device_attribute *attr, const char *buf, size_t size)
22{
23 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
24 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
25 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
26 ssize_t rc;
27 bool val;
28
29 rc = kstrtobool(buf, &val);
30 if (rc)
31 return rc;
32 if (val != acpi_desc->fwa_noidle)
33 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_INVALID;
34 acpi_desc->fwa_noidle = val;
35 return size;
36}
37DEVICE_ATTR_RW(firmware_activate_noidle);
38
39bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus)
40{
41 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
42 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
43 unsigned long *mask;
44
45 if (!test_bit(NVDIMM_BUS_FAMILY_INTEL, &nd_desc->bus_family_mask))
46 return false;
47
48 mask = &acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL];
49 return *mask == NVDIMM_BUS_INTEL_FW_ACTIVATE_CMDMASK;
50}
51
52static unsigned long intel_security_flags(struct nvdimm *nvdimm,
53 enum nvdimm_passphrase_type ptype)
54{
55 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
56 unsigned long security_flags = 0;
57 struct {
58 struct nd_cmd_pkg pkg;
59 struct nd_intel_get_security_state cmd;
60 } nd_cmd = {
61 .pkg = {
62 .nd_command = NVDIMM_INTEL_GET_SECURITY_STATE,
63 .nd_family = NVDIMM_FAMILY_INTEL,
64 .nd_size_out =
65 sizeof(struct nd_intel_get_security_state),
66 .nd_fw_size =
67 sizeof(struct nd_intel_get_security_state),
68 },
69 };
70 int rc;
71
72 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
73 return 0;
74
75 /*
76 * Short circuit the state retrieval while we are doing overwrite.
77 * The DSM spec states that the security state is indeterminate
78 * until the overwrite DSM completes.
79 */
80 if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
81 return BIT(NVDIMM_SECURITY_OVERWRITE);
82
83 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
84 if (rc < 0 || nd_cmd.cmd.status) {
85 pr_err("%s: security state retrieval failed (%d:%#x)\n",
86 nvdimm_name(nvdimm), rc, nd_cmd.cmd.status);
87 return 0;
88 }
89
90 /* check and see if security is enabled and locked */
91 if (ptype == NVDIMM_MASTER) {
92 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
93 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
94 else
95 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
96 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_PLIMIT)
97 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
98 return security_flags;
99 }
100
101 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
102 return 0;
103
104 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
105 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN ||
106 nd_cmd.cmd.state & ND_INTEL_SEC_STATE_PLIMIT)
107 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
108
109 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
110 set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
111 else
112 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
113 } else
114 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
115
116 return security_flags;
117}
118
119static int intel_security_freeze(struct nvdimm *nvdimm)
120{
121 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
122 struct {
123 struct nd_cmd_pkg pkg;
124 struct nd_intel_freeze_lock cmd;
125 } nd_cmd = {
126 .pkg = {
127 .nd_command = NVDIMM_INTEL_FREEZE_LOCK,
128 .nd_family = NVDIMM_FAMILY_INTEL,
129 .nd_size_out = ND_INTEL_STATUS_SIZE,
130 .nd_fw_size = ND_INTEL_STATUS_SIZE,
131 },
132 };
133 int rc;
134
135 if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
136 return -ENOTTY;
137
138 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
139 if (rc < 0)
140 return rc;
141 if (nd_cmd.cmd.status)
142 return -EIO;
143 return 0;
144}
145
146static int intel_security_change_key(struct nvdimm *nvdimm,
147 const struct nvdimm_key_data *old_data,
148 const struct nvdimm_key_data *new_data,
149 enum nvdimm_passphrase_type ptype)
150{
151 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
152 unsigned int cmd = ptype == NVDIMM_MASTER ?
153 NVDIMM_INTEL_SET_MASTER_PASSPHRASE :
154 NVDIMM_INTEL_SET_PASSPHRASE;
155 struct {
156 struct nd_cmd_pkg pkg;
157 struct nd_intel_set_passphrase cmd;
158 } nd_cmd = {
159 .pkg = {
160 .nd_family = NVDIMM_FAMILY_INTEL,
161 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE * 2,
162 .nd_size_out = ND_INTEL_STATUS_SIZE,
163 .nd_fw_size = ND_INTEL_STATUS_SIZE,
164 .nd_command = cmd,
165 },
166 };
167 int rc;
168
169 if (!test_bit(cmd, &nfit_mem->dsm_mask))
170 return -ENOTTY;
171
172 memcpy(nd_cmd.cmd.old_pass, old_data->data,
173 sizeof(nd_cmd.cmd.old_pass));
174 memcpy(nd_cmd.cmd.new_pass, new_data->data,
175 sizeof(nd_cmd.cmd.new_pass));
176 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
177 if (rc < 0)
178 return rc;
179
180 switch (nd_cmd.cmd.status) {
181 case 0:
182 return 0;
183 case ND_INTEL_STATUS_INVALID_PASS:
184 return -EINVAL;
185 case ND_INTEL_STATUS_NOT_SUPPORTED:
186 return -EOPNOTSUPP;
187 case ND_INTEL_STATUS_INVALID_STATE:
188 default:
189 return -EIO;
190 }
191}
192
193static void nvdimm_invalidate_cache(void);
194
195static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
196 const struct nvdimm_key_data *key_data)
197{
198 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
199 struct {
200 struct nd_cmd_pkg pkg;
201 struct nd_intel_unlock_unit cmd;
202 } nd_cmd = {
203 .pkg = {
204 .nd_command = NVDIMM_INTEL_UNLOCK_UNIT,
205 .nd_family = NVDIMM_FAMILY_INTEL,
206 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
207 .nd_size_out = ND_INTEL_STATUS_SIZE,
208 .nd_fw_size = ND_INTEL_STATUS_SIZE,
209 },
210 };
211 int rc;
212
213 if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask))
214 return -ENOTTY;
215
216 memcpy(nd_cmd.cmd.passphrase, key_data->data,
217 sizeof(nd_cmd.cmd.passphrase));
218 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
219 if (rc < 0)
220 return rc;
221 switch (nd_cmd.cmd.status) {
222 case 0:
223 break;
224 case ND_INTEL_STATUS_INVALID_PASS:
225 return -EINVAL;
226 default:
227 return -EIO;
228 }
229
230 /* DIMM unlocked, invalidate all CPU caches before we read it */
231 nvdimm_invalidate_cache();
232
233 return 0;
234}
235
236static int intel_security_disable(struct nvdimm *nvdimm,
237 const struct nvdimm_key_data *key_data)
238{
239 int rc;
240 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
241 struct {
242 struct nd_cmd_pkg pkg;
243 struct nd_intel_disable_passphrase cmd;
244 } nd_cmd = {
245 .pkg = {
246 .nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE,
247 .nd_family = NVDIMM_FAMILY_INTEL,
248 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
249 .nd_size_out = ND_INTEL_STATUS_SIZE,
250 .nd_fw_size = ND_INTEL_STATUS_SIZE,
251 },
252 };
253
254 if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask))
255 return -ENOTTY;
256
257 memcpy(nd_cmd.cmd.passphrase, key_data->data,
258 sizeof(nd_cmd.cmd.passphrase));
259 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
260 if (rc < 0)
261 return rc;
262
263 switch (nd_cmd.cmd.status) {
264 case 0:
265 break;
266 case ND_INTEL_STATUS_INVALID_PASS:
267 return -EINVAL;
268 case ND_INTEL_STATUS_INVALID_STATE:
269 default:
270 return -ENXIO;
271 }
272
273 return 0;
274}
275
276static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
277 const struct nvdimm_key_data *key,
278 enum nvdimm_passphrase_type ptype)
279{
280 int rc;
281 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
282 unsigned int cmd = ptype == NVDIMM_MASTER ?
283 NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE;
284 struct {
285 struct nd_cmd_pkg pkg;
286 struct nd_intel_secure_erase cmd;
287 } nd_cmd = {
288 .pkg = {
289 .nd_family = NVDIMM_FAMILY_INTEL,
290 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
291 .nd_size_out = ND_INTEL_STATUS_SIZE,
292 .nd_fw_size = ND_INTEL_STATUS_SIZE,
293 .nd_command = cmd,
294 },
295 };
296
297 if (!test_bit(cmd, &nfit_mem->dsm_mask))
298 return -ENOTTY;
299
300 /* flush all cache before we erase DIMM */
301 nvdimm_invalidate_cache();
302 memcpy(nd_cmd.cmd.passphrase, key->data,
303 sizeof(nd_cmd.cmd.passphrase));
304 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
305 if (rc < 0)
306 return rc;
307
308 switch (nd_cmd.cmd.status) {
309 case 0:
310 break;
311 case ND_INTEL_STATUS_NOT_SUPPORTED:
312 return -EOPNOTSUPP;
313 case ND_INTEL_STATUS_INVALID_PASS:
314 return -EINVAL;
315 case ND_INTEL_STATUS_INVALID_STATE:
316 default:
317 return -ENXIO;
318 }
319
320 /* DIMM erased, invalidate all CPU caches before we read it */
321 nvdimm_invalidate_cache();
322 return 0;
323}
324
325static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
326{
327 int rc;
328 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
329 struct {
330 struct nd_cmd_pkg pkg;
331 struct nd_intel_query_overwrite cmd;
332 } nd_cmd = {
333 .pkg = {
334 .nd_command = NVDIMM_INTEL_QUERY_OVERWRITE,
335 .nd_family = NVDIMM_FAMILY_INTEL,
336 .nd_size_out = ND_INTEL_STATUS_SIZE,
337 .nd_fw_size = ND_INTEL_STATUS_SIZE,
338 },
339 };
340
341 if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask))
342 return -ENOTTY;
343
344 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
345 if (rc < 0)
346 return rc;
347
348 switch (nd_cmd.cmd.status) {
349 case 0:
350 break;
351 case ND_INTEL_STATUS_OQUERY_INPROGRESS:
352 return -EBUSY;
353 default:
354 return -ENXIO;
355 }
356
357 /* flush all cache before we make the nvdimms available */
358 nvdimm_invalidate_cache();
359 return 0;
360}
361
362static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
363 const struct nvdimm_key_data *nkey)
364{
365 int rc;
366 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
367 struct {
368 struct nd_cmd_pkg pkg;
369 struct nd_intel_overwrite cmd;
370 } nd_cmd = {
371 .pkg = {
372 .nd_command = NVDIMM_INTEL_OVERWRITE,
373 .nd_family = NVDIMM_FAMILY_INTEL,
374 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
375 .nd_size_out = ND_INTEL_STATUS_SIZE,
376 .nd_fw_size = ND_INTEL_STATUS_SIZE,
377 },
378 };
379
380 if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
381 return -ENOTTY;
382
383 /* flush all cache before we erase DIMM */
384 nvdimm_invalidate_cache();
385 memcpy(nd_cmd.cmd.passphrase, nkey->data,
386 sizeof(nd_cmd.cmd.passphrase));
387 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
388 if (rc < 0)
389 return rc;
390
391 switch (nd_cmd.cmd.status) {
392 case 0:
393 return 0;
394 case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED:
395 return -ENOTSUPP;
396 case ND_INTEL_STATUS_INVALID_PASS:
397 return -EINVAL;
398 case ND_INTEL_STATUS_INVALID_STATE:
399 default:
400 return -ENXIO;
401 }
402}
403
404/*
405 * TODO: define a cross arch wbinvd equivalent when/if
406 * NVDIMM_FAMILY_INTEL command support arrives on another arch.
407 */
408#ifdef CONFIG_X86
409static void nvdimm_invalidate_cache(void)
410{
411 wbinvd_on_all_cpus();
412}
413#else
414static void nvdimm_invalidate_cache(void)
415{
416 WARN_ON_ONCE("cache invalidation required after unlock\n");
417}
418#endif
419
420static const struct nvdimm_security_ops __intel_security_ops = {
421 .get_flags = intel_security_flags,
422 .freeze = intel_security_freeze,
423 .change_key = intel_security_change_key,
424 .disable = intel_security_disable,
425#ifdef CONFIG_X86
426 .unlock = intel_security_unlock,
427 .erase = intel_security_erase,
428 .overwrite = intel_security_overwrite,
429 .query_overwrite = intel_security_query_overwrite,
430#endif
431};
432
433const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;
434
435static int intel_bus_fwa_businfo(struct nvdimm_bus_descriptor *nd_desc,
436 struct nd_intel_bus_fw_activate_businfo *info)
437{
438 struct {
439 struct nd_cmd_pkg pkg;
440 struct nd_intel_bus_fw_activate_businfo cmd;
441 } nd_cmd = {
442 .pkg = {
443 .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO,
444 .nd_family = NVDIMM_BUS_FAMILY_INTEL,
445 .nd_size_out =
446 sizeof(struct nd_intel_bus_fw_activate_businfo),
447 .nd_fw_size =
448 sizeof(struct nd_intel_bus_fw_activate_businfo),
449 },
450 };
451 int rc;
452
453 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
454 NULL);
455 *info = nd_cmd.cmd;
456 return rc;
457}
458
459/* The fw_ops expect to be called with the nvdimm_bus_lock() held */
460static enum nvdimm_fwa_state intel_bus_fwa_state(
461 struct nvdimm_bus_descriptor *nd_desc)
462{
463 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
464 struct nd_intel_bus_fw_activate_businfo info;
465 struct device *dev = acpi_desc->dev;
466 enum nvdimm_fwa_state state;
467 int rc;
468
469 /*
470 * It should not be possible for platform firmware to return
471 * busy because activate is a synchronous operation. Treat it
472 * similar to invalid, i.e. always refresh / poll the status.
473 */
474 switch (acpi_desc->fwa_state) {
475 case NVDIMM_FWA_INVALID:
476 case NVDIMM_FWA_BUSY:
477 break;
478 default:
479 /* check if capability needs to be refreshed */
480 if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID)
481 break;
482 return acpi_desc->fwa_state;
483 }
484
485 /* Refresh with platform firmware */
486 rc = intel_bus_fwa_businfo(nd_desc, &info);
487 if (rc)
488 return NVDIMM_FWA_INVALID;
489
490 switch (info.state) {
491 case ND_INTEL_FWA_IDLE:
492 state = NVDIMM_FWA_IDLE;
493 break;
494 case ND_INTEL_FWA_BUSY:
495 state = NVDIMM_FWA_BUSY;
496 break;
497 case ND_INTEL_FWA_ARMED:
498 if (info.activate_tmo > info.max_quiesce_tmo)
499 state = NVDIMM_FWA_ARM_OVERFLOW;
500 else
501 state = NVDIMM_FWA_ARMED;
502 break;
503 default:
504 dev_err_once(dev, "invalid firmware activate state %d\n",
505 info.state);
506 return NVDIMM_FWA_INVALID;
507 }
508
509 /*
510 * Capability data is available in the same payload as state. It
511 * is expected to be static.
512 */
513 if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID) {
514 if (info.capability & ND_INTEL_BUS_FWA_CAP_FWQUIESCE)
515 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_QUIESCE;
516 else if (info.capability & ND_INTEL_BUS_FWA_CAP_OSQUIESCE) {
517 /*
518 * Skip hibernate cycle by default if platform
519 * indicates that it does not need devices to be
520 * quiesced.
521 */
522 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_LIVE;
523 } else
524 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_NONE;
525 }
526
527 acpi_desc->fwa_state = state;
528
529 return state;
530}
531
532static enum nvdimm_fwa_capability intel_bus_fwa_capability(
533 struct nvdimm_bus_descriptor *nd_desc)
534{
535 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
536
537 if (acpi_desc->fwa_cap > NVDIMM_FWA_CAP_INVALID)
538 return acpi_desc->fwa_cap;
539
540 if (intel_bus_fwa_state(nd_desc) > NVDIMM_FWA_INVALID)
541 return acpi_desc->fwa_cap;
542
543 return NVDIMM_FWA_CAP_INVALID;
544}
545
546static int intel_bus_fwa_activate(struct nvdimm_bus_descriptor *nd_desc)
547{
548 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
549 struct {
550 struct nd_cmd_pkg pkg;
551 struct nd_intel_bus_fw_activate cmd;
552 } nd_cmd = {
553 .pkg = {
554 .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE,
555 .nd_family = NVDIMM_BUS_FAMILY_INTEL,
556 .nd_size_in = sizeof(nd_cmd.cmd.iodev_state),
557 .nd_size_out =
558 sizeof(struct nd_intel_bus_fw_activate),
559 .nd_fw_size =
560 sizeof(struct nd_intel_bus_fw_activate),
561 },
562 /*
563 * Even though activate is run from a suspended context,
564 * for safety, still ask platform firmware to force
565 * quiesce devices by default. Let a module
566 * parameter override that policy.
567 */
568 .cmd = {
569 .iodev_state = acpi_desc->fwa_noidle
570 ? ND_INTEL_BUS_FWA_IODEV_OS_IDLE
571 : ND_INTEL_BUS_FWA_IODEV_FORCE_IDLE,
572 },
573 };
574 int rc;
575
576 switch (intel_bus_fwa_state(nd_desc)) {
577 case NVDIMM_FWA_ARMED:
578 case NVDIMM_FWA_ARM_OVERFLOW:
579 break;
580 default:
581 return -ENXIO;
582 }
583
584 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
585 NULL);
586
587 /*
588 * Whether the command succeeded, or failed, the agent checking
589 * for the result needs to query the DIMMs individually.
590 * Increment the activation count to invalidate all the DIMM
591 * states at once (it's otherwise not possible to take
592 * acpi_desc->init_mutex in this context)
593 */
594 acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
595 acpi_desc->fwa_count++;
596
597 dev_dbg(acpi_desc->dev, "result: %d\n", rc);
598
599 return rc;
600}
601
602static const struct nvdimm_bus_fw_ops __intel_bus_fw_ops = {
603 .activate_state = intel_bus_fwa_state,
604 .capability = intel_bus_fwa_capability,
605 .activate = intel_bus_fwa_activate,
606};
607
608const struct nvdimm_bus_fw_ops *intel_bus_fw_ops = &__intel_bus_fw_ops;
609
610static int intel_fwa_dimminfo(struct nvdimm *nvdimm,
611 struct nd_intel_fw_activate_dimminfo *info)
612{
613 struct {
614 struct nd_cmd_pkg pkg;
615 struct nd_intel_fw_activate_dimminfo cmd;
616 } nd_cmd = {
617 .pkg = {
618 .nd_command = NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO,
619 .nd_family = NVDIMM_FAMILY_INTEL,
620 .nd_size_out =
621 sizeof(struct nd_intel_fw_activate_dimminfo),
622 .nd_fw_size =
623 sizeof(struct nd_intel_fw_activate_dimminfo),
624 },
625 };
626 int rc;
627
628 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
629 *info = nd_cmd.cmd;
630 return rc;
631}
632
633static enum nvdimm_fwa_state intel_fwa_state(struct nvdimm *nvdimm)
634{
635 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
636 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
637 struct nd_intel_fw_activate_dimminfo info;
638 int rc;
639
640 /*
641 * Similar to the bus state, since activate is synchronous the
642 * busy state should resolve within the context of 'activate'.
643 */
644 switch (nfit_mem->fwa_state) {
645 case NVDIMM_FWA_INVALID:
646 case NVDIMM_FWA_BUSY:
647 break;
648 default:
649 /* If no activations occurred the old state is still valid */
650 if (nfit_mem->fwa_count == acpi_desc->fwa_count)
651 return nfit_mem->fwa_state;
652 }
653
654 rc = intel_fwa_dimminfo(nvdimm, &info);
655 if (rc)
656 return NVDIMM_FWA_INVALID;
657
658 switch (info.state) {
659 case ND_INTEL_FWA_IDLE:
660 nfit_mem->fwa_state = NVDIMM_FWA_IDLE;
661 break;
662 case ND_INTEL_FWA_BUSY:
663 nfit_mem->fwa_state = NVDIMM_FWA_BUSY;
664 break;
665 case ND_INTEL_FWA_ARMED:
666 nfit_mem->fwa_state = NVDIMM_FWA_ARMED;
667 break;
668 default:
669 nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
670 break;
671 }
672
673 switch (info.result) {
674 case ND_INTEL_DIMM_FWA_NONE:
675 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NONE;
676 break;
677 case ND_INTEL_DIMM_FWA_SUCCESS:
678 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_SUCCESS;
679 break;
680 case ND_INTEL_DIMM_FWA_NOTSTAGED:
681 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NOTSTAGED;
682 break;
683 case ND_INTEL_DIMM_FWA_NEEDRESET:
684 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NEEDRESET;
685 break;
686 case ND_INTEL_DIMM_FWA_MEDIAFAILED:
687 case ND_INTEL_DIMM_FWA_ABORT:
688 case ND_INTEL_DIMM_FWA_NOTSUPP:
689 case ND_INTEL_DIMM_FWA_ERROR:
690 default:
691 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_FAIL;
692 break;
693 }
694
695 nfit_mem->fwa_count = acpi_desc->fwa_count;
696
697 return nfit_mem->fwa_state;
698}
699
700static enum nvdimm_fwa_result intel_fwa_result(struct nvdimm *nvdimm)
701{
702 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
703 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
704
705 if (nfit_mem->fwa_count == acpi_desc->fwa_count
706 && nfit_mem->fwa_result > NVDIMM_FWA_RESULT_INVALID)
707 return nfit_mem->fwa_result;
708
709 if (intel_fwa_state(nvdimm) > NVDIMM_FWA_INVALID)
710 return nfit_mem->fwa_result;
711
712 return NVDIMM_FWA_RESULT_INVALID;
713}
714
715static int intel_fwa_arm(struct nvdimm *nvdimm, enum nvdimm_fwa_trigger arm)
716{
717 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
718 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
719 struct {
720 struct nd_cmd_pkg pkg;
721 struct nd_intel_fw_activate_arm cmd;
722 } nd_cmd = {
723 .pkg = {
724 .nd_command = NVDIMM_INTEL_FW_ACTIVATE_ARM,
725 .nd_family = NVDIMM_FAMILY_INTEL,
726 .nd_size_in = sizeof(nd_cmd.cmd.activate_arm),
727 .nd_size_out =
728 sizeof(struct nd_intel_fw_activate_arm),
729 .nd_fw_size =
730 sizeof(struct nd_intel_fw_activate_arm),
731 },
732 .cmd = {
733 .activate_arm = arm == NVDIMM_FWA_ARM
734 ? ND_INTEL_DIMM_FWA_ARM
735 : ND_INTEL_DIMM_FWA_DISARM,
736 },
737 };
738 int rc;
739
740 switch (intel_fwa_state(nvdimm)) {
741 case NVDIMM_FWA_INVALID:
742 return -ENXIO;
743 case NVDIMM_FWA_BUSY:
744 return -EBUSY;
745 case NVDIMM_FWA_IDLE:
746 if (arm == NVDIMM_FWA_DISARM)
747 return 0;
748 break;
749 case NVDIMM_FWA_ARMED:
750 if (arm == NVDIMM_FWA_ARM)
751 return 0;
752 break;
753 default:
754 return -ENXIO;
755 }
756
757 /*
758 * Invalidate the bus-level state, now that we're committed to
759 * changing the 'arm' state.
760 */
761 acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
762 nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
763
764 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
765
766 dev_dbg(acpi_desc->dev, "%s result: %d\n", arm == NVDIMM_FWA_ARM
767 ? "arm" : "disarm", rc);
768 return rc;
769}
770
771static const struct nvdimm_fw_ops __intel_fw_ops = {
772 .activate_state = intel_fwa_state,
773 .activate_result = intel_fwa_result,
774 .arm = intel_fwa_arm,
775};
776
777const struct nvdimm_fw_ops *intel_fw_ops = &__intel_fw_ops;
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
3#include <linux/libnvdimm.h>
4#include <linux/ndctl.h>
5#include <linux/acpi.h>
6#include <linux/memregion.h>
7#include <asm/smp.h>
8#include "intel.h"
9#include "nfit.h"
10
11static ssize_t firmware_activate_noidle_show(struct device *dev,
12 struct device_attribute *attr, char *buf)
13{
14 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
15 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
16 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
17
18 return sprintf(buf, "%s\n", acpi_desc->fwa_noidle ? "Y" : "N");
19}
20
21static ssize_t firmware_activate_noidle_store(struct device *dev,
22 struct device_attribute *attr, const char *buf, size_t size)
23{
24 struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev);
25 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
26 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
27 ssize_t rc;
28 bool val;
29
30 rc = kstrtobool(buf, &val);
31 if (rc)
32 return rc;
33 if (val != acpi_desc->fwa_noidle)
34 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_INVALID;
35 acpi_desc->fwa_noidle = val;
36 return size;
37}
38DEVICE_ATTR_RW(firmware_activate_noidle);
39
40bool intel_fwa_supported(struct nvdimm_bus *nvdimm_bus)
41{
42 struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
43 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
44 unsigned long *mask;
45
46 if (!test_bit(NVDIMM_BUS_FAMILY_INTEL, &nd_desc->bus_family_mask))
47 return false;
48
49 mask = &acpi_desc->family_dsm_mask[NVDIMM_BUS_FAMILY_INTEL];
50 return *mask == NVDIMM_BUS_INTEL_FW_ACTIVATE_CMDMASK;
51}
52
53static unsigned long intel_security_flags(struct nvdimm *nvdimm,
54 enum nvdimm_passphrase_type ptype)
55{
56 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
57 unsigned long security_flags = 0;
58 struct {
59 struct nd_cmd_pkg pkg;
60 struct nd_intel_get_security_state cmd;
61 } nd_cmd = {
62 .pkg = {
63 .nd_command = NVDIMM_INTEL_GET_SECURITY_STATE,
64 .nd_family = NVDIMM_FAMILY_INTEL,
65 .nd_size_out =
66 sizeof(struct nd_intel_get_security_state),
67 .nd_fw_size =
68 sizeof(struct nd_intel_get_security_state),
69 },
70 };
71 int rc;
72
73 if (!test_bit(NVDIMM_INTEL_GET_SECURITY_STATE, &nfit_mem->dsm_mask))
74 return 0;
75
76 /*
77 * Short circuit the state retrieval while we are doing overwrite.
78 * The DSM spec states that the security state is indeterminate
79 * until the overwrite DSM completes.
80 */
81 if (nvdimm_in_overwrite(nvdimm) && ptype == NVDIMM_USER)
82 return BIT(NVDIMM_SECURITY_OVERWRITE);
83
84 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
85 if (rc < 0 || nd_cmd.cmd.status) {
86 pr_err("%s: security state retrieval failed (%d:%#x)\n",
87 nvdimm_name(nvdimm), rc, nd_cmd.cmd.status);
88 return 0;
89 }
90
91 /* check and see if security is enabled and locked */
92 if (ptype == NVDIMM_MASTER) {
93 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_ENABLED)
94 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
95 else
96 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
97 if (nd_cmd.cmd.extended_state & ND_INTEL_SEC_ESTATE_PLIMIT)
98 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
99 return security_flags;
100 }
101
102 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_UNSUPPORTED)
103 return 0;
104
105 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_ENABLED) {
106 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_FROZEN ||
107 nd_cmd.cmd.state & ND_INTEL_SEC_STATE_PLIMIT)
108 set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
109
110 if (nd_cmd.cmd.state & ND_INTEL_SEC_STATE_LOCKED)
111 set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
112 else
113 set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
114 } else
115 set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
116
117 return security_flags;
118}
119
120static int intel_security_freeze(struct nvdimm *nvdimm)
121{
122 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
123 struct {
124 struct nd_cmd_pkg pkg;
125 struct nd_intel_freeze_lock cmd;
126 } nd_cmd = {
127 .pkg = {
128 .nd_command = NVDIMM_INTEL_FREEZE_LOCK,
129 .nd_family = NVDIMM_FAMILY_INTEL,
130 .nd_size_out = ND_INTEL_STATUS_SIZE,
131 .nd_fw_size = ND_INTEL_STATUS_SIZE,
132 },
133 };
134 int rc;
135
136 if (!test_bit(NVDIMM_INTEL_FREEZE_LOCK, &nfit_mem->dsm_mask))
137 return -ENOTTY;
138
139 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
140 if (rc < 0)
141 return rc;
142 if (nd_cmd.cmd.status)
143 return -EIO;
144 return 0;
145}
146
147static int intel_security_change_key(struct nvdimm *nvdimm,
148 const struct nvdimm_key_data *old_data,
149 const struct nvdimm_key_data *new_data,
150 enum nvdimm_passphrase_type ptype)
151{
152 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
153 unsigned int cmd = ptype == NVDIMM_MASTER ?
154 NVDIMM_INTEL_SET_MASTER_PASSPHRASE :
155 NVDIMM_INTEL_SET_PASSPHRASE;
156 struct {
157 struct nd_cmd_pkg pkg;
158 struct nd_intel_set_passphrase cmd;
159 } nd_cmd = {
160 .pkg = {
161 .nd_family = NVDIMM_FAMILY_INTEL,
162 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE * 2,
163 .nd_size_out = ND_INTEL_STATUS_SIZE,
164 .nd_fw_size = ND_INTEL_STATUS_SIZE,
165 .nd_command = cmd,
166 },
167 };
168 int rc;
169
170 if (!test_bit(cmd, &nfit_mem->dsm_mask))
171 return -ENOTTY;
172
173 memcpy(nd_cmd.cmd.old_pass, old_data->data,
174 sizeof(nd_cmd.cmd.old_pass));
175 memcpy(nd_cmd.cmd.new_pass, new_data->data,
176 sizeof(nd_cmd.cmd.new_pass));
177 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
178 if (rc < 0)
179 return rc;
180
181 switch (nd_cmd.cmd.status) {
182 case 0:
183 return 0;
184 case ND_INTEL_STATUS_INVALID_PASS:
185 return -EINVAL;
186 case ND_INTEL_STATUS_NOT_SUPPORTED:
187 return -EOPNOTSUPP;
188 case ND_INTEL_STATUS_INVALID_STATE:
189 default:
190 return -EIO;
191 }
192}
193
194static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
195 const struct nvdimm_key_data *key_data)
196{
197 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
198 struct {
199 struct nd_cmd_pkg pkg;
200 struct nd_intel_unlock_unit cmd;
201 } nd_cmd = {
202 .pkg = {
203 .nd_command = NVDIMM_INTEL_UNLOCK_UNIT,
204 .nd_family = NVDIMM_FAMILY_INTEL,
205 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
206 .nd_size_out = ND_INTEL_STATUS_SIZE,
207 .nd_fw_size = ND_INTEL_STATUS_SIZE,
208 },
209 };
210 int rc;
211
212 if (!test_bit(NVDIMM_INTEL_UNLOCK_UNIT, &nfit_mem->dsm_mask))
213 return -ENOTTY;
214
215 memcpy(nd_cmd.cmd.passphrase, key_data->data,
216 sizeof(nd_cmd.cmd.passphrase));
217 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
218 if (rc < 0)
219 return rc;
220 switch (nd_cmd.cmd.status) {
221 case 0:
222 break;
223 case ND_INTEL_STATUS_INVALID_PASS:
224 return -EINVAL;
225 default:
226 return -EIO;
227 }
228
229 return 0;
230}
231
232static int intel_security_disable(struct nvdimm *nvdimm,
233 const struct nvdimm_key_data *key_data)
234{
235 int rc;
236 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
237 struct {
238 struct nd_cmd_pkg pkg;
239 struct nd_intel_disable_passphrase cmd;
240 } nd_cmd = {
241 .pkg = {
242 .nd_command = NVDIMM_INTEL_DISABLE_PASSPHRASE,
243 .nd_family = NVDIMM_FAMILY_INTEL,
244 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
245 .nd_size_out = ND_INTEL_STATUS_SIZE,
246 .nd_fw_size = ND_INTEL_STATUS_SIZE,
247 },
248 };
249
250 if (!test_bit(NVDIMM_INTEL_DISABLE_PASSPHRASE, &nfit_mem->dsm_mask))
251 return -ENOTTY;
252
253 memcpy(nd_cmd.cmd.passphrase, key_data->data,
254 sizeof(nd_cmd.cmd.passphrase));
255 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
256 if (rc < 0)
257 return rc;
258
259 switch (nd_cmd.cmd.status) {
260 case 0:
261 break;
262 case ND_INTEL_STATUS_INVALID_PASS:
263 return -EINVAL;
264 case ND_INTEL_STATUS_INVALID_STATE:
265 default:
266 return -ENXIO;
267 }
268
269 return 0;
270}
271
272static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
273 const struct nvdimm_key_data *key,
274 enum nvdimm_passphrase_type ptype)
275{
276 int rc;
277 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
278 unsigned int cmd = ptype == NVDIMM_MASTER ?
279 NVDIMM_INTEL_MASTER_SECURE_ERASE : NVDIMM_INTEL_SECURE_ERASE;
280 struct {
281 struct nd_cmd_pkg pkg;
282 struct nd_intel_secure_erase cmd;
283 } nd_cmd = {
284 .pkg = {
285 .nd_family = NVDIMM_FAMILY_INTEL,
286 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
287 .nd_size_out = ND_INTEL_STATUS_SIZE,
288 .nd_fw_size = ND_INTEL_STATUS_SIZE,
289 .nd_command = cmd,
290 },
291 };
292
293 if (!test_bit(cmd, &nfit_mem->dsm_mask))
294 return -ENOTTY;
295
296 memcpy(nd_cmd.cmd.passphrase, key->data,
297 sizeof(nd_cmd.cmd.passphrase));
298 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
299 if (rc < 0)
300 return rc;
301
302 switch (nd_cmd.cmd.status) {
303 case 0:
304 break;
305 case ND_INTEL_STATUS_NOT_SUPPORTED:
306 return -EOPNOTSUPP;
307 case ND_INTEL_STATUS_INVALID_PASS:
308 return -EINVAL;
309 case ND_INTEL_STATUS_INVALID_STATE:
310 default:
311 return -ENXIO;
312 }
313
314 return 0;
315}
316
317static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
318{
319 int rc;
320 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
321 struct {
322 struct nd_cmd_pkg pkg;
323 struct nd_intel_query_overwrite cmd;
324 } nd_cmd = {
325 .pkg = {
326 .nd_command = NVDIMM_INTEL_QUERY_OVERWRITE,
327 .nd_family = NVDIMM_FAMILY_INTEL,
328 .nd_size_out = ND_INTEL_STATUS_SIZE,
329 .nd_fw_size = ND_INTEL_STATUS_SIZE,
330 },
331 };
332
333 if (!test_bit(NVDIMM_INTEL_QUERY_OVERWRITE, &nfit_mem->dsm_mask))
334 return -ENOTTY;
335
336 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
337 if (rc < 0)
338 return rc;
339
340 switch (nd_cmd.cmd.status) {
341 case 0:
342 break;
343 case ND_INTEL_STATUS_OQUERY_INPROGRESS:
344 return -EBUSY;
345 default:
346 return -ENXIO;
347 }
348
349 return 0;
350}
351
352static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
353 const struct nvdimm_key_data *nkey)
354{
355 int rc;
356 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
357 struct {
358 struct nd_cmd_pkg pkg;
359 struct nd_intel_overwrite cmd;
360 } nd_cmd = {
361 .pkg = {
362 .nd_command = NVDIMM_INTEL_OVERWRITE,
363 .nd_family = NVDIMM_FAMILY_INTEL,
364 .nd_size_in = ND_INTEL_PASSPHRASE_SIZE,
365 .nd_size_out = ND_INTEL_STATUS_SIZE,
366 .nd_fw_size = ND_INTEL_STATUS_SIZE,
367 },
368 };
369
370 if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
371 return -ENOTTY;
372
373 memcpy(nd_cmd.cmd.passphrase, nkey->data,
374 sizeof(nd_cmd.cmd.passphrase));
375 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
376 if (rc < 0)
377 return rc;
378
379 switch (nd_cmd.cmd.status) {
380 case 0:
381 return 0;
382 case ND_INTEL_STATUS_OVERWRITE_UNSUPPORTED:
383 return -ENOTSUPP;
384 case ND_INTEL_STATUS_INVALID_PASS:
385 return -EINVAL;
386 case ND_INTEL_STATUS_INVALID_STATE:
387 default:
388 return -ENXIO;
389 }
390}
391
392static const struct nvdimm_security_ops __intel_security_ops = {
393 .get_flags = intel_security_flags,
394 .freeze = intel_security_freeze,
395 .change_key = intel_security_change_key,
396 .disable = intel_security_disable,
397#ifdef CONFIG_X86
398 .unlock = intel_security_unlock,
399 .erase = intel_security_erase,
400 .overwrite = intel_security_overwrite,
401 .query_overwrite = intel_security_query_overwrite,
402#endif
403};
404
405const struct nvdimm_security_ops *intel_security_ops = &__intel_security_ops;
406
407static int intel_bus_fwa_businfo(struct nvdimm_bus_descriptor *nd_desc,
408 struct nd_intel_bus_fw_activate_businfo *info)
409{
410 struct {
411 struct nd_cmd_pkg pkg;
412 struct nd_intel_bus_fw_activate_businfo cmd;
413 } nd_cmd = {
414 .pkg = {
415 .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE_BUSINFO,
416 .nd_family = NVDIMM_BUS_FAMILY_INTEL,
417 .nd_size_out =
418 sizeof(struct nd_intel_bus_fw_activate_businfo),
419 .nd_fw_size =
420 sizeof(struct nd_intel_bus_fw_activate_businfo),
421 },
422 };
423 int rc;
424
425 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
426 NULL);
427 *info = nd_cmd.cmd;
428 return rc;
429}
430
431/* The fw_ops expect to be called with the nvdimm_bus_lock() held */
432static enum nvdimm_fwa_state intel_bus_fwa_state(
433 struct nvdimm_bus_descriptor *nd_desc)
434{
435 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
436 struct nd_intel_bus_fw_activate_businfo info;
437 struct device *dev = acpi_desc->dev;
438 enum nvdimm_fwa_state state;
439 int rc;
440
441 /*
442 * It should not be possible for platform firmware to return
443 * busy because activate is a synchronous operation. Treat it
444 * similar to invalid, i.e. always refresh / poll the status.
445 */
446 switch (acpi_desc->fwa_state) {
447 case NVDIMM_FWA_INVALID:
448 case NVDIMM_FWA_BUSY:
449 break;
450 default:
451 /* check if capability needs to be refreshed */
452 if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID)
453 break;
454 return acpi_desc->fwa_state;
455 }
456
457 /* Refresh with platform firmware */
458 rc = intel_bus_fwa_businfo(nd_desc, &info);
459 if (rc)
460 return NVDIMM_FWA_INVALID;
461
462 switch (info.state) {
463 case ND_INTEL_FWA_IDLE:
464 state = NVDIMM_FWA_IDLE;
465 break;
466 case ND_INTEL_FWA_BUSY:
467 state = NVDIMM_FWA_BUSY;
468 break;
469 case ND_INTEL_FWA_ARMED:
470 if (info.activate_tmo > info.max_quiesce_tmo)
471 state = NVDIMM_FWA_ARM_OVERFLOW;
472 else
473 state = NVDIMM_FWA_ARMED;
474 break;
475 default:
476 dev_err_once(dev, "invalid firmware activate state %d\n",
477 info.state);
478 return NVDIMM_FWA_INVALID;
479 }
480
481 /*
482 * Capability data is available in the same payload as state. It
483 * is expected to be static.
484 */
485 if (acpi_desc->fwa_cap == NVDIMM_FWA_CAP_INVALID) {
486 if (info.capability & ND_INTEL_BUS_FWA_CAP_FWQUIESCE)
487 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_QUIESCE;
488 else if (info.capability & ND_INTEL_BUS_FWA_CAP_OSQUIESCE) {
489 /*
490 * Skip hibernate cycle by default if platform
491 * indicates that it does not need devices to be
492 * quiesced.
493 */
494 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_LIVE;
495 } else
496 acpi_desc->fwa_cap = NVDIMM_FWA_CAP_NONE;
497 }
498
499 acpi_desc->fwa_state = state;
500
501 return state;
502}
503
504static enum nvdimm_fwa_capability intel_bus_fwa_capability(
505 struct nvdimm_bus_descriptor *nd_desc)
506{
507 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
508
509 if (acpi_desc->fwa_cap > NVDIMM_FWA_CAP_INVALID)
510 return acpi_desc->fwa_cap;
511
512 if (intel_bus_fwa_state(nd_desc) > NVDIMM_FWA_INVALID)
513 return acpi_desc->fwa_cap;
514
515 return NVDIMM_FWA_CAP_INVALID;
516}
517
518static int intel_bus_fwa_activate(struct nvdimm_bus_descriptor *nd_desc)
519{
520 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
521 struct {
522 struct nd_cmd_pkg pkg;
523 struct nd_intel_bus_fw_activate cmd;
524 } nd_cmd = {
525 .pkg = {
526 .nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE,
527 .nd_family = NVDIMM_BUS_FAMILY_INTEL,
528 .nd_size_in = sizeof(nd_cmd.cmd.iodev_state),
529 .nd_size_out =
530 sizeof(struct nd_intel_bus_fw_activate),
531 .nd_fw_size =
532 sizeof(struct nd_intel_bus_fw_activate),
533 },
534 /*
535 * Even though activate is run from a suspended context,
536 * for safety, still ask platform firmware to force
537 * quiesce devices by default. Let a module
538 * parameter override that policy.
539 */
540 .cmd = {
541 .iodev_state = acpi_desc->fwa_noidle
542 ? ND_INTEL_BUS_FWA_IODEV_OS_IDLE
543 : ND_INTEL_BUS_FWA_IODEV_FORCE_IDLE,
544 },
545 };
546 int rc;
547
548 switch (intel_bus_fwa_state(nd_desc)) {
549 case NVDIMM_FWA_ARMED:
550 case NVDIMM_FWA_ARM_OVERFLOW:
551 break;
552 default:
553 return -ENXIO;
554 }
555
556 rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
557 NULL);
558
559 /*
560 * Whether the command succeeded, or failed, the agent checking
561 * for the result needs to query the DIMMs individually.
562 * Increment the activation count to invalidate all the DIMM
563 * states at once (it's otherwise not possible to take
564 * acpi_desc->init_mutex in this context)
565 */
566 acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
567 acpi_desc->fwa_count++;
568
569 dev_dbg(acpi_desc->dev, "result: %d\n", rc);
570
571 return rc;
572}
573
574static const struct nvdimm_bus_fw_ops __intel_bus_fw_ops = {
575 .activate_state = intel_bus_fwa_state,
576 .capability = intel_bus_fwa_capability,
577 .activate = intel_bus_fwa_activate,
578};
579
580const struct nvdimm_bus_fw_ops *intel_bus_fw_ops = &__intel_bus_fw_ops;
581
582static int intel_fwa_dimminfo(struct nvdimm *nvdimm,
583 struct nd_intel_fw_activate_dimminfo *info)
584{
585 struct {
586 struct nd_cmd_pkg pkg;
587 struct nd_intel_fw_activate_dimminfo cmd;
588 } nd_cmd = {
589 .pkg = {
590 .nd_command = NVDIMM_INTEL_FW_ACTIVATE_DIMMINFO,
591 .nd_family = NVDIMM_FAMILY_INTEL,
592 .nd_size_out =
593 sizeof(struct nd_intel_fw_activate_dimminfo),
594 .nd_fw_size =
595 sizeof(struct nd_intel_fw_activate_dimminfo),
596 },
597 };
598 int rc;
599
600 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
601 *info = nd_cmd.cmd;
602 return rc;
603}
604
605static enum nvdimm_fwa_state intel_fwa_state(struct nvdimm *nvdimm)
606{
607 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
608 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
609 struct nd_intel_fw_activate_dimminfo info;
610 int rc;
611
612 /*
613 * Similar to the bus state, since activate is synchronous the
614 * busy state should resolve within the context of 'activate'.
615 */
616 switch (nfit_mem->fwa_state) {
617 case NVDIMM_FWA_INVALID:
618 case NVDIMM_FWA_BUSY:
619 break;
620 default:
621 /* If no activations occurred the old state is still valid */
622 if (nfit_mem->fwa_count == acpi_desc->fwa_count)
623 return nfit_mem->fwa_state;
624 }
625
626 rc = intel_fwa_dimminfo(nvdimm, &info);
627 if (rc)
628 return NVDIMM_FWA_INVALID;
629
630 switch (info.state) {
631 case ND_INTEL_FWA_IDLE:
632 nfit_mem->fwa_state = NVDIMM_FWA_IDLE;
633 break;
634 case ND_INTEL_FWA_BUSY:
635 nfit_mem->fwa_state = NVDIMM_FWA_BUSY;
636 break;
637 case ND_INTEL_FWA_ARMED:
638 nfit_mem->fwa_state = NVDIMM_FWA_ARMED;
639 break;
640 default:
641 nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
642 break;
643 }
644
645 switch (info.result) {
646 case ND_INTEL_DIMM_FWA_NONE:
647 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NONE;
648 break;
649 case ND_INTEL_DIMM_FWA_SUCCESS:
650 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_SUCCESS;
651 break;
652 case ND_INTEL_DIMM_FWA_NOTSTAGED:
653 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NOTSTAGED;
654 break;
655 case ND_INTEL_DIMM_FWA_NEEDRESET:
656 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_NEEDRESET;
657 break;
658 case ND_INTEL_DIMM_FWA_MEDIAFAILED:
659 case ND_INTEL_DIMM_FWA_ABORT:
660 case ND_INTEL_DIMM_FWA_NOTSUPP:
661 case ND_INTEL_DIMM_FWA_ERROR:
662 default:
663 nfit_mem->fwa_result = NVDIMM_FWA_RESULT_FAIL;
664 break;
665 }
666
667 nfit_mem->fwa_count = acpi_desc->fwa_count;
668
669 return nfit_mem->fwa_state;
670}
671
672static enum nvdimm_fwa_result intel_fwa_result(struct nvdimm *nvdimm)
673{
674 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
675 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
676
677 if (nfit_mem->fwa_count == acpi_desc->fwa_count
678 && nfit_mem->fwa_result > NVDIMM_FWA_RESULT_INVALID)
679 return nfit_mem->fwa_result;
680
681 if (intel_fwa_state(nvdimm) > NVDIMM_FWA_INVALID)
682 return nfit_mem->fwa_result;
683
684 return NVDIMM_FWA_RESULT_INVALID;
685}
686
687static int intel_fwa_arm(struct nvdimm *nvdimm, enum nvdimm_fwa_trigger arm)
688{
689 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
690 struct acpi_nfit_desc *acpi_desc = nfit_mem->acpi_desc;
691 struct {
692 struct nd_cmd_pkg pkg;
693 struct nd_intel_fw_activate_arm cmd;
694 } nd_cmd = {
695 .pkg = {
696 .nd_command = NVDIMM_INTEL_FW_ACTIVATE_ARM,
697 .nd_family = NVDIMM_FAMILY_INTEL,
698 .nd_size_in = sizeof(nd_cmd.cmd.activate_arm),
699 .nd_size_out =
700 sizeof(struct nd_intel_fw_activate_arm),
701 .nd_fw_size =
702 sizeof(struct nd_intel_fw_activate_arm),
703 },
704 .cmd = {
705 .activate_arm = arm == NVDIMM_FWA_ARM
706 ? ND_INTEL_DIMM_FWA_ARM
707 : ND_INTEL_DIMM_FWA_DISARM,
708 },
709 };
710 int rc;
711
712 switch (intel_fwa_state(nvdimm)) {
713 case NVDIMM_FWA_INVALID:
714 return -ENXIO;
715 case NVDIMM_FWA_BUSY:
716 return -EBUSY;
717 case NVDIMM_FWA_IDLE:
718 if (arm == NVDIMM_FWA_DISARM)
719 return 0;
720 break;
721 case NVDIMM_FWA_ARMED:
722 if (arm == NVDIMM_FWA_ARM)
723 return 0;
724 break;
725 default:
726 return -ENXIO;
727 }
728
729 /*
730 * Invalidate the bus-level state, now that we're committed to
731 * changing the 'arm' state.
732 */
733 acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
734 nfit_mem->fwa_state = NVDIMM_FWA_INVALID;
735
736 rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
737
738 dev_dbg(acpi_desc->dev, "%s result: %d\n", arm == NVDIMM_FWA_ARM
739 ? "arm" : "disarm", rc);
740 return rc;
741}
742
743static const struct nvdimm_fw_ops __intel_fw_ops = {
744 .activate_state = intel_fwa_state,
745 .activate_result = intel_fwa_result,
746 .arm = intel_fwa_arm,
747};
748
749const struct nvdimm_fw_ops *intel_fw_ops = &__intel_fw_ops;