dimm_devs.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of version 2 of the GNU General Public License as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License for more details.
  12. */
  13. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14. #include <linux/vmalloc.h>
  15. #include <linux/device.h>
  16. #include <linux/ndctl.h>
  17. #include <linux/slab.h>
  18. #include <linux/io.h>
  19. #include <linux/fs.h>
  20. #include <linux/mm.h>
  21. #include "nd-core.h"
  22. #include "nd.h"
  23. static DEFINE_IDA(dimm_ida);
  24. /*
  25. * Retrieve bus and dimm handle and return if this bus supports
  26. * get_config_data commands
  27. */
  28. static int __validate_dimm(struct nvdimm_drvdata *ndd)
  29. {
  30. struct nvdimm *nvdimm;
  31. if (!ndd)
  32. return -EINVAL;
  33. nvdimm = to_nvdimm(ndd->dev);
  34. if (!nvdimm->dsm_mask)
  35. return -ENXIO;
  36. if (!test_bit(ND_CMD_GET_CONFIG_DATA, nvdimm->dsm_mask))
  37. return -ENXIO;
  38. return 0;
  39. }
  40. static int validate_dimm(struct nvdimm_drvdata *ndd)
  41. {
  42. int rc = __validate_dimm(ndd);
  43. if (rc && ndd)
  44. dev_dbg(ndd->dev, "%pf: %s error: %d\n",
  45. __builtin_return_address(0), __func__, rc);
  46. return rc;
  47. }
  48. /**
  49. * nvdimm_init_nsarea - determine the geometry of a dimm's namespace area
  50. * @nvdimm: dimm to initialize
  51. */
  52. int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd)
  53. {
  54. struct nd_cmd_get_config_size *cmd = &ndd->nsarea;
  55. struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
  56. struct nvdimm_bus_descriptor *nd_desc;
  57. int rc = validate_dimm(ndd);
  58. if (rc)
  59. return rc;
  60. if (cmd->config_size)
  61. return 0; /* already valid */
  62. memset(cmd, 0, sizeof(*cmd));
  63. nd_desc = nvdimm_bus->nd_desc;
  64. return nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
  65. ND_CMD_GET_CONFIG_SIZE, cmd, sizeof(*cmd));
  66. }
  67. int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
  68. {
  69. struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
  70. struct nd_cmd_get_config_data_hdr *cmd;
  71. struct nvdimm_bus_descriptor *nd_desc;
  72. int rc = validate_dimm(ndd);
  73. u32 max_cmd_size, config_size;
  74. size_t offset;
  75. if (rc)
  76. return rc;
  77. if (ndd->data)
  78. return 0;
  79. if (ndd->nsarea.status || ndd->nsarea.max_xfer == 0
  80. || ndd->nsarea.config_size < ND_LABEL_MIN_SIZE) {
  81. dev_dbg(ndd->dev, "failed to init config data area: (%d:%d)\n",
  82. ndd->nsarea.max_xfer, ndd->nsarea.config_size);
  83. return -ENXIO;
  84. }
  85. ndd->data = kmalloc(ndd->nsarea.config_size, GFP_KERNEL);
  86. if (!ndd->data)
  87. ndd->data = vmalloc(ndd->nsarea.config_size);
  88. if (!ndd->data)
  89. return -ENOMEM;
  90. max_cmd_size = min_t(u32, PAGE_SIZE, ndd->nsarea.max_xfer);
  91. cmd = kzalloc(max_cmd_size + sizeof(*cmd), GFP_KERNEL);
  92. if (!cmd)
  93. return -ENOMEM;
  94. nd_desc = nvdimm_bus->nd_desc;
  95. for (config_size = ndd->nsarea.config_size, offset = 0;
  96. config_size; config_size -= cmd->in_length,
  97. offset += cmd->in_length) {
  98. cmd->in_length = min(config_size, max_cmd_size);
  99. cmd->in_offset = offset;
  100. rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
  101. ND_CMD_GET_CONFIG_DATA, cmd,
  102. cmd->in_length + sizeof(*cmd));
  103. if (rc || cmd->status) {
  104. rc = -ENXIO;
  105. break;
  106. }
  107. memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
  108. }
  109. dev_dbg(ndd->dev, "%s: len: %zu rc: %d\n", __func__, offset, rc);
  110. kfree(cmd);
  111. return rc;
  112. }
  113. int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
  114. void *buf, size_t len)
  115. {
  116. int rc = validate_dimm(ndd);
  117. size_t max_cmd_size, buf_offset;
  118. struct nd_cmd_set_config_hdr *cmd;
  119. struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
  120. struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
  121. if (rc)
  122. return rc;
  123. if (!ndd->data)
  124. return -ENXIO;
  125. if (offset + len > ndd->nsarea.config_size)
  126. return -ENXIO;
  127. max_cmd_size = min_t(u32, PAGE_SIZE, len);
  128. max_cmd_size = min_t(u32, max_cmd_size, ndd->nsarea.max_xfer);
  129. cmd = kzalloc(max_cmd_size + sizeof(*cmd) + sizeof(u32), GFP_KERNEL);
  130. if (!cmd)
  131. return -ENOMEM;
  132. for (buf_offset = 0; len; len -= cmd->in_length,
  133. buf_offset += cmd->in_length) {
  134. size_t cmd_size;
  135. u32 *status;
  136. cmd->in_offset = offset + buf_offset;
  137. cmd->in_length = min(max_cmd_size, len);
  138. memcpy(cmd->in_buf, buf + buf_offset, cmd->in_length);
  139. /* status is output in the last 4-bytes of the command buffer */
  140. cmd_size = sizeof(*cmd) + cmd->in_length + sizeof(u32);
  141. status = ((void *) cmd) + cmd_size - sizeof(u32);
  142. rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
  143. ND_CMD_SET_CONFIG_DATA, cmd, cmd_size);
  144. if (rc || *status) {
  145. rc = rc ? rc : -ENXIO;
  146. break;
  147. }
  148. }
  149. kfree(cmd);
  150. return rc;
  151. }
  152. static void nvdimm_release(struct device *dev)
  153. {
  154. struct nvdimm *nvdimm = to_nvdimm(dev);
  155. ida_simple_remove(&dimm_ida, nvdimm->id);
  156. kfree(nvdimm);
  157. }
  158. static struct device_type nvdimm_device_type = {
  159. .name = "nvdimm",
  160. .release = nvdimm_release,
  161. };
  162. bool is_nvdimm(struct device *dev)
  163. {
  164. return dev->type == &nvdimm_device_type;
  165. }
  166. struct nvdimm *to_nvdimm(struct device *dev)
  167. {
  168. struct nvdimm *nvdimm = container_of(dev, struct nvdimm, dev);
  169. WARN_ON(!is_nvdimm(dev));
  170. return nvdimm;
  171. }
  172. EXPORT_SYMBOL_GPL(to_nvdimm);
  173. struct nvdimm_drvdata *to_ndd(struct nd_mapping *nd_mapping)
  174. {
  175. struct nvdimm *nvdimm = nd_mapping->nvdimm;
  176. WARN_ON_ONCE(!is_nvdimm_bus_locked(&nvdimm->dev));
  177. return dev_get_drvdata(&nvdimm->dev);
  178. }
  179. EXPORT_SYMBOL(to_ndd);
  180. void nvdimm_drvdata_release(struct kref *kref)
  181. {
  182. struct nvdimm_drvdata *ndd = container_of(kref, typeof(*ndd), kref);
  183. struct device *dev = ndd->dev;
  184. struct resource *res, *_r;
  185. dev_dbg(dev, "%s\n", __func__);
  186. nvdimm_bus_lock(dev);
  187. for_each_dpa_resource_safe(ndd, res, _r)
  188. nvdimm_free_dpa(ndd, res);
  189. nvdimm_bus_unlock(dev);
  190. if (ndd->data && is_vmalloc_addr(ndd->data))
  191. vfree(ndd->data);
  192. else
  193. kfree(ndd->data);
  194. kfree(ndd);
  195. put_device(dev);
  196. }
  197. void get_ndd(struct nvdimm_drvdata *ndd)
  198. {
  199. kref_get(&ndd->kref);
  200. }
  201. void put_ndd(struct nvdimm_drvdata *ndd)
  202. {
  203. if (ndd)
  204. kref_put(&ndd->kref, nvdimm_drvdata_release);
  205. }
  206. const char *nvdimm_name(struct nvdimm *nvdimm)
  207. {
  208. return dev_name(&nvdimm->dev);
  209. }
  210. EXPORT_SYMBOL_GPL(nvdimm_name);
  211. void *nvdimm_provider_data(struct nvdimm *nvdimm)
  212. {
  213. if (nvdimm)
  214. return nvdimm->provider_data;
  215. return NULL;
  216. }
  217. EXPORT_SYMBOL_GPL(nvdimm_provider_data);
  218. static ssize_t commands_show(struct device *dev,
  219. struct device_attribute *attr, char *buf)
  220. {
  221. struct nvdimm *nvdimm = to_nvdimm(dev);
  222. int cmd, len = 0;
  223. if (!nvdimm->dsm_mask)
  224. return sprintf(buf, "\n");
  225. for_each_set_bit(cmd, nvdimm->dsm_mask, BITS_PER_LONG)
  226. len += sprintf(buf + len, "%s ", nvdimm_cmd_name(cmd));
  227. len += sprintf(buf + len, "\n");
  228. return len;
  229. }
  230. static DEVICE_ATTR_RO(commands);
  231. static ssize_t state_show(struct device *dev, struct device_attribute *attr,
  232. char *buf)
  233. {
  234. struct nvdimm *nvdimm = to_nvdimm(dev);
  235. /*
  236. * The state may be in the process of changing, userspace should
  237. * quiesce probing if it wants a static answer
  238. */
  239. nvdimm_bus_lock(dev);
  240. nvdimm_bus_unlock(dev);
  241. return sprintf(buf, "%s\n", atomic_read(&nvdimm->busy)
  242. ? "active" : "idle");
  243. }
  244. static DEVICE_ATTR_RO(state);
  245. static struct attribute *nvdimm_attributes[] = {
  246. &dev_attr_state.attr,
  247. &dev_attr_commands.attr,
  248. NULL,
  249. };
  250. struct attribute_group nvdimm_attribute_group = {
  251. .attrs = nvdimm_attributes,
  252. };
  253. EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
  254. struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
  255. const struct attribute_group **groups, unsigned long flags,
  256. unsigned long *dsm_mask)
  257. {
  258. struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
  259. struct device *dev;
  260. if (!nvdimm)
  261. return NULL;
  262. nvdimm->id = ida_simple_get(&dimm_ida, 0, 0, GFP_KERNEL);
  263. if (nvdimm->id < 0) {
  264. kfree(nvdimm);
  265. return NULL;
  266. }
  267. nvdimm->provider_data = provider_data;
  268. nvdimm->flags = flags;
  269. nvdimm->dsm_mask = dsm_mask;
  270. atomic_set(&nvdimm->busy, 0);
  271. dev = &nvdimm->dev;
  272. dev_set_name(dev, "nmem%d", nvdimm->id);
  273. dev->parent = &nvdimm_bus->dev;
  274. dev->type = &nvdimm_device_type;
  275. dev->devt = MKDEV(nvdimm_major, nvdimm->id);
  276. dev->groups = groups;
  277. nd_device_register(dev);
  278. return nvdimm;
  279. }
  280. EXPORT_SYMBOL_GPL(nvdimm_create);
  281. /**
  282. * nd_blk_available_dpa - account the unused dpa of BLK region
  283. * @nd_mapping: container of dpa-resource-root + labels
  284. *
  285. * Unlike PMEM, BLK namespaces can occupy discontiguous DPA ranges.
  286. */
  287. resource_size_t nd_blk_available_dpa(struct nd_mapping *nd_mapping)
  288. {
  289. struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
  290. resource_size_t map_end, busy = 0, available;
  291. struct resource *res;
  292. if (!ndd)
  293. return 0;
  294. map_end = nd_mapping->start + nd_mapping->size - 1;
  295. for_each_dpa_resource(ndd, res)
  296. if (res->start >= nd_mapping->start && res->start < map_end) {
  297. resource_size_t end = min(map_end, res->end);
  298. busy += end - res->start + 1;
  299. } else if (res->end >= nd_mapping->start
  300. && res->end <= map_end) {
  301. busy += res->end - nd_mapping->start;
  302. } else if (nd_mapping->start > res->start
  303. && nd_mapping->start < res->end) {
  304. /* total eclipse of the BLK region mapping */
  305. busy += nd_mapping->size;
  306. }
  307. available = map_end - nd_mapping->start + 1;
  308. if (busy < available)
  309. return available - busy;
  310. return 0;
  311. }
  312. /**
  313. * nd_pmem_available_dpa - for the given dimm+region account unallocated dpa
  314. * @nd_mapping: container of dpa-resource-root + labels
  315. * @nd_region: constrain available space check to this reference region
  316. * @overlap: calculate available space assuming this level of overlap
  317. *
  318. * Validate that a PMEM label, if present, aligns with the start of an
  319. * interleave set and truncate the available size at the lowest BLK
  320. * overlap point.
  321. *
  322. * The expectation is that this routine is called multiple times as it
  323. * probes for the largest BLK encroachment for any single member DIMM of
  324. * the interleave set. Once that value is determined the PMEM-limit for
  325. * the set can be established.
  326. */
  327. resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region,
  328. struct nd_mapping *nd_mapping, resource_size_t *overlap)
  329. {
  330. resource_size_t map_start, map_end, busy = 0, available, blk_start;
  331. struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
  332. struct resource *res;
  333. const char *reason;
  334. if (!ndd)
  335. return 0;
  336. map_start = nd_mapping->start;
  337. map_end = map_start + nd_mapping->size - 1;
  338. blk_start = max(map_start, map_end + 1 - *overlap);
  339. for_each_dpa_resource(ndd, res)
  340. if (res->start >= map_start && res->start < map_end) {
  341. if (strncmp(res->name, "blk", 3) == 0)
  342. blk_start = min(blk_start, res->start);
  343. else if (res->start != map_start) {
  344. reason = "misaligned to iset";
  345. goto err;
  346. } else {
  347. if (busy) {
  348. reason = "duplicate overlapping PMEM reservations?";
  349. goto err;
  350. }
  351. busy += resource_size(res);
  352. continue;
  353. }
  354. } else if (res->end >= map_start && res->end <= map_end) {
  355. if (strncmp(res->name, "blk", 3) == 0) {
  356. /*
  357. * If a BLK allocation overlaps the start of
  358. * PMEM the entire interleave set may now only
  359. * be used for BLK.
  360. */
  361. blk_start = map_start;
  362. } else {
  363. reason = "misaligned to iset";
  364. goto err;
  365. }
  366. } else if (map_start > res->start && map_start < res->end) {
  367. /* total eclipse of the mapping */
  368. busy += nd_mapping->size;
  369. blk_start = map_start;
  370. }
  371. *overlap = map_end + 1 - blk_start;
  372. available = blk_start - map_start;
  373. if (busy < available)
  374. return available - busy;
  375. return 0;
  376. err:
  377. /*
  378. * Something is wrong, PMEM must align with the start of the
  379. * interleave set, and there can only be one allocation per set.
  380. */
  381. nd_dbg_dpa(nd_region, ndd, res, "%s\n", reason);
  382. return 0;
  383. }
  384. void nvdimm_free_dpa(struct nvdimm_drvdata *ndd, struct resource *res)
  385. {
  386. WARN_ON_ONCE(!is_nvdimm_bus_locked(ndd->dev));
  387. kfree(res->name);
  388. __release_region(&ndd->dpa, res->start, resource_size(res));
  389. }
  390. struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd,
  391. struct nd_label_id *label_id, resource_size_t start,
  392. resource_size_t n)
  393. {
  394. char *name = kmemdup(label_id, sizeof(*label_id), GFP_KERNEL);
  395. struct resource *res;
  396. if (!name)
  397. return NULL;
  398. WARN_ON_ONCE(!is_nvdimm_bus_locked(ndd->dev));
  399. res = __request_region(&ndd->dpa, start, n, name, 0);
  400. if (!res)
  401. kfree(name);
  402. return res;
  403. }
  404. /**
  405. * nvdimm_allocated_dpa - sum up the dpa currently allocated to this label_id
  406. * @nvdimm: container of dpa-resource-root + labels
  407. * @label_id: dpa resource name of the form {pmem|blk}-<human readable uuid>
  408. */
  409. resource_size_t nvdimm_allocated_dpa(struct nvdimm_drvdata *ndd,
  410. struct nd_label_id *label_id)
  411. {
  412. resource_size_t allocated = 0;
  413. struct resource *res;
  414. for_each_dpa_resource(ndd, res)
  415. if (strcmp(res->name, label_id->id) == 0)
  416. allocated += resource_size(res);
  417. return allocated;
  418. }
  419. static int count_dimms(struct device *dev, void *c)
  420. {
  421. int *count = c;
  422. if (is_nvdimm(dev))
  423. (*count)++;
  424. return 0;
  425. }
  426. int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count)
  427. {
  428. int count = 0;
  429. /* Flush any possible dimm registration failures */
  430. nd_synchronize();
  431. device_for_each_child(&nvdimm_bus->dev, &count, count_dimms);
  432. dev_dbg(&nvdimm_bus->dev, "%s: count: %d\n", __func__, count);
  433. if (count != dimm_count)
  434. return -ENXIO;
  435. return 0;
  436. }
  437. EXPORT_SYMBOL_GPL(nvdimm_bus_check_dimm_count);