intel.c 19 KB

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