static ssize_t provider_show(struct device *dev, struct device_attribute *attr, char *buf) { struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev); return sprintf(buf, "%s\n", nvdimm_bus_provider(nvdimm_bus)); }
struct nvdimm_bus *walk_to_nvdimm_bus(struct device *nd_dev) { struct device *dev; for (dev = nd_dev; dev; dev = dev->parent) if (dev->release == nvdimm_bus_release) break; dev_WARN_ONCE(nd_dev, !dev, "invalid dev, not on nd bus\n"); if (dev) return to_nvdimm_bus(dev); return NULL; }
static ssize_t commands_show(struct device *dev, struct device_attribute *attr, char *buf) { int cmd, len = 0; struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev); struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc; for_each_set_bit(cmd, &nd_desc->dsm_mask, BITS_PER_LONG) len += sprintf(buf + len, "%s ", nvdimm_bus_cmd_name(cmd)); len += sprintf(buf + len, "\n"); return len; }
/** * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks * @ndns: the namespace containing poison ranges * @bb: badblocks instance to populate * @offset: offset at the start of the namespace before 'sector 0' * * The poison list generated during NFIT initialization may contain multiple, * possibly overlapping ranges in the SPA (System Physical Address) space. * Compare each of these ranges to the namespace currently being initialized, * and add badblocks to the gendisk for all matching sub-ranges */ void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, struct badblocks *bb, resource_size_t offset) { struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); struct nd_region *nd_region = to_nd_region(ndns->dev.parent); struct nvdimm_bus *nvdimm_bus; struct list_head *poison_list; u64 ns_start, ns_end, ns_size; struct nd_poison *pl; ns_size = nvdimm_namespace_capacity(ndns) - offset; ns_start = nsio->res.start + offset; ns_end = nsio->res.end; nvdimm_bus = to_nvdimm_bus(nd_region->dev.parent); poison_list = &nvdimm_bus->poison_list; if (list_empty(poison_list)) return; list_for_each_entry(pl, poison_list, list) { u64 pl_end = pl->start + pl->length - 1; /* Discard intervals with no intersection */ if (pl_end < ns_start) continue; if (pl->start > ns_end) continue; /* Deal with any overlap after start of the namespace */ if (pl->start >= ns_start) { u64 start = pl->start; u64 len; if (pl_end <= ns_end) len = pl->length; else len = ns_start + ns_size - pl->start; __add_badblock_range(bb, start - ns_start, len); continue; } /* Deal with overlap for poison starting before the namespace */ if (pl->start < ns_start) { u64 len; if (pl_end < ns_end) len = pl->start + pl->length - ns_start; else len = ns_size; __add_badblock_range(bb, 0, len); } }
static ssize_t wait_probe_show(struct device *dev, struct device_attribute *attr, char *buf) { struct nvdimm_bus *nvdimm_bus = to_nvdimm_bus(dev); struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc; int rc; if (nd_desc->flush_probe) { rc = nd_desc->flush_probe(nd_desc); if (rc) return rc; } nd_synchronize(); device_for_each_child(dev, NULL, flush_regions_dimms); return sprintf(buf, "1\n"); }