Linux Audio

Check our new training course

Loading...
v5.9
  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;
v6.8
  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;