Skip to content

Commit 30280ee

Browse files
lsgunthChristoph Hellwig
authored andcommitted
iommu/dma: support PCI P2PDMA pages in dma-iommu map_sg
Call pci_p2pdma_map_segment() when a PCI P2PDMA page is seen so the bus address is set in the dma address and the segment is marked with sg_dma_mark_bus_address(). iommu_map_sg() will then skip these segments. Then, in __finalise_sg(), copy the dma address from the input segment to the output segment. __invalidate_sg() must also learn to skip these segments. A P2PDMA page may have three possible outcomes when being mapped: 1) If the data path between the two devices doesn't go through the root port, then it should be mapped with a PCI bus address 2) If the data path goes through the host bridge, it should be mapped normally with an IOMMU IOVA. 3) It is not possible for the two devices to communicate and thus the mapping operation should fail (and it will return -EREMOTEIO). Similar to dma-direct, the sg_dma_mark_pci_p2pdma() flag is used to indicate bus address segments. On unmap, P2PDMA segments are skipped over when determining the start and end IOVA addresses. With this change, the flags variable in the dma_map_ops is set to DMA_F_PCI_P2PDMA_SUPPORTED to indicate support for P2PDMA pages. Signed-off-by: Logan Gunthorpe <logang@deltatee.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent c963218 commit 30280ee

1 file changed

Lines changed: 85 additions & 14 deletions

File tree

drivers/iommu/dma-iommu.c

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/iova.h>
2222
#include <linux/irq.h>
2323
#include <linux/list_sort.h>
24+
#include <linux/memremap.h>
2425
#include <linux/mm.h>
2526
#include <linux/mutex.h>
2627
#include <linux/pci.h>
@@ -1053,15 +1054,30 @@ static int __finalise_sg(struct device *dev, struct scatterlist *sg, int nents,
10531054

10541055
for_each_sg(sg, s, nents, i) {
10551056
/* Restore this segment's original unaligned fields first */
1057+
dma_addr_t s_dma_addr = sg_dma_address(s);
10561058
unsigned int s_iova_off = sg_dma_address(s);
10571059
unsigned int s_length = sg_dma_len(s);
10581060
unsigned int s_iova_len = s->length;
10591061

1060-
s->offset += s_iova_off;
1061-
s->length = s_length;
10621062
sg_dma_address(s) = DMA_MAPPING_ERROR;
10631063
sg_dma_len(s) = 0;
10641064

1065+
if (sg_is_dma_bus_address(s)) {
1066+
if (i > 0)
1067+
cur = sg_next(cur);
1068+
1069+
sg_dma_unmark_bus_address(s);
1070+
sg_dma_address(cur) = s_dma_addr;
1071+
sg_dma_len(cur) = s_length;
1072+
sg_dma_mark_bus_address(cur);
1073+
count++;
1074+
cur_len = 0;
1075+
continue;
1076+
}
1077+
1078+
s->offset += s_iova_off;
1079+
s->length = s_length;
1080+
10651081
/*
10661082
* Now fill in the real DMA data. If...
10671083
* - there is a valid output segment to append to
@@ -1102,10 +1118,14 @@ static void __invalidate_sg(struct scatterlist *sg, int nents)
11021118
int i;
11031119

11041120
for_each_sg(sg, s, nents, i) {
1105-
if (sg_dma_address(s) != DMA_MAPPING_ERROR)
1106-
s->offset += sg_dma_address(s);
1107-
if (sg_dma_len(s))
1108-
s->length = sg_dma_len(s);
1121+
if (sg_is_dma_bus_address(s)) {
1122+
sg_dma_unmark_bus_address(s);
1123+
} else {
1124+
if (sg_dma_address(s) != DMA_MAPPING_ERROR)
1125+
s->offset += sg_dma_address(s);
1126+
if (sg_dma_len(s))
1127+
s->length = sg_dma_len(s);
1128+
}
11091129
sg_dma_address(s) = DMA_MAPPING_ERROR;
11101130
sg_dma_len(s) = 0;
11111131
}
@@ -1158,6 +1178,8 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
11581178
struct iova_domain *iovad = &cookie->iovad;
11591179
struct scatterlist *s, *prev = NULL;
11601180
int prot = dma_info_to_prot(dir, dev_is_dma_coherent(dev), attrs);
1181+
struct pci_p2pdma_map_state p2pdma_state = {};
1182+
enum pci_p2pdma_map_type map;
11611183
dma_addr_t iova;
11621184
size_t iova_len = 0;
11631185
unsigned long mask = dma_get_seg_boundary(dev);
@@ -1187,6 +1209,30 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
11871209
size_t s_length = s->length;
11881210
size_t pad_len = (mask - iova_len + 1) & mask;
11891211

1212+
if (is_pci_p2pdma_page(sg_page(s))) {
1213+
map = pci_p2pdma_map_segment(&p2pdma_state, dev, s);
1214+
switch (map) {
1215+
case PCI_P2PDMA_MAP_BUS_ADDR:
1216+
/*
1217+
* iommu_map_sg() will skip this segment as
1218+
* it is marked as a bus address,
1219+
* __finalise_sg() will copy the dma address
1220+
* into the output segment.
1221+
*/
1222+
continue;
1223+
case PCI_P2PDMA_MAP_THRU_HOST_BRIDGE:
1224+
/*
1225+
* Mapping through host bridge should be
1226+
* mapped with regular IOVAs, thus we
1227+
* do nothing here and continue below.
1228+
*/
1229+
break;
1230+
default:
1231+
ret = -EREMOTEIO;
1232+
goto out_restore_sg;
1233+
}
1234+
}
1235+
11901236
sg_dma_address(s) = s_iova_off;
11911237
sg_dma_len(s) = s_length;
11921238
s->offset -= s_iova_off;
@@ -1215,6 +1261,9 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
12151261
prev = s;
12161262
}
12171263

