diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/acpi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/acpi/nfit.c | 55 | ||||
-rw-r--r-- | drivers/acpi/nfit.h | 16 |
3 files changed, 43 insertions, 29 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 114cf48085ab..4baeb853e0c3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -410,6 +410,7 @@ config ACPI_NFIT | |||
410 | tristate "ACPI NVDIMM Firmware Interface Table (NFIT)" | 410 | tristate "ACPI NVDIMM Firmware Interface Table (NFIT)" |
411 | depends on PHYS_ADDR_T_64BIT | 411 | depends on PHYS_ADDR_T_64BIT |
412 | depends on BLK_DEV | 412 | depends on BLK_DEV |
413 | depends on ARCH_HAS_MMIO_FLUSH | ||
413 | select LIBNVDIMM | 414 | select LIBNVDIMM |
414 | help | 415 | help |
415 | Infrastructure to probe ACPI 6 compliant platforms for | 416 | Infrastructure to probe ACPI 6 compliant platforms for |
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 7c2638f914a9..56fff0141636 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c | |||
@@ -1017,7 +1017,7 @@ static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) | |||
1017 | if (mmio->num_lines) | 1017 | if (mmio->num_lines) |
1018 | offset = to_interleave_offset(offset, mmio); | 1018 | offset = to_interleave_offset(offset, mmio); |
1019 | 1019 | ||
1020 | return readq(mmio->base + offset); | 1020 | return readq(mmio->addr.base + offset); |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, | 1023 | static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, |
@@ -1042,11 +1042,11 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, | |||
1042 | if (mmio->num_lines) | 1042 | if (mmio->num_lines) |
1043 | offset = to_interleave_offset(offset, mmio); | 1043 | offset = to_interleave_offset(offset, mmio); |
1044 | 1044 | ||
1045 | writeq(cmd, mmio->base + offset); | 1045 | writeq(cmd, mmio->addr.base + offset); |
1046 | wmb_blk(nfit_blk); | 1046 | wmb_blk(nfit_blk); |
1047 | 1047 | ||
1048 | if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH) | 1048 | if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH) |
1049 | readq(mmio->base + offset); | 1049 | readq(mmio->addr.base + offset); |
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, | 1052 | static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, |
@@ -1078,11 +1078,16 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, | |||
1078 | } | 1078 | } |
1079 | 1079 | ||
1080 | if (rw) | 1080 | if (rw) |
1081 | memcpy_to_pmem(mmio->aperture + offset, | 1081 | memcpy_to_pmem(mmio->addr.aperture + offset, |
1082 | iobuf + copied, c); | 1082 | iobuf + copied, c); |
1083 | else | 1083 | else { |
1084 | if (nfit_blk->dimm_flags & ND_BLK_READ_FLUSH) | ||
1085 | mmio_flush_range((void __force *) | ||
1086 | mmio->addr.aperture + offset, c); | ||
1087 | |||
1084 | memcpy_from_pmem(iobuf + copied, | 1088 | memcpy_from_pmem(iobuf + copied, |
1085 | mmio->aperture + offset, c); | 1089 | mmio->addr.aperture + offset, c); |
1090 | } | ||
1086 | 1091 | ||
1087 | copied += c; | 1092 | copied += c; |
1088 | len -= c; | 1093 | len -= c; |
@@ -1129,7 +1134,10 @@ static void nfit_spa_mapping_release(struct kref *kref) | |||
1129 | 1134 | ||
1130 | WARN_ON(!mutex_is_locked(&acpi_desc->spa_map_mutex)); | 1135 | WARN_ON(!mutex_is_locked(&acpi_desc->spa_map_mutex)); |
1131 | dev_dbg(acpi_desc->dev, "%s: SPA%d\n", __func__, spa->range_index); | 1136 | dev_dbg(acpi_desc->dev, "%s: SPA%d\n", __func__, spa->range_index); |
1132 | iounmap(spa_map->iomem); | 1137 | if (spa_map->type == SPA_MAP_APERTURE) |
1138 | memunmap((void __force *)spa_map->addr.aperture); | ||
1139 | else | ||
1140 | iounmap(spa_map->addr.base); | ||
1133 | release_mem_region(spa->address, spa->length); | 1141 | release_mem_region(spa->address, spa->length); |
1134 | list_del(&spa_map->list); | 1142 | list_del(&spa_map->list); |
1135 | kfree(spa_map); | 1143 | kfree(spa_map); |
@@ -1175,7 +1183,7 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | |||
1175 | spa_map = find_spa_mapping(acpi_desc, spa); | 1183 | spa_map = find_spa_mapping(acpi_desc, spa); |
1176 | if (spa_map) { | 1184 | if (spa_map) { |
1177 | kref_get(&spa_map->kref); | 1185 | kref_get(&spa_map->kref); |
1178 | return spa_map->iomem; | 1186 | return spa_map->addr.base; |
1179 | } | 1187 | } |
1180 | 1188 | ||
1181 | spa_map = kzalloc(sizeof(*spa_map), GFP_KERNEL); | 1189 | spa_map = kzalloc(sizeof(*spa_map), GFP_KERNEL); |
@@ -1191,20 +1199,19 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | |||
1191 | if (!res) | 1199 | if (!res) |
1192 | goto err_mem; | 1200 | goto err_mem; |
1193 | 1201 | ||
1194 | if (type == SPA_MAP_APERTURE) { | 1202 | spa_map->type = type; |
1195 | /* | 1203 | if (type == SPA_MAP_APERTURE) |
1196 | * TODO: memremap_pmem() support, but that requires cache | 1204 | spa_map->addr.aperture = (void __pmem *)memremap(start, n, |
1197 | * flushing when the aperture is moved. | 1205 | ARCH_MEMREMAP_PMEM); |
1198 | */ | 1206 | else |
1199 | spa_map->iomem = ioremap_wc(start, n); | 1207 | spa_map->addr.base = ioremap_nocache(start, n); |
1200 | } else | 1208 | |
1201 | spa_map->iomem = ioremap_nocache(start, n); | ||
1202 | 1209 | ||
1203 | if (!spa_map->iomem) | 1210 | if (!spa_map->addr.base) |
1204 | goto err_map; | 1211 | goto err_map; |
1205 | 1212 | ||
1206 | list_add_tail(&spa_map->list, &acpi_desc->spa_maps); | 1213 | list_add_tail(&spa_map->list, &acpi_desc->spa_maps); |
1207 | return spa_map->iomem; | 1214 | return spa_map->addr.base; |
1208 | 1215 | ||
1209 | err_map: | 1216 | err_map: |
1210 | release_mem_region(start, n); | 1217 | release_mem_region(start, n); |
@@ -1267,7 +1274,7 @@ static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc, | |||
1267 | nfit_blk->dimm_flags = flags.flags; | 1274 | nfit_blk->dimm_flags = flags.flags; |
1268 | else if (rc == -ENOTTY) { | 1275 | else if (rc == -ENOTTY) { |
1269 | /* fall back to a conservative default */ | 1276 | /* fall back to a conservative default */ |
1270 | nfit_blk->dimm_flags = ND_BLK_DCR_LATCH; | 1277 | nfit_blk->dimm_flags = ND_BLK_DCR_LATCH | ND_BLK_READ_FLUSH; |
1271 | rc = 0; | 1278 | rc = 0; |
1272 | } else | 1279 | } else |
1273 | rc = -ENXIO; | 1280 | rc = -ENXIO; |
@@ -1307,9 +1314,9 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
1307 | /* map block aperture memory */ | 1314 | /* map block aperture memory */ |
1308 | nfit_blk->bdw_offset = nfit_mem->bdw->offset; | 1315 | nfit_blk->bdw_offset = nfit_mem->bdw->offset; |
1309 | mmio = &nfit_blk->mmio[BDW]; | 1316 | mmio = &nfit_blk->mmio[BDW]; |
1310 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw, | 1317 | mmio->addr.base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw, |
1311 | SPA_MAP_APERTURE); | 1318 | SPA_MAP_APERTURE); |
1312 | if (!mmio->base) { | 1319 | if (!mmio->addr.base) { |
1313 | dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, | 1320 | dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, |
1314 | nvdimm_name(nvdimm)); | 1321 | nvdimm_name(nvdimm)); |
1315 | return -ENOMEM; | 1322 | return -ENOMEM; |
@@ -1330,9 +1337,9 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
1330 | nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; | 1337 | nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; |
1331 | nfit_blk->stat_offset = nfit_mem->dcr->status_offset; | 1338 | nfit_blk->stat_offset = nfit_mem->dcr->status_offset; |
1332 | mmio = &nfit_blk->mmio[DCR]; | 1339 | mmio = &nfit_blk->mmio[DCR]; |
1333 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr, | 1340 | mmio->addr.base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr, |
1334 | SPA_MAP_CONTROL); | 1341 | SPA_MAP_CONTROL); |
1335 | if (!mmio->base) { | 1342 | if (!mmio->addr.base) { |
1336 | dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, | 1343 | dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, |
1337 | nvdimm_name(nvdimm)); | 1344 | nvdimm_name(nvdimm)); |
1338 | return -ENOMEM; | 1345 | return -ENOMEM; |
@@ -1399,7 +1406,7 @@ static void acpi_nfit_blk_region_disable(struct nvdimm_bus *nvdimm_bus, | |||
1399 | for (i = 0; i < 2; i++) { | 1406 | for (i = 0; i < 2; i++) { |
1400 | struct nfit_blk_mmio *mmio = &nfit_blk->mmio[i]; | 1407 | struct nfit_blk_mmio *mmio = &nfit_blk->mmio[i]; |
1401 | 1408 | ||
1402 | if (mmio->base) | 1409 | if (mmio->addr.base) |
1403 | nfit_spa_unmap(acpi_desc, mmio->spa); | 1410 | nfit_spa_unmap(acpi_desc, mmio->spa); |
1404 | } | 1411 | } |
1405 | nd_blk_region_set_provider_data(ndbr, NULL); | 1412 | nd_blk_region_set_provider_data(ndbr, NULL); |
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index f2c2bb751882..7e740156b9c2 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h | |||
@@ -41,6 +41,7 @@ enum nfit_uuids { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | enum { | 43 | enum { |
44 | ND_BLK_READ_FLUSH = 1, | ||
44 | ND_BLK_DCR_LATCH = 2, | 45 | ND_BLK_DCR_LATCH = 2, |
45 | }; | 46 | }; |
46 | 47 | ||
@@ -117,12 +118,16 @@ enum nd_blk_mmio_selector { | |||
117 | DCR, | 118 | DCR, |
118 | }; | 119 | }; |
119 | 120 | ||
121 | struct nd_blk_addr { | ||
122 | union { | ||
123 | void __iomem *base; | ||
124 | void __pmem *aperture; | ||
125 | }; | ||
126 | }; | ||
127 | |||
120 | struct nfit_blk { | 128 | struct nfit_blk { |
121 | struct nfit_blk_mmio { | 129 | struct nfit_blk_mmio { |
122 | union { | 130 | struct nd_blk_addr addr; |
123 | void __iomem *base; | ||
124 | void __pmem *aperture; | ||
125 | }; | ||
126 | u64 size; | 131 | u64 size; |
127 | u64 base_offset; | 132 | u64 base_offset; |
128 | u32 line_size; | 133 | u32 line_size; |
@@ -149,7 +154,8 @@ struct nfit_spa_mapping { | |||
149 | struct acpi_nfit_system_address *spa; | 154 | struct acpi_nfit_system_address *spa; |
150 | struct list_head list; | 155 | struct list_head list; |
151 | struct kref kref; | 156 | struct kref kref; |
152 | void __iomem *iomem; | 157 | enum spa_map_type type; |
158 | struct nd_blk_addr addr; | ||
153 | }; | 159 | }; |
154 | 160 | ||
155 | static inline struct nfit_spa_mapping *to_spa_map(struct kref *kref) | 161 | static inline struct nfit_spa_mapping *to_spa_map(struct kref *kref) |