xref: /freebsd/sys/dev/nvdimm/nvdimm_ns.c (revision fdafd315)
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/param.h>
288ebb6dddSBen Widawsky #include <sys/bio.h>
298ebb6dddSBen Widawsky #include <sys/bus.h>
308ebb6dddSBen Widawsky #include <sys/malloc.h>
318ebb6dddSBen Widawsky #include <sys/uuid.h>
328ebb6dddSBen Widawsky 
338ebb6dddSBen Widawsky #include <contrib/dev/acpica/include/acpi.h>
348ebb6dddSBen Widawsky #include <dev/acpica/acpivar.h>
358ebb6dddSBen Widawsky #include <dev/nvdimm/nvdimm_var.h>
368ebb6dddSBen Widawsky 
378ebb6dddSBen Widawsky int
nvdimm_create_namespaces(struct SPA_mapping * spa,ACPI_TABLE_NFIT * nfitbl)388ebb6dddSBen Widawsky nvdimm_create_namespaces(struct SPA_mapping *spa, ACPI_TABLE_NFIT *nfitbl)
398ebb6dddSBen Widawsky {
408ebb6dddSBen Widawsky 	ACPI_NFIT_MEMORY_MAP **regions;
418ebb6dddSBen Widawsky 	struct nvdimm_dev *nv;
428ebb6dddSBen Widawsky 	struct nvdimm_label_entry *e;
438ebb6dddSBen Widawsky 	struct nvdimm_namespace *ns;
448ebb6dddSBen Widawsky 	nfit_handle_t dimm_handle;
458ebb6dddSBen Widawsky 	char *name;
468ebb6dddSBen Widawsky 	int i, error, num_regions;
478ebb6dddSBen Widawsky 
488ebb6dddSBen Widawsky 	acpi_nfit_get_region_mappings_by_spa_range(nfitbl, spa->spa_nfit_idx,
498ebb6dddSBen Widawsky 	    &regions, &num_regions);
508ebb6dddSBen Widawsky 	if (num_regions == 0 || num_regions != regions[0]->InterleaveWays) {
518ebb6dddSBen Widawsky 		free(regions, M_NVDIMM);
528ebb6dddSBen Widawsky 		return (ENXIO);
538ebb6dddSBen Widawsky 	}
548ebb6dddSBen Widawsky 	dimm_handle = regions[0]->DeviceHandle;
558ebb6dddSBen Widawsky 	nv = nvdimm_find_by_handle(dimm_handle);
568ebb6dddSBen Widawsky 	if (nv == NULL) {
578ebb6dddSBen Widawsky 		free(regions, M_NVDIMM);
588ebb6dddSBen Widawsky 		return (ENXIO);
598ebb6dddSBen Widawsky 	}
608ebb6dddSBen Widawsky 	i = 0;
618ebb6dddSBen Widawsky 	error = 0;
628ebb6dddSBen Widawsky 	SLIST_FOREACH(e, &nv->labels, link) {
638ebb6dddSBen Widawsky 		ns = malloc(sizeof(struct nvdimm_namespace), M_NVDIMM,
648ebb6dddSBen Widawsky 		    M_WAITOK | M_ZERO);
658ebb6dddSBen Widawsky 		ns->dev.spa_domain = spa->dev.spa_domain;
668ebb6dddSBen Widawsky 		ns->dev.spa_phys_base = spa->dev.spa_phys_base +
678ebb6dddSBen Widawsky 		    regions[0]->RegionOffset +
688ebb6dddSBen Widawsky 		    num_regions *
698ebb6dddSBen Widawsky 		    (e->label.dimm_phys_addr - regions[0]->Address);
708ebb6dddSBen Widawsky 		ns->dev.spa_len = num_regions * e->label.raw_size;
718ebb6dddSBen Widawsky 		ns->dev.spa_efi_mem_flags = spa->dev.spa_efi_mem_flags;
7251501370SConrad Meyer 		ns->dev.spa_memattr = spa->dev.spa_memattr;
738ebb6dddSBen Widawsky 		asprintf(&name, M_NVDIMM, "spa%dns%d", spa->spa_nfit_idx, i);
7443e4b6caSConrad Meyer 		error = nvdimm_spa_dev_init(&ns->dev, name, i);
758ebb6dddSBen Widawsky 		free(name, M_NVDIMM);
768ebb6dddSBen Widawsky 		if (error != 0)
778ebb6dddSBen Widawsky 			break;
788ebb6dddSBen Widawsky 		SLIST_INSERT_HEAD(&spa->namespaces, ns, link);
798ebb6dddSBen Widawsky 		i++;
808ebb6dddSBen Widawsky 	}
818ebb6dddSBen Widawsky 	free(regions, M_NVDIMM);
828ebb6dddSBen Widawsky 	return (error);
838ebb6dddSBen Widawsky }
848ebb6dddSBen Widawsky 
858ebb6dddSBen Widawsky void
nvdimm_destroy_namespaces(struct SPA_mapping * spa)868ebb6dddSBen Widawsky nvdimm_destroy_namespaces(struct SPA_mapping *spa)
878ebb6dddSBen Widawsky {
888ebb6dddSBen Widawsky 	struct nvdimm_namespace *ns, *next;
898ebb6dddSBen Widawsky 
908ebb6dddSBen Widawsky 	SLIST_FOREACH_SAFE(ns, &spa->namespaces, link, next) {
918ebb6dddSBen Widawsky 		SLIST_REMOVE_HEAD(&spa->namespaces, link);
928ebb6dddSBen Widawsky 		nvdimm_spa_dev_fini(&ns->dev);
938ebb6dddSBen Widawsky 		free(ns, M_NVDIMM);
948ebb6dddSBen Widawsky 	}
958ebb6dddSBen Widawsky }
96