cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

of_pmem.c (2687B)


      1// SPDX-License-Identifier: GPL-2.0+
      2
      3#define pr_fmt(fmt) "of_pmem: " fmt
      4
      5#include <linux/of_platform.h>
      6#include <linux/of_address.h>
      7#include <linux/libnvdimm.h>
      8#include <linux/module.h>
      9#include <linux/ioport.h>
     10#include <linux/slab.h>
     11
     12struct of_pmem_private {
     13	struct nvdimm_bus_descriptor bus_desc;
     14	struct nvdimm_bus *bus;
     15};
     16
     17static int of_pmem_region_probe(struct platform_device *pdev)
     18{
     19	struct of_pmem_private *priv;
     20	struct device_node *np;
     21	struct nvdimm_bus *bus;
     22	bool is_volatile;
     23	int i;
     24
     25	np = dev_of_node(&pdev->dev);
     26	if (!np)
     27		return -ENXIO;
     28
     29	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
     30	if (!priv)
     31		return -ENOMEM;
     32
     33	priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
     34	priv->bus_desc.module = THIS_MODULE;
     35	priv->bus_desc.of_node = np;
     36
     37	priv->bus = bus = nvdimm_bus_register(&pdev->dev, &priv->bus_desc);
     38	if (!bus) {
     39		kfree(priv);
     40		return -ENODEV;
     41	}
     42	platform_set_drvdata(pdev, priv);
     43
     44	is_volatile = !!of_find_property(np, "volatile", NULL);
     45	dev_dbg(&pdev->dev, "Registering %s regions from %pOF\n",
     46			is_volatile ? "volatile" : "non-volatile",  np);
     47
     48	for (i = 0; i < pdev->num_resources; i++) {
     49		struct nd_region_desc ndr_desc;
     50		struct nd_region *region;
     51
     52		/*
     53		 * NB: libnvdimm copies the data from ndr_desc into it's own
     54		 * structures so passing a stack pointer is fine.
     55		 */
     56		memset(&ndr_desc, 0, sizeof(ndr_desc));
     57		ndr_desc.numa_node = dev_to_node(&pdev->dev);
     58		ndr_desc.target_node = ndr_desc.numa_node;
     59		ndr_desc.res = &pdev->resource[i];
     60		ndr_desc.of_node = np;
     61		set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
     62
     63		if (is_volatile)
     64			region = nvdimm_volatile_region_create(bus, &ndr_desc);
     65		else {
     66			set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags);
     67			region = nvdimm_pmem_region_create(bus, &ndr_desc);
     68		}
     69
     70		if (!region)
     71			dev_warn(&pdev->dev, "Unable to register region %pR from %pOF\n",
     72					ndr_desc.res, np);
     73		else
     74			dev_dbg(&pdev->dev, "Registered region %pR from %pOF\n",
     75					ndr_desc.res, np);
     76	}
     77
     78	return 0;
     79}
     80
     81static int of_pmem_region_remove(struct platform_device *pdev)
     82{
     83	struct of_pmem_private *priv = platform_get_drvdata(pdev);
     84
     85	nvdimm_bus_unregister(priv->bus);
     86	kfree(priv);
     87
     88	return 0;
     89}
     90
     91static const struct of_device_id of_pmem_region_match[] = {
     92	{ .compatible = "pmem-region" },
     93	{ .compatible = "pmem-region-v2" },
     94	{ },
     95};
     96
     97static struct platform_driver of_pmem_region_driver = {
     98	.probe = of_pmem_region_probe,
     99	.remove = of_pmem_region_remove,
    100	.driver = {
    101		.name = "of_pmem",
    102		.of_match_table = of_pmem_region_match,
    103	},
    104};
    105
    106module_platform_driver(of_pmem_region_driver);
    107MODULE_DEVICE_TABLE(of, of_pmem_region_match);
    108MODULE_LICENSE("GPL");
    109MODULE_AUTHOR("IBM Corporation");