18ebb6dddSBen Widawsky /*- 28ebb6dddSBen Widawsky * Copyright (c) 2018 Intel Corporation 38ebb6dddSBen Widawsky * All rights reserved. 48ebb6dddSBen Widawsky * 58ebb6dddSBen Widawsky * Redistribution and use in source and binary forms, with or without 68ebb6dddSBen Widawsky * modification, are permitted provided that the following conditions 78ebb6dddSBen Widawsky * are met: 88ebb6dddSBen Widawsky * 1. Redistributions of source code must retain the above copyright 98ebb6dddSBen Widawsky * notice, this list of conditions and the following disclaimer. 108ebb6dddSBen Widawsky * 2. Redistributions in binary form must reproduce the above copyright 118ebb6dddSBen Widawsky * notice, this list of conditions and the following disclaimer in the 128ebb6dddSBen Widawsky * documentation and/or other materials provided with the distribution. 138ebb6dddSBen Widawsky * 148ebb6dddSBen Widawsky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158ebb6dddSBen Widawsky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168ebb6dddSBen Widawsky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 178ebb6dddSBen Widawsky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 188ebb6dddSBen Widawsky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 198ebb6dddSBen Widawsky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 208ebb6dddSBen Widawsky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 218ebb6dddSBen Widawsky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 228ebb6dddSBen Widawsky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 238ebb6dddSBen Widawsky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 248ebb6dddSBen Widawsky * SUCH DAMAGE. 258ebb6dddSBen Widawsky */ 268ebb6dddSBen Widawsky 278ebb6dddSBen Widawsky #include <sys/cdefs.h> 288ebb6dddSBen Widawsky __FBSDID("$FreeBSD$"); 298ebb6dddSBen Widawsky 308ebb6dddSBen Widawsky #include <sys/param.h> 318ebb6dddSBen Widawsky #include <sys/bio.h> 328ebb6dddSBen Widawsky #include <sys/bus.h> 338ebb6dddSBen Widawsky #include <sys/malloc.h> 348ebb6dddSBen Widawsky #include <sys/uuid.h> 358ebb6dddSBen Widawsky 368ebb6dddSBen Widawsky #include <contrib/dev/acpica/include/acpi.h> 378ebb6dddSBen Widawsky #include <dev/acpica/acpivar.h> 388ebb6dddSBen Widawsky #include <dev/nvdimm/nvdimm_var.h> 398ebb6dddSBen Widawsky 408ebb6dddSBen Widawsky int 418ebb6dddSBen Widawsky nvdimm_create_namespaces(struct SPA_mapping *spa, ACPI_TABLE_NFIT *nfitbl) 428ebb6dddSBen Widawsky { 438ebb6dddSBen Widawsky ACPI_NFIT_MEMORY_MAP **regions; 448ebb6dddSBen Widawsky struct nvdimm_dev *nv; 458ebb6dddSBen Widawsky struct nvdimm_label_entry *e; 468ebb6dddSBen Widawsky struct nvdimm_namespace *ns; 478ebb6dddSBen Widawsky nfit_handle_t dimm_handle; 488ebb6dddSBen Widawsky char *name; 498ebb6dddSBen Widawsky int i, error, num_regions; 508ebb6dddSBen Widawsky 518ebb6dddSBen Widawsky acpi_nfit_get_region_mappings_by_spa_range(nfitbl, spa->spa_nfit_idx, 528ebb6dddSBen Widawsky ®ions, &num_regions); 538ebb6dddSBen Widawsky if (num_regions == 0 || num_regions != regions[0]->InterleaveWays) { 548ebb6dddSBen Widawsky free(regions, M_NVDIMM); 558ebb6dddSBen Widawsky return (ENXIO); 568ebb6dddSBen Widawsky } 578ebb6dddSBen Widawsky dimm_handle = regions[0]->DeviceHandle; 588ebb6dddSBen Widawsky nv = nvdimm_find_by_handle(dimm_handle); 598ebb6dddSBen Widawsky if (nv == NULL) { 608ebb6dddSBen Widawsky free(regions, M_NVDIMM); 618ebb6dddSBen Widawsky return (ENXIO); 628ebb6dddSBen Widawsky } 638ebb6dddSBen Widawsky i = 0; 648ebb6dddSBen Widawsky error = 0; 658ebb6dddSBen Widawsky SLIST_FOREACH(e, &nv->labels, link) { 668ebb6dddSBen Widawsky ns = malloc(sizeof(struct nvdimm_namespace), M_NVDIMM, 678ebb6dddSBen Widawsky M_WAITOK | M_ZERO); 688ebb6dddSBen Widawsky ns->dev.spa_domain = spa->dev.spa_domain; 698ebb6dddSBen Widawsky ns->dev.spa_phys_base = spa->dev.spa_phys_base + 708ebb6dddSBen Widawsky regions[0]->RegionOffset + 718ebb6dddSBen Widawsky num_regions * 728ebb6dddSBen Widawsky (e->label.dimm_phys_addr - regions[0]->Address); 738ebb6dddSBen Widawsky ns->dev.spa_len = num_regions * e->label.raw_size; 748ebb6dddSBen Widawsky ns->dev.spa_efi_mem_flags = spa->dev.spa_efi_mem_flags; 7551501370SConrad Meyer ns->dev.spa_memattr = spa->dev.spa_memattr; 768ebb6dddSBen Widawsky asprintf(&name, M_NVDIMM, "spa%dns%d", spa->spa_nfit_idx, i); 7743e4b6caSConrad Meyer error = nvdimm_spa_dev_init(&ns->dev, name, i); 788ebb6dddSBen Widawsky free(name, M_NVDIMM); 798ebb6dddSBen Widawsky if (error != 0) 808ebb6dddSBen Widawsky break; 818ebb6dddSBen Widawsky SLIST_INSERT_HEAD(&spa->namespaces, ns, link); 828ebb6dddSBen Widawsky i++; 838ebb6dddSBen Widawsky } 848ebb6dddSBen Widawsky free(regions, M_NVDIMM); 858ebb6dddSBen Widawsky return (error); 868ebb6dddSBen Widawsky } 878ebb6dddSBen Widawsky 888ebb6dddSBen Widawsky void 898ebb6dddSBen Widawsky nvdimm_destroy_namespaces(struct SPA_mapping *spa) 908ebb6dddSBen Widawsky { 918ebb6dddSBen Widawsky struct nvdimm_namespace *ns, *next; 928ebb6dddSBen Widawsky 938ebb6dddSBen Widawsky SLIST_FOREACH_SAFE(ns, &spa->namespaces, link, next) { 948ebb6dddSBen Widawsky SLIST_REMOVE_HEAD(&spa->namespaces, link); 958ebb6dddSBen Widawsky nvdimm_spa_dev_fini(&ns->dev); 968ebb6dddSBen Widawsky free(ns, M_NVDIMM); 978ebb6dddSBen Widawsky } 988ebb6dddSBen Widawsky } 99