mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
misc: mods: fix handling regions >4GB
The API for retrieving PAs needs to correctly handle offsets which exceed 4GB. Bug 1860962 Change-Id: I877c370d97c35fde565c70cd86a95093be083ebb Signed-off-by: Chris Dragan <kdragan@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1958611 Reviewed-by: Sami Kiminki <skiminki@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
bf8bcb968d
commit
63bb979778
@@ -49,23 +49,32 @@ static bool dummy_device_registered;
|
||||
int esc_mods_dmabuf_get_phys_addr(struct file *filp,
|
||||
struct MODS_DMABUF_GET_PHYSICAL_ADDRESS *op)
|
||||
{
|
||||
int err = 0;
|
||||
struct dma_buf *dmabuf = NULL;
|
||||
int err = 0;
|
||||
struct dma_buf *dmabuf = NULL;
|
||||
struct dma_buf_attachment *attachment = NULL;
|
||||
struct sg_table *sgt = NULL;
|
||||
unsigned int remaining_offset = op->offset;
|
||||
phys_addr_t physical_address = 0;
|
||||
unsigned int segment_size = 0;
|
||||
struct scatterlist *sg;
|
||||
unsigned int sg_index;
|
||||
struct sg_table *sgt = NULL;
|
||||
u64 remaining_offset = op->offset;
|
||||
u64 total_size = 0;
|
||||
u32 total_segments = 0;
|
||||
phys_addr_t physical_address = 0;
|
||||
unsigned int segment_size = 0;
|
||||
struct scatterlist *sg;
|
||||
unsigned int sg_index;
|
||||
|
||||
if (op->offset > UINT_MAX)
|
||||
return -EINVAL;
|
||||
LOG_ENT();
|
||||
|
||||
mods_debug_printk(DEBUG_MEM_DETAILED, "%s: fd=%d offs=0x%llx\n",
|
||||
__func__, op->buf_fd, (unsigned long long)op->offset);
|
||||
|
||||
dmabuf = dma_buf_get(op->buf_fd);
|
||||
if (IS_ERR_OR_NULL(dmabuf))
|
||||
if (IS_ERR_OR_NULL(dmabuf)) {
|
||||
mods_error_printk("%s: failed to get dma buf from fd %d\n",
|
||||
__func__, op->buf_fd);
|
||||
LOG_EXT();
|
||||
return IS_ERR(dmabuf) ? PTR_ERR(dmabuf) : -EINVAL;
|
||||
}
|
||||
|
||||
WARN_ON(!dummy_device_registered);
|
||||
attachment = dma_buf_attach(dmabuf, &dummy_device.dev);
|
||||
if (IS_ERR_OR_NULL(attachment)) {
|
||||
mods_error_printk("%s: failed to attach dma buf\n", __func__);
|
||||
@@ -81,6 +90,8 @@ int esc_mods_dmabuf_get_phys_addr(struct file *filp,
|
||||
}
|
||||
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, sg_index) {
|
||||
total_size += sg->length;
|
||||
++total_segments;
|
||||
if (remaining_offset >= sg->length) {
|
||||
/* haven't reached segment yet, or empty sg */
|
||||
remaining_offset -= sg->length;
|
||||
@@ -98,7 +109,14 @@ int esc_mods_dmabuf_get_phys_addr(struct file *filp,
|
||||
}
|
||||
}
|
||||
|
||||
mods_debug_printk(DEBUG_MEM_DETAILED, "%s: traversed %u segments, 0x%llx size\n",
|
||||
__func__, total_segments,
|
||||
(unsigned long long) total_size);
|
||||
|
||||
if (segment_size == 0) {
|
||||
mods_error_printk("%s: offset 0x%llx exceeds allocation size 0x%llx\n",
|
||||
__func__, (unsigned long long)op->offset,
|
||||
total_size);
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
op->physical_address = physical_address;
|
||||
@@ -113,6 +131,7 @@ buf_map_fail:
|
||||
buf_attach_fail:
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
LOG_EXT();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -120,6 +139,8 @@ int mods_init_dmabuf(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WARN_ON(dummy_device_registered);
|
||||
|
||||
ret = platform_device_register(&dummy_device);
|
||||
if (ret) {
|
||||
mods_error_printk("failed to register %s\n", dummy_device.name);
|
||||
|
||||
Reference in New Issue
Block a user