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 #include <linux/slab.h> 14 #include <linux/io.h> 15 #include "nd-core.h" 16 #include "nd.h" 17 18 static DEFINE_IDA(region_ida); 19 20 static void nd_region_release(struct device *dev) 21 { 22 struct nd_region *nd_region = to_nd_region(dev); 23 u16 i; 24 25 for (i = 0; i < nd_region->ndr_mappings; i++) { 26 struct nd_mapping *nd_mapping = &nd_region->mapping[i]; 27 struct nvdimm *nvdimm = nd_mapping->nvdimm; 28 29 put_device(&nvdimm->dev); 30 } 31 ida_simple_remove(®ion_ida, nd_region->id); 32 kfree(nd_region); 33 } 34 35 static struct device_type nd_blk_device_type = { 36 .name = "nd_blk", 37 .release = nd_region_release, 38 }; 39 40 static struct device_type nd_pmem_device_type = { 41 .name = "nd_pmem", 42 .release = nd_region_release, 43 }; 44 45 static struct device_type nd_volatile_device_type = { 46 .name = "nd_volatile", 47 .release = nd_region_release, 48 }; 49 50 static bool is_nd_pmem(struct device *dev) 51 { 52 return dev ? dev->type == &nd_pmem_device_type : false; 53 } 54 55 struct nd_region *to_nd_region(struct device *dev) 56 { 57 struct nd_region *nd_region = container_of(dev, struct nd_region, dev); 58 59 WARN_ON(dev->type->release != nd_region_release); 60 return nd_region; 61 } 62 EXPORT_SYMBOL_GPL(to_nd_region); 63 64 static ssize_t size_show(struct device *dev, 65 struct device_attribute *attr, char *buf) 66 { 67 struct nd_region *nd_region = to_nd_region(dev); 68 unsigned long long size = 0; 69 70 if (is_nd_pmem(dev)) { 71 size = nd_region->ndr_size; 72 } else if (nd_region->ndr_mappings == 1) { 73 struct nd_mapping *nd_mapping = &nd_region->mapping[0]; 74 75 size = nd_mapping->size; 76 } 77 78 return sprintf(buf, "%llu\n", size); 79 } 80 static DEVICE_ATTR_RO(size); 81 82 static ssize_t mappings_show(struct device *dev, 83 struct device_attribute *attr, char *buf) 84 { 85 struct nd_region *nd_region = to_nd_region(dev); 86 87 return sprintf(buf, "%d\n", nd_region->ndr_mappings); 88 } 89 static DEVICE_ATTR_RO(mappings); 90 91 static struct attribute *nd_region_attributes[] = { 92 &dev_attr_size.attr, 93 &dev_attr_mappings.attr, 94 NULL, 95 }; 96 97 struct attribute_group nd_region_attribute_group = { 98 .attrs = nd_region_attributes, 99 }; 100 EXPORT_SYMBOL_GPL(nd_region_attribute_group); 101 102 static ssize_t mappingN(struct device *dev, char *buf, int n) 103 { 104 struct nd_region *nd_region = to_nd_region(dev); 105 struct nd_mapping *nd_mapping; 106 struct nvdimm *nvdimm; 107 108 if (n >= nd_region->ndr_mappings) 109 return -ENXIO; 110 nd_mapping = &nd_region->mapping[n]; 111 nvdimm = nd_mapping->nvdimm; 112 113 return sprintf(buf, "%s,%llu,%llu\n", dev_name(&nvdimm->dev), 114 nd_mapping->start, nd_mapping->size); 115 } 116 117 #define REGION_MAPPING(idx) \ 118 static ssize_t mapping##idx##_show(struct device *dev, \ 119 struct device_attribute *attr, char *buf) \ 120 { \ 121 return mappingN(dev, buf, idx); \ 122 } \ 123 static DEVICE_ATTR_RO(mapping##idx) 124 125 /* 126 * 32 should be enough for a while, even in the presence of socket 127 * interleave a 32-way interleave set is a degenerate case. 128 */ 129 REGION_MAPPING(0); 130 REGION_MAPPING(1); 131 REGION_MAPPING(2); 132 REGION_MAPPING(3); 133 REGION_MAPPING(4); 134 REGION_MAPPING(5); 135 REGION_MAPPING(6); 136 REGION_MAPPING(7); 137 REGION_MAPPING(8); 138 REGION_MAPPING(9); 139 REGION_MAPPING(10); 140 REGION_MAPPING(11); 141 REGION_MAPPING(12); 142 REGION_MAPPING(13); 143 REGION_MAPPING(14); 144 REGION_MAPPING(15); 145 REGION_MAPPING(16); 146 REGION_MAPPING(17); 147 REGION_MAPPING(18); 148 REGION_MAPPING(19); 149 REGION_MAPPING(20); 150 REGION_MAPPING(21); 151 REGION_MAPPING(22); 152 REGION_MAPPING(23); 153 REGION_MAPPING(24); 154 REGION_MAPPING(25); 155 REGION_MAPPING(26); 156 REGION_MAPPING(27); 157 REGION_MAPPING(28); 158 REGION_MAPPING(29); 159 REGION_MAPPING(30); 160 REGION_MAPPING(31); 161 162 static umode_t mapping_visible(struct kobject *kobj, struct attribute *a, int n) 163 { 164 struct device *dev = container_of(kobj, struct device, kobj); 165 struct nd_region *nd_region = to_nd_region(dev); 166 167 if (n < nd_region->ndr_mappings) 168 return a->mode; 169 return 0; 170 } 171 172 static struct attribute *mapping_attributes[] = { 173 &dev_attr_mapping0.attr, 174 &dev_attr_mapping1.attr, 175 &dev_attr_mapping2.attr, 176 &dev_attr_mapping3.attr, 177 &dev_attr_mapping4.attr, 178 &dev_attr_mapping5.attr, 179 &dev_attr_mapping6.attr, 180 &dev_attr_mapping7.attr, 181 &dev_attr_mapping8.attr, 182 &dev_attr_mapping9.attr, 183 &dev_attr_mapping10.attr, 184 &dev_attr_mapping11.attr, 185 &dev_attr_mapping12.attr, 186 &dev_attr_mapping13.attr, 187 &dev_attr_mapping14.attr, 188 &dev_attr_mapping15.attr, 189 &dev_attr_mapping16.attr, 190 &dev_attr_mapping17.attr, 191 &dev_attr_mapping18.attr, 192 &dev_attr_mapping19.attr, 193 &dev_attr_mapping20.attr, 194 &dev_attr_mapping21.attr, 195 &dev_attr_mapping22.attr, 196 &dev_attr_mapping23.attr, 197 &dev_attr_mapping24.attr, 198 &dev_attr_mapping25.attr, 199 &dev_attr_mapping26.attr, 200 &dev_attr_mapping27.attr, 201 &dev_attr_mapping28.attr, 202 &dev_attr_mapping29.attr, 203 &dev_attr_mapping30.attr, 204 &dev_attr_mapping31.attr, 205 NULL, 206 }; 207 208 struct attribute_group nd_mapping_attribute_group = { 209 .is_visible = mapping_visible, 210 .attrs = mapping_attributes, 211 }; 212 EXPORT_SYMBOL_GPL(nd_mapping_attribute_group); 213 214 void *nd_region_provider_data(struct nd_region *nd_region) 215 { 216 return nd_region->provider_data; 217 } 218 EXPORT_SYMBOL_GPL(nd_region_provider_data); 219 220 static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, 221 struct nd_region_desc *ndr_desc, struct device_type *dev_type, 222 const char *caller) 223 { 224 struct nd_region *nd_region; 225 struct device *dev; 226 u16 i; 227 228 for (i = 0; i < ndr_desc->num_mappings; i++) { 229 struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; 230 struct nvdimm *nvdimm = nd_mapping->nvdimm; 231 232 if ((nd_mapping->start | nd_mapping->size) % SZ_4K) { 233 dev_err(&nvdimm_bus->dev, "%s: %s mapping%d is not 4K aligned\n", 234 caller, dev_name(&nvdimm->dev), i); 235 236 return NULL; 237 } 238 } 239 240 nd_region = kzalloc(sizeof(struct nd_region) 241 + sizeof(struct nd_mapping) * ndr_desc->num_mappings, 242 GFP_KERNEL); 243 if (!nd_region) 244 return NULL; 245 nd_region->id = ida_simple_get(®ion_ida, 0, 0, GFP_KERNEL); 246 if (nd_region->id < 0) { 247 kfree(nd_region); 248 return NULL; 249 } 250 251 memcpy(nd_region->mapping, ndr_desc->nd_mapping, 252 sizeof(struct nd_mapping) * ndr_desc->num_mappings); 253 for (i = 0; i < ndr_desc->num_mappings; i++) { 254 struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; 255 struct nvdimm *nvdimm = nd_mapping->nvdimm; 256 257 get_device(&nvdimm->dev); 258 } 259 nd_region->ndr_mappings = ndr_desc->num_mappings; 260 nd_region->provider_data = ndr_desc->provider_data; 261 dev = &nd_region->dev; 262 dev_set_name(dev, "region%d", nd_region->id); 263 dev->parent = &nvdimm_bus->dev; 264 dev->type = dev_type; 265 dev->groups = ndr_desc->attr_groups; 266 nd_region->ndr_size = resource_size(ndr_desc->res); 267 nd_region->ndr_start = ndr_desc->res->start; 268 nd_device_register(dev); 269 270 return nd_region; 271 } 272 273 struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus, 274 struct nd_region_desc *ndr_desc) 275 { 276 return nd_region_create(nvdimm_bus, ndr_desc, &nd_pmem_device_type, 277 __func__); 278 } 279 EXPORT_SYMBOL_GPL(nvdimm_pmem_region_create); 280 281 struct nd_region *nvdimm_blk_region_create(struct nvdimm_bus *nvdimm_bus, 282 struct nd_region_desc *ndr_desc) 283 { 284 if (ndr_desc->num_mappings > 1) 285 return NULL; 286 return nd_region_create(nvdimm_bus, ndr_desc, &nd_blk_device_type, 287 __func__); 288 } 289 EXPORT_SYMBOL_GPL(nvdimm_blk_region_create); 290 291 struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus, 292 struct nd_region_desc *ndr_desc) 293 { 294 return nd_region_create(nvdimm_bus, ndr_desc, &nd_volatile_device_type, 295 __func__); 296 } 297 EXPORT_SYMBOL_GPL(nvdimm_volatile_region_create); 298