Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/cpumask.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/nd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include "nd-core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include "nd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) static int nd_region_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	int err, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	static unsigned long once;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	struct nd_region_data *ndrd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	struct nd_region *nd_region = to_nd_region(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	if (nd_region->num_lanes > num_online_cpus()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 			&& nd_region->num_lanes < num_possible_cpus()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 			&& !test_and_set_bit(0, &once)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 		dev_dbg(dev, "online cpus (%d) < concurrent i/o lanes (%d) < possible cpus (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 				num_online_cpus(), nd_region->num_lanes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 				num_possible_cpus());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		dev_dbg(dev, "setting nr_cpus=%d may yield better libnvdimm device performance\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 				nd_region->num_lanes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	rc = nd_region_activate(nd_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	rc = nd_blk_region_init(nd_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	if (is_memory(&nd_region->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 		struct range range = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 			.start = nd_region->ndr_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 			.end = nd_region->ndr_start + nd_region->ndr_size - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		if (devm_init_badblocks(dev, &nd_region->bb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 			return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		nd_region->bb_state = sysfs_get_dirent(nd_region->dev.kobj.sd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 						       "badblocks");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		if (!nd_region->bb_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			dev_warn(&nd_region->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 					"'badblocks' notification disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		nvdimm_badblocks_populate(nd_region, &nd_region->bb, &range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	rc = nd_region_register_namespaces(nd_region, &err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	ndrd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	ndrd->ns_active = rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	ndrd->ns_count = rc + err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	if (rc && err && rc == err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	nd_region->btt_seed = nd_btt_create(nd_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	nd_region->pfn_seed = nd_pfn_create(nd_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	nd_region->dax_seed = nd_dax_create(nd_region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	 * Given multiple namespaces per region, we do not want to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 * disable all the successfully registered peer namespaces upon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	 * a single registration failure.  If userspace is missing a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	 * namespace that it expects it can disable/re-enable the region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	 * to retry discovery after correcting the failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	 * <regionX>/namespaces returns the current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	 * "<async-registered>/<total>" namespace count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	dev_err(dev, "failed to register %d namespace%s, continuing...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			err, err == 1 ? "" : "s");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) static int child_unregister(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	nd_device_unregister(dev, ND_SYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static int nd_region_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct nd_region *nd_region = to_nd_region(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	device_for_each_child(dev, NULL, child_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	/* flush attribute readers and disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	nvdimm_bus_lock(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	nd_region->ns_seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	nd_region->btt_seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	nd_region->pfn_seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	nd_region->dax_seed = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	dev_set_drvdata(dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	nvdimm_bus_unlock(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	 * Note, this assumes nd_device_lock() context to not race
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	 * nd_region_notify()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	sysfs_put(nd_region->bb_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	nd_region->bb_state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int child_notify(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	nd_device_notify(dev, *(enum nvdimm_event *) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void nd_region_notify(struct device *dev, enum nvdimm_event event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (event == NVDIMM_REVALIDATE_POISON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		struct nd_region *nd_region = to_nd_region(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		if (is_memory(&nd_region->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			struct range range = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 				.start = nd_region->ndr_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 				.end = nd_region->ndr_start +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 					nd_region->ndr_size - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			nvdimm_badblocks_populate(nd_region,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 					&nd_region->bb, &range);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 			if (nd_region->bb_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 				sysfs_notify_dirent(nd_region->bb_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	device_for_each_child(dev, &event, child_notify);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static struct nd_device_driver nd_region_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	.probe = nd_region_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	.remove = nd_region_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	.notify = nd_region_notify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	.drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		.name = "nd_region",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	.type = ND_DRIVER_REGION_BLK | ND_DRIVER_REGION_PMEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int __init nd_region_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	return nd_driver_register(&nd_region_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) void nd_region_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	driver_unregister(&nd_region_driver.drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MODULE_ALIAS_ND_DEVICE(ND_DEVICE_REGION_PMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) MODULE_ALIAS_ND_DEVICE(ND_DEVICE_REGION_BLK);