Skip to content

Commit d16945f

Browse files
Tomer Tayarogabbay
authored andcommitted
accel/habanalabs: add missing offset handling for dma-buf
On devices with virtual device memory (Gaudi2 onwards), user can provide an offset within an allocated device memory from which he wants to export a dma-buf object. The offset value is verified by driver, but it is not taken into consideration when the importer driver maps the dma-buf and the SG table it prepared. Add the missing offset handling. Signed-off-by: Tomer Tayar <ttayar@habana.ai> Reviewed-by: Oded Gabbay <ogabbay@kernel.org> Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
1 parent 878ebc1 commit d16945f

2 files changed

Lines changed: 43 additions & 35 deletions

File tree

drivers/accel/habanalabs/common/habanalabs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,8 @@ struct hl_cs_counters_atomic {
18111811
* @phys_pg_pack: pointer to physical page pack if the dma-buf was exported
18121812
* where virtual memory is supported.
18131813
* @memhash_hnode: pointer to the memhash node. this object holds the export count.
1814+
* @offset: the offset into the buffer from which the memory is exported.
1815+
* Relevant only if virtual memory is supported and phys_pg_pack is being used.
18141816
* device_phys_addr: physical address of the device's memory. Relevant only
18151817
* if phys_pg_pack is NULL (dma-buf was exported from address).
18161818
* The total size can be taken from the dmabuf object.
@@ -1820,6 +1822,7 @@ struct hl_dmabuf_priv {
18201822
struct hl_ctx *ctx;
18211823
struct hl_vm_phys_pg_pack *phys_pg_pack;
18221824
struct hl_vm_hash_node *memhash_hnode;
1825+
u64 offset;
18231826
u64 device_phys_addr;
18241827
};
18251828

drivers/accel/habanalabs/common/memory.c

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,11 +1532,11 @@ static int set_dma_sg(struct scatterlist *sg, u64 bar_address, u64 chunk_size,
15321532
}
15331533

15341534
static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 *pages, u64 npages,
1535-
u64 page_size, u64 exported_size,
1535+
u64 page_size, u64 exported_size, u64 offset,
15361536
struct device *dev, enum dma_data_direction dir)
15371537
{
15381538
u64 dma_max_seg_size, curr_page, size, chunk_size, left_size_to_export, left_size_in_page,
1539-
left_size_in_dma_seg, device_address, bar_address;
1539+
left_size_in_dma_seg, device_address, bar_address, start_page;
15401540
struct asic_fixed_properties *prop = &hdev->asic_prop;
15411541
struct scatterlist *sg;
15421542
unsigned int nents, i;
@@ -1557,11 +1557,20 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64
15571557
if (!sgt)
15581558
return ERR_PTR(-ENOMEM);
15591559

1560+
/* Use the offset to move to the actual first page that is exported */
1561+
for (start_page = 0 ; start_page < npages ; ++start_page) {
1562+
if (offset < page_size)
1563+
break;
1564+
1565+
/* The offset value was validated so there can't be an underflow */
1566+
offset -= page_size;
1567+
}
1568+
15601569
/* Calculate the required number of entries for the SG table */
1561-
curr_page = 0;
1570+
curr_page = start_page;
15621571
nents = 1;
15631572
left_size_to_export = exported_size;
1564-
left_size_in_page = page_size;
1573+
left_size_in_page = page_size - offset;
15651574
left_size_in_dma_seg = dma_max_seg_size;
15661575
next_sg_entry = false;
15671576

@@ -1599,10 +1608,10 @@ static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64
15991608
goto err_free_sgt;
16001609

16011610
/* Prepare the SG table entries */
1602-
curr_page = 0;
1603-
device_address = pages[curr_page];
1611+
curr_page = start_page;
1612+
device_address = pages[curr_page] + offset;
16041613
left_size_to_export = exported_size;
1605-
left_size_in_page = page_size;
1614+
left_size_in_page = page_size - offset;
16061615
left_size_in_dma_seg = dma_max_seg_size;
16071616
next_sg_entry = false;
16081617

@@ -1708,7 +1717,7 @@ static int hl_dmabuf_attach(struct dma_buf *dmabuf,
17081717
static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
17091718
enum dma_data_direction dir)
17101719
{
1711-
u64 *pages, npages, page_size, exported_size;
1720+
u64 *pages, npages, page_size, exported_size, offset;
17121721
struct dma_buf *dma_buf = attachment->dmabuf;
17131722
struct hl_vm_phys_pg_pack *phys_pg_pack;
17141723
struct hl_dmabuf_priv *hl_dmabuf;
@@ -1724,6 +1733,7 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
17241733
}
17251734

17261735
exported_size = hl_dmabuf->dmabuf->size;
1736+
offset = hl_dmabuf->offset;
17271737
phys_pg_pack = hl_dmabuf->phys_pg_pack;
17281738

17291739
if (phys_pg_pack) {
@@ -1736,7 +1746,7 @@ static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment,
17361746
page_size = hl_dmabuf->dmabuf->size;
17371747
}
17381748

1739-
sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size, exported_size,
1749+
sgt = alloc_sgt_from_device_pages(hdev, pages, npages, page_size, exported_size, offset,
17401750
attachment->dev, dir);
17411751
if (IS_ERR(sgt))
17421752
dev_err(hdev->dev, "failed (%ld) to initialize sgt for dmabuf\n", PTR_ERR(sgt));
@@ -1882,12 +1892,12 @@ static int export_dmabuf(struct hl_ctx *ctx,
18821892
return rc;
18831893
}
18841894

1885-
static int validate_export_params_common(struct hl_device *hdev, u64 device_addr, u64 size)
1895+
static int validate_export_params_common(struct hl_device *hdev, u64 addr, u64 size, u64 offset)
18861896
{
1887-
if (!PAGE_ALIGNED(device_addr)) {
1897+
if (!PAGE_ALIGNED(addr)) {
18881898
dev_dbg(hdev->dev,
18891899
"exported device memory address 0x%llx should be aligned to PAGE_SIZE 0x%lx\n",
1890-
device_addr, PAGE_SIZE);
1900+
addr, PAGE_SIZE);
18911901
return -EINVAL;
18921902
}
18931903

@@ -1898,6 +1908,13 @@ static int validate_export_params_common(struct hl_device *hdev, u64 device_addr
18981908
return -EINVAL;
18991909
}
19001910

1911+
if (!PAGE_ALIGNED(offset)) {
1912+
dev_dbg(hdev->dev,
1913+
"exported device memory offset %llu should be a multiple of PAGE_SIZE %lu\n",
1914+
offset, PAGE_SIZE);
1915+
return -EINVAL;
1916+
}
1917+
19011918
return 0;
19021919
}
19031920

@@ -1907,13 +1924,13 @@ static int validate_export_params_no_mmu(struct hl_device *hdev, u64 device_addr
19071924
u64 bar_address;
19081925
int rc;
19091926

1910-
rc = validate_export_params_common(hdev, device_addr, size);
1927+
rc = validate_export_params_common(hdev, device_addr, size, 0);
19111928
if (rc)
19121929
return rc;
19131930

19141931
if (device_addr < prop->dram_user_base_address ||
1915-
(device_addr + size) > prop->dram_end_address ||
1916-
(device_addr + size) < device_addr) {
1932+
(device_addr + size) > prop->dram_end_address ||
1933+
(device_addr + size) < device_addr) {
19171934
dev_dbg(hdev->dev,
19181935
"DRAM memory range 0x%llx (+0x%llx) is outside of DRAM boundaries\n",
19191936
device_addr, size);
@@ -1940,36 +1957,26 @@ static int validate_export_params(struct hl_device *hdev, u64 device_addr, u64 s
19401957
u64 bar_address;
19411958
int i, rc;
19421959

1943-
rc = validate_export_params_common(hdev, device_addr, size);
1960+
rc = validate_export_params_common(hdev, device_addr, size, offset);
19441961
if (rc)
19451962
return rc;
19461963

1947-
if (!PAGE_ALIGNED(offset)) {
1948-
dev_dbg(hdev->dev,
1949-
"exported device memory offset %llu should be a multiple of PAGE_SIZE %lu\n",
1950-
offset, PAGE_SIZE);
1951-
return -EINVAL;
1952-
}
1953-
19541964
if ((offset + size) > phys_pg_pack->total_size) {
19551965
dev_dbg(hdev->dev, "offset %#llx and size %#llx exceed total map size %#llx\n",
1956-
offset, size, phys_pg_pack->total_size);
1966+
offset, size, phys_pg_pack->total_size);
19571967
return -EINVAL;
19581968
}
19591969

19601970
for (i = 0 ; i < phys_pg_pack->npages ; i++) {
1961-
19621971
bar_address = hdev->dram_pci_bar_start +
1963-
(phys_pg_pack->pages[i] - prop->dram_base_address);
1972+
(phys_pg_pack->pages[i] - prop->dram_base_address);
19641973

19651974
if ((bar_address + phys_pg_pack->page_size) >
19661975
(hdev->dram_pci_bar_start + prop->dram_pci_bar_size) ||
19671976
(bar_address + phys_pg_pack->page_size) < bar_address) {
19681977
dev_dbg(hdev->dev,
19691978
"DRAM memory range 0x%llx (+0x%x) is outside of PCI BAR boundaries\n",
1970-
phys_pg_pack->pages[i],
1971-
phys_pg_pack->page_size);
1972-
1979+
phys_pg_pack->pages[i], phys_pg_pack->page_size);
19731980
return -EINVAL;
19741981
}
19751982
}
@@ -2025,7 +2032,6 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
20252032
struct asic_fixed_properties *prop;
20262033
struct hl_dmabuf_priv *hl_dmabuf;
20272034
struct hl_device *hdev;
2028-
u64 export_addr;
20292035
int rc;
20302036

20312037
hdev = ctx->hdev;
@@ -2037,8 +2043,6 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
20372043
return -EINVAL;
20382044
}
20392045

2040-
export_addr = addr + offset;
2041-
20422046
hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL);
20432047
if (!hl_dmabuf)
20442048
return -ENOMEM;
@@ -2054,18 +2058,19 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 addr, u64 size, u64 o
20542058
rc = PTR_ERR(phys_pg_pack);
20552059
goto dec_memhash_export_cnt;
20562060
}
2057-
rc = validate_export_params(hdev, export_addr, size, offset, phys_pg_pack);
2061+
rc = validate_export_params(hdev, addr, size, offset, phys_pg_pack);
20582062
if (rc)
20592063
goto dec_memhash_export_cnt;
20602064

20612065
hl_dmabuf->phys_pg_pack = phys_pg_pack;
20622066
hl_dmabuf->memhash_hnode = hnode;
2067+
hl_dmabuf->offset = offset;
20632068
} else {
2064-
rc = validate_export_params_no_mmu(hdev, export_addr, size);
2069+
rc = validate_export_params_no_mmu(hdev, addr, size);
20652070
if (rc)
20662071
goto err_free_dmabuf_wrapper;
20672072

2068-
hl_dmabuf->device_phys_addr = export_addr;
2073+
hl_dmabuf->device_phys_addr = addr;
20692074
}
20702075

20712076
rc = export_dmabuf(ctx, hl_dmabuf, size, flags, dmabuf_fd);

0 commit comments

Comments
 (0)