1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. 4 */ 5 #ifndef __LABEL_H__ 6 #define __LABEL_H__ 7 8 #include <linux/ndctl.h> 9 #include <linux/sizes.h> 10 #include <linux/uuid.h> 11 #include <linux/io.h> 12 13 enum { 14 NSINDEX_SIG_LEN = 16, 15 NSINDEX_ALIGN = 256, 16 NSINDEX_SEQ_MASK = 0x3, 17 NSLABEL_UUID_LEN = 16, 18 NSLABEL_NAME_LEN = 64, 19 NSLABEL_FLAG_ROLABEL = 0x1, /* read-only label */ 20 NSLABEL_FLAG_LOCAL = 0x2, /* DIMM-local namespace */ 21 NSLABEL_FLAG_BTT = 0x4, /* namespace contains a BTT */ 22 NSLABEL_FLAG_UPDATING = 0x8, /* label being updated */ 23 BTT_ALIGN = 4096, /* all btt structures */ 24 BTTINFO_SIG_LEN = 16, 25 BTTINFO_UUID_LEN = 16, 26 BTTINFO_FLAG_ERROR = 0x1, /* error state (read-only) */ 27 BTTINFO_MAJOR_VERSION = 1, 28 ND_LABEL_MIN_SIZE = 256 * 4, /* see sizeof_namespace_index() */ 29 ND_LABEL_ID_SIZE = 50, 30 ND_NSINDEX_INIT = 0x1, 31 }; 32 33 /** 34 * struct nd_namespace_index - label set superblock 35 * @sig: NAMESPACE_INDEX\0 36 * @flags: placeholder 37 * @labelsize: log2 size (v1 labels 128 bytes v2 labels 256 bytes) 38 * @seq: sequence number for this index 39 * @myoff: offset of this index in label area 40 * @mysize: size of this index struct 41 * @otheroff: offset of other index 42 * @labeloff: offset of first label slot 43 * @nslot: total number of label slots 44 * @major: label area major version 45 * @minor: label area minor version 46 * @checksum: fletcher64 of all fields 47 * @free: bitmap, nlabel bits 48 * 49 * The size of free[] is rounded up so the total struct size is a 50 * multiple of NSINDEX_ALIGN bytes. Any bits this allocates beyond 51 * nlabel bits must be zero. 52 */ 53 struct nd_namespace_index { 54 u8 sig[NSINDEX_SIG_LEN]; 55 u8 flags[3]; 56 u8 labelsize; 57 __le32 seq; 58 __le64 myoff; 59 __le64 mysize; 60 __le64 otheroff; 61 __le64 labeloff; 62 __le32 nslot; 63 __le16 major; 64 __le16 minor; 65 __le64 checksum; 66 u8 free[]; 67 }; 68 69 /** 70 * struct cxl_region_label - CXL 2.0 Table 211 71 * @type: uuid identifying this label format (region) 72 * @uuid: uuid for the region this label describes 73 * @flags: NSLABEL_FLAG_UPDATING (all other flags reserved) 74 * @nlabel: 1 per interleave-way in the region 75 * @position: this label's position in the set 76 * @dpa: start address in device-local capacity for this label 77 * @rawsize: size of this label's contribution to region 78 * @hpa: mandatory system physical address to map this region 79 * @slot: slot id of this label in label area 80 * @ig: interleave granularity (1 << @ig) * 256 bytes 81 * @align: alignment in SZ_256M blocks 82 * @reserved: reserved 83 * @checksum: fletcher64 sum of this label 84 */ 85 struct cxl_region_label { 86 u8 type[NSLABEL_UUID_LEN]; 87 u8 uuid[NSLABEL_UUID_LEN]; 88 __le32 flags; 89 __le16 nlabel; 90 __le16 position; 91 __le64 dpa; 92 __le64 rawsize; 93 __le64 hpa; 94 __le32 slot; 95 __le32 ig; 96 __le32 align; 97 u8 reserved[0xac]; 98 __le64 checksum; 99 }; 100 101 /** 102 * struct nvdimm_efi_label - namespace superblock 103 * @uuid: UUID per RFC 4122 104 * @name: optional name (NULL-terminated) 105 * @flags: see NSLABEL_FLAG_* 106 * @nlabel: num labels to describe this ns 107 * @position: labels position in set 108 * @isetcookie: interleave set cookie 109 * @lbasize: LBA size in bytes or 0 for pmem 110 * @dpa: DPA of NVM range on this DIMM 111 * @rawsize: size of namespace 112 * @slot: slot of this label in label area 113 * @align: physical address alignment of the namespace 114 * @reserved: reserved 115 * @type_guid: copy of struct acpi_nfit_system_address.range_guid 116 * @abstraction_guid: personality id (btt, btt2, fsdax, devdax....) 117 * @reserved2: reserved 118 * @checksum: fletcher64 sum of this object 119 */ 120 struct nvdimm_efi_label { 121 u8 uuid[NSLABEL_UUID_LEN]; 122 u8 name[NSLABEL_NAME_LEN]; 123 __le32 flags; 124 __le16 nlabel; 125 __le16 position; 126 __le64 isetcookie; 127 __le64 lbasize; 128 __le64 dpa; 129 __le64 rawsize; 130 __le32 slot; 131 /* 132 * Accessing fields past this point should be gated by a 133 * efi_namespace_label_has() check. 134 */ 135 u8 align; 136 u8 reserved[3]; 137 guid_t type_guid; 138 guid_t abstraction_guid; 139 u8 reserved2[88]; 140 __le64 checksum; 141 }; 142 143 /** 144 * struct nvdimm_cxl_label - CXL 2.0 Table 212 145 * @type: uuid identifying this label format (namespace) 146 * @uuid: uuid for the namespace this label describes 147 * @name: friendly name for the namespace 148 * @flags: NSLABEL_FLAG_UPDATING (all other flags reserved) 149 * @nrange: discontiguous namespace support 150 * @position: this label's position in the set 151 * @dpa: start address in device-local capacity for this label 152 * @rawsize: size of this label's contribution to namespace 153 * @slot: slot id of this label in label area 154 * @align: alignment in SZ_256M blocks 155 * @region_uuid: host interleave set identifier 156 * @abstraction_uuid: personality driver for this namespace 157 * @lbasize: address geometry for disk-like personalities 158 * @reserved: reserved 159 * @checksum: fletcher64 sum of this label 160 */ 161 struct nvdimm_cxl_label { 162 u8 type[NSLABEL_UUID_LEN]; 163 u8 uuid[NSLABEL_UUID_LEN]; 164 u8 name[NSLABEL_NAME_LEN]; 165 __le32 flags; 166 __le16 nrange; 167 __le16 position; 168 __le64 dpa; 169 __le64 rawsize; 170 __le32 slot; 171 __le32 align; 172 u8 region_uuid[16]; 173 u8 abstraction_uuid[16]; 174 __le16 lbasize; 175 u8 reserved[0x56]; 176 __le64 checksum; 177 }; 178 179 struct nd_namespace_label { 180 union { 181 struct nvdimm_cxl_label cxl; 182 struct nvdimm_efi_label efi; 183 }; 184 }; 185 186 #define NVDIMM_BTT_GUID "8aed63a2-29a2-4c66-8b12-f05d15d3922a" 187 #define NVDIMM_BTT2_GUID "18633bfc-1735-4217-8ac9-17239282d3f8" 188 #define NVDIMM_PFN_GUID "266400ba-fb9f-4677-bcb0-968f11d0d225" 189 #define NVDIMM_DAX_GUID "97a86d9c-3cdd-4eda-986f-5068b4f80088" 190 191 #define CXL_REGION_UUID "529d7c61-da07-47c4-a93f-ecdf2c06f444" 192 #define CXL_NAMESPACE_UUID "68bb2c0a-5a77-4937-9f85-3caf41a0f93c" 193 194 /** 195 * struct nd_label_id - identifier string for dpa allocation 196 * @id: "pmem-<namespace uuid>" 197 */ 198 struct nd_label_id { 199 char id[ND_LABEL_ID_SIZE]; 200 }; 201 202 /* 203 * If the 'best' index is invalid, so is the 'next' index. Otherwise, 204 * the next index is MOD(index+1, 2) 205 */ 206 static inline int nd_label_next_nsindex(int index) 207 { 208 if (index < 0) 209 return -1; 210 211 return (index + 1) % 2; 212 } 213 214 struct nvdimm_drvdata; 215 int nd_label_data_init(struct nvdimm_drvdata *ndd); 216 size_t sizeof_namespace_index(struct nvdimm_drvdata *ndd); 217 int nd_label_active_count(struct nvdimm_drvdata *ndd); 218 struct nd_namespace_label *nd_label_active(struct nvdimm_drvdata *ndd, int n); 219 u32 nd_label_alloc_slot(struct nvdimm_drvdata *ndd); 220 bool nd_label_free_slot(struct nvdimm_drvdata *ndd, u32 slot); 221 u32 nd_label_nfree(struct nvdimm_drvdata *ndd); 222 struct nd_region; 223 struct nd_namespace_pmem; 224 int nd_pmem_namespace_label_update(struct nd_region *nd_region, 225 struct nd_namespace_pmem *nspm, resource_size_t size); 226 #endif /* __LABEL_H__ */ 227