drivers/nvdimm/ramdax.c

Source file repositories/reference/linux-study-clean/drivers/nvdimm/ramdax.c

File Facts

System
Linux kernel
Corpus path
drivers/nvdimm/ramdax.c
Extension
.c
Size
6558 bytes
Lines
283
Domain
Driver Families
Bucket
drivers/nvdimm
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ramdax_dimm {
	struct nvdimm *nvdimm;
	void *label_area;
};

static void ramdax_remove(struct platform_device *pdev)
{
	struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);

	nvdimm_bus_unregister(nvdimm_bus);
}

static int ramdax_register_region(struct resource *res,
		struct nvdimm *nvdimm,
		struct nvdimm_bus *nvdimm_bus)
{
	struct nd_mapping_desc mapping;
	struct nd_region_desc ndr_desc;
	struct nd_interleave_set *nd_set;
	int nid = phys_to_target_node(res->start);

	nd_set = kzalloc_obj(*nd_set);
	if (!nd_set)
		return -ENOMEM;

	nd_set->cookie1 = 0xcafebeefcafebeef;
	nd_set->cookie2 = nd_set->cookie1;
	nd_set->altcookie = nd_set->cookie1;

	memset(&mapping, 0, sizeof(mapping));
	mapping.nvdimm = nvdimm;
	mapping.start = 0;
	mapping.size = resource_size(res) - LABEL_AREA_SIZE;

	memset(&ndr_desc, 0, sizeof(ndr_desc));
	ndr_desc.res = res;
	ndr_desc.numa_node = numa_map_to_online_node(nid);
	ndr_desc.target_node = nid;
	ndr_desc.num_mappings = 1;
	ndr_desc.mapping = &mapping;
	ndr_desc.nd_set = nd_set;

	if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
		goto err_free_nd_set;

	return 0;

err_free_nd_set:
	kfree(nd_set);
	return -ENXIO;
}

static int ramdax_register_dimm(struct resource *res, void *data)
{
	resource_size_t start = res->start;
	resource_size_t size = resource_size(res);
	unsigned long flags = 0, cmd_mask = 0;
	struct nvdimm_bus *nvdimm_bus = data;
	struct ramdax_dimm *dimm;
	int err;

	dimm = kzalloc_obj(*dimm);
	if (!dimm)
		return -ENOMEM;

	dimm->label_area = memremap(start + size - LABEL_AREA_SIZE,
				    LABEL_AREA_SIZE, MEMREMAP_WB);
	if (!dimm->label_area) {
		err = -ENOMEM;
		goto err_free_dimm;
	}

	set_bit(NDD_LABELING, &flags);
	set_bit(NDD_REGISTER_SYNC, &flags);
	set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
	set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
	set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask);
	dimm->nvdimm = nvdimm_create(nvdimm_bus, dimm,
				     /* dimm_attribute_groups */ NULL,
				     flags, cmd_mask, 0, NULL);
	if (!dimm->nvdimm) {
		err = -ENOMEM;
		goto err_unmap_label;
	}

	err = ramdax_register_region(res, dimm->nvdimm, nvdimm_bus);
	if (err)
		goto err_remove_nvdimm;

	return 0;

Annotation

Implementation Notes