Merge tag 'for-5.15/parisc-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[linux-2.6-microblaze.git] / drivers / misc / habanalabs / common / memory.c
index d54fdd0..3398693 100644 (file)
@@ -124,7 +124,7 @@ static int alloc_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args,
 
        spin_lock(&vm->idr_lock);
        handle = idr_alloc(&vm->phys_pg_pack_handles, phys_pg_pack, 1, 0,
-                               GFP_KERNEL);
+                               GFP_ATOMIC);
        spin_unlock(&vm->idr_lock);
 
        if (handle < 0) {
@@ -607,8 +607,7 @@ static u64 get_va_block(struct hl_device *hdev,
                        do_div(tmp_hint_addr, va_range->page_size))) {
 
                if (force_hint) {
-                       /* Hint must be repected, so here we just fail.
-                        */
+                       /* Hint must be respected, so here we just fail */
                        dev_err(hdev->dev,
                                "Hint address 0x%llx is not page aligned - cannot be respected\n",
                                hint_addr);
@@ -797,29 +796,16 @@ int hl_unreserve_va_block(struct hl_device *hdev, struct hl_ctx *ctx,
        return rc;
 }
 
-/**
- * get_sg_info() - get number of pages and the DMA address from SG list.
- * @sg: the SG list.
- * @dma_addr: pointer to DMA address to return.
- *
- * Calculate the number of consecutive pages described by the SG list. Take the
- * offset of the address in the first page, add to it the length and round it up
- * to the number of needed pages.
- */
-static u32 get_sg_info(struct scatterlist *sg, dma_addr_t *dma_addr)
-{
-       *dma_addr = sg_dma_address(sg);
-
-       return ((((*dma_addr) & (PAGE_SIZE - 1)) + sg_dma_len(sg)) +
-                       (PAGE_SIZE - 1)) >> PAGE_SHIFT;
-}
-
 /**
  * init_phys_pg_pack_from_userptr() - initialize physical page pack from host
  *                                    memory
  * @ctx: pointer to the context structure.
  * @userptr: userptr to initialize from.
  * @pphys_pg_pack: result pointer.
+ * @force_regular_page: tell the function to ignore huge page optimization,
+ *                      even if possible. Needed for cases where the device VA
+ *                      is allocated before we know the composition of the
+ *                      physical pages
  *
  * This function does the following:
  * - Pin the physical pages related to the given virtual block.
@@ -828,17 +814,18 @@ static u32 get_sg_info(struct scatterlist *sg, dma_addr_t *dma_addr)
  */
 static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
                                struct hl_userptr *userptr,
-                               struct hl_vm_phys_pg_pack **pphys_pg_pack)
+                               struct hl_vm_phys_pg_pack **pphys_pg_pack,
+                               bool force_regular_page)
 {
+       u32 npages, page_size = PAGE_SIZE,
+               huge_page_size = ctx->hdev->asic_prop.pmmu_huge.page_size;
+       u32 pgs_in_huge_page = huge_page_size >> __ffs(page_size);
        struct hl_vm_phys_pg_pack *phys_pg_pack;
+       bool first = true, is_huge_page_opt;
+       u64 page_mask, total_npages;
        struct scatterlist *sg;
        dma_addr_t dma_addr;
-       u64 page_mask, total_npages;
-       u32 npages, page_size = PAGE_SIZE,
-               huge_page_size = ctx->hdev->asic_prop.pmmu_huge.page_size;
-       bool first = true, is_huge_page_opt = true;
        int rc, i, j;
-       u32 pgs_in_huge_page = huge_page_size >> __ffs(page_size);
 
        phys_pg_pack = kzalloc(sizeof(*phys_pg_pack), GFP_KERNEL);
        if (!phys_pg_pack)
@@ -849,6 +836,8 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
        phys_pg_pack->asid = ctx->asid;
        atomic_set(&phys_pg_pack->mapping_cnt, 1);
 
+       is_huge_page_opt = (force_regular_page ? false : true);
+
        /* Only if all dma_addrs are aligned to 2MB and their
         * sizes is at least 2MB, we can use huge page mapping.
         * We limit the 2MB optimization to this condition,
@@ -857,7 +846,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
         */
        total_npages = 0;
        for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
-               npages = get_sg_info(sg, &dma_addr);
+               npages = hl_get_sg_info(sg, &dma_addr);
 
                total_npages += npages;
 
@@ -886,7 +875,7 @@ static int init_phys_pg_pack_from_userptr(struct hl_ctx *ctx,
 
        j = 0;
        for_each_sg(userptr->sgt->sgl, sg, userptr->sgt->nents, i) {
-               npages = get_sg_info(sg, &dma_addr);
+               npages = hl_get_sg_info(sg, &dma_addr);
 
                /* align down to physical page size and save the offset */
                if (first) {
@@ -1067,7 +1056,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
        struct hl_userptr *userptr = NULL;
        struct hl_vm_hash_node *hnode;
        struct hl_va_range *va_range;
-       enum vm_type_t *vm_type;
+       enum vm_type *vm_type;
        u64 ret_vaddr, hint_addr;
        u32 handle = 0, va_block_align;
        int rc;
@@ -1090,7 +1079,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
                }
 
                rc = init_phys_pg_pack_from_userptr(ctx, userptr,
-                               &phys_pg_pack);
+                               &phys_pg_pack, false);
                if (rc) {
                        dev_err(hdev->dev,
                                "unable to init page pack for vaddr 0x%llx\n",
@@ -1098,7 +1087,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
                        goto init_page_pack_err;
                }
 
-               vm_type = (enum vm_type_t *) userptr;
+               vm_type = (enum vm_type *) userptr;
                hint_addr = args->map_host.hint_addr;
                handle = phys_pg_pack->handle;
 
@@ -1140,7 +1129,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
 
                spin_unlock(&vm->idr_lock);
 
-               vm_type = (enum vm_type_t *) phys_pg_pack;
+               vm_type = (enum vm_type *) phys_pg_pack;
 
                hint_addr = args->map_device.hint_addr;
 
@@ -1171,8 +1160,7 @@ static int map_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
 
        if (hint_addr && phys_pg_pack->offset) {
                if (args->flags & HL_MEM_FORCE_HINT) {
-                       /* If hint must be repected, since we can't - just fail.
-                        */
+                       /* Fail if hint must be respected but it can't be */
                        dev_err(hdev->dev,
                                "Hint address 0x%llx cannot be respected because source memory is not aligned 0x%x\n",
                                hint_addr, phys_pg_pack->offset);
@@ -1266,17 +1254,19 @@ init_page_pack_err:
 static int unmap_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
                                bool ctx_free)
 {
-       struct hl_device *hdev = ctx->hdev;
-       struct asic_fixed_properties *prop = &hdev->asic_prop;
        struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
+       u64 vaddr = args->unmap.device_virt_addr;
        struct hl_vm_hash_node *hnode = NULL;
+       struct asic_fixed_properties *prop;
+       struct hl_device *hdev = ctx->hdev;
        struct hl_userptr *userptr = NULL;
        struct hl_va_range *va_range;
-       u64 vaddr = args->unmap.device_virt_addr;
-       enum vm_type_t *vm_type;
+       enum vm_type *vm_type;
        bool is_userptr;
        int rc = 0;
 
+       prop = &hdev->asic_prop;
+
        /* protect from double entrance */
        mutex_lock(&ctx->mem_hash_lock);
        hash_for_each_possible(ctx->mem_hash, hnode, node, (unsigned long)vaddr)
@@ -1299,8 +1289,9 @@ static int unmap_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
        if (*vm_type == VM_TYPE_USERPTR) {
                is_userptr = true;
                userptr = hnode->ptr;
-               rc = init_phys_pg_pack_from_userptr(ctx, userptr,
-                                                       &phys_pg_pack);
+
+               rc = init_phys_pg_pack_from_userptr(ctx, userptr, &phys_pg_pack,
+                                                       false);
                if (rc) {
                        dev_err(hdev->dev,
                                "unable to init page pack for vaddr 0x%llx\n",
@@ -1384,7 +1375,7 @@ static int unmap_device_va(struct hl_ctx *ctx, struct hl_mem_in *args,
        kfree(hnode);
 
        if (is_userptr) {
-               rc = free_phys_pg_pack(hdev, phys_pg_pack);
+               free_phys_pg_pack(hdev, phys_pg_pack);
                dma_unmap_host_va(hdev, userptr);
        }
 
@@ -1754,6 +1745,7 @@ int hl_pin_host_memory(struct hl_device *hdev, u64 addr, u64 size,
                return -EINVAL;
        }
 
+       userptr->pid = current->pid;
        userptr->sgt = kzalloc(sizeof(*userptr->sgt), GFP_KERNEL);
        if (!userptr->sgt)
                return -ENOMEM;
@@ -2118,7 +2110,7 @@ void hl_vm_ctx_fini(struct hl_ctx *ctx)
         * another side effect error
         */
        if (!hdev->hard_reset_pending && !hash_empty(ctx->mem_hash))
-               dev_notice(hdev->dev,
+               dev_dbg(hdev->dev,
                        "user released device without removing its memory mappings\n");
 
        hash_for_each_safe(ctx->mem_hash, i, tmp_node, hnode, node) {