1264+
if (!iova_len)
1265+
return __finalise_sg(dev, sg, nents, 0);
1266+
12181267
iova = iommu_dma_alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
12191268
if (!iova) {
12201269
ret = -ENOMEM;
@@ -1236,15 +1285,15 @@ static int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
12361285
out_restore_sg:
12371286
__invalidate_sg(sg, nents);
12381287
out:
1239-
if (ret != -ENOMEM)
1288+
if (ret != -ENOMEM && ret != -EREMOTEIO)
12401289
return -EINVAL;
12411290
return ret;
12421291
}
12431292

12441293
static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
12451294
int nents, enum dma_data_direction dir, unsigned long attrs)
12461295
{
1247-
dma_addr_t start, end;
1296+
dma_addr_t end = 0, start;
12481297
struct scatterlist *tmp;
12491298
int i;
12501299

@@ -1258,16 +1307,37 @@ static void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
12581307

12591308
/*
12601309
* The scatterlist segments are mapped into a single
1261-
* contiguous IOVA allocation, so this is incredibly easy.
1310+
* contiguous IOVA allocation, the start and end points
1311+
* just have to be determined.
12621312
*/
1263-
start = sg_dma_address(sg);
1264-
for_each_sg(sg_next(sg), tmp, nents - 1, i) {
1313+
for_each_sg(sg, tmp, nents, i) {
1314+
if (sg_is_dma_bus_address(tmp)) {
1315+
sg_dma_unmark_bus_address(tmp);
1316+
continue;
1317+
}
1318+
1319+
if (sg_dma_len(tmp) == 0)
1320+
break;
1321+
1322+
start = sg_dma_address(tmp);
1323+
break;
1324+
}
1325+
1326+
nents -= i;
1327+
for_each_sg(tmp, tmp, nents, i) {
1328+
if (sg_is_dma_bus_address(tmp)) {
1329+
sg_dma_unmark_bus_address(tmp);
1330+
continue;
1331+
}
1332+
12651333
if (sg_dma_len(tmp) == 0)
12661334
break;
1267-
sg = tmp;
1335+
1336+
end = sg_dma_address(tmp) + sg_dma_len(tmp);
12681337
}
1269-
end = sg_dma_address(sg) + sg_dma_len(sg);
1270-
__iommu_dma_unmap(dev, start, end - start);
1338+
1339+
if (end)
1340+
__iommu_dma_unmap(dev, start, end - start);
12711341
}
12721342

12731343
static dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
@@ -1465,6 +1535,7 @@ static size_t iommu_dma_opt_mapping_size(void)
14651535
}
14661536

14671537
static const struct dma_map_ops iommu_dma_ops = {
1538+
.flags = DMA_F_PCI_P2PDMA_SUPPORTED,
14681539
.alloc = iommu_dma_alloc,
14691540
.free = iommu_dma_free,
14701541
.alloc_pages = dma_common_alloc_pages,

0 commit comments

Comments
 (0)