Commit 02039b17 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'misc-habanalabs-fixes-2021-01-13' of...

Merge tag 'misc-habanalabs-fixes-2021-01-13' of https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux into char-misc-linus

Oded writes:

This tag contains the following bug fixes:

- Fix the dma address that is passed to dma_mmap_coherent. We passed
  an address that includes an offset that is needed by our device and
  that caused dma_mmap_coherent to do an errounous mapping.

- Fix the reset process in case failures happen during the reset process.
  Without this fix, if the user would have asked to perform reset after
  the previous reset failed he would get a kernel panic

- WA to prevent soft lockup BUG during unmap of host memory. In case of
  tens of thousands of mappings, the unmapping can take a long time that
  exceeds the soft lockup timeout. This WA adds a small sleep every 32K
  page unmappings to prevent that.

* tag 'misc-habanalabs-fixes-2021-01-13' of https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/linux:
  habanalabs: prevent soft lockup during unmap
  habanalabs: fix reset process in case of failures
  habanalabs: fix dma_addr passed to dma_mmap_coherent
parents f970d1d0 9488307a
...@@ -1037,7 +1037,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset, ...@@ -1037,7 +1037,7 @@ int hl_device_reset(struct hl_device *hdev, bool hard_reset,
if (hard_reset) { if (hard_reset) {
/* Release kernel context */ /* Release kernel context */
if (hl_ctx_put(hdev->kernel_ctx) == 1) if (hdev->kernel_ctx && hl_ctx_put(hdev->kernel_ctx) == 1)
hdev->kernel_ctx = NULL; hdev->kernel_ctx = NULL;
hl_vm_fini(hdev); hl_vm_fini(hdev);
hl_mmu_fini(hdev); hl_mmu_fini(hdev);
......
...@@ -2182,6 +2182,7 @@ void hl_mmu_v1_set_funcs(struct hl_device *hdev, struct hl_mmu_funcs *mmu); ...@@ -2182,6 +2182,7 @@ void hl_mmu_v1_set_funcs(struct hl_device *hdev, struct hl_mmu_funcs *mmu);
int hl_mmu_va_to_pa(struct hl_ctx *ctx, u64 virt_addr, u64 *phys_addr); int hl_mmu_va_to_pa(struct hl_ctx *ctx, u64 virt_addr, u64 *phys_addr);
int hl_mmu_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr, int hl_mmu_get_tlb_info(struct hl_ctx *ctx, u64 virt_addr,
struct hl_mmu_hop_info *hops); struct hl_mmu_hop_info *hops);
bool hl_is_dram_va(struct hl_device *hdev, u64 virt_addr);
int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name, int hl_fw_load_fw_to_device(struct hl_device *hdev, const char *fw_name,
void __iomem *dst, u32 src_offset, u32 size); void __iomem *dst, u32 src_offset, u32 size);
......
...@@ -886,8 +886,10 @@ static void unmap_phys_pg_pack(struct hl_ctx *ctx, u64 vaddr, ...@@ -886,8 +886,10 @@ static void unmap_phys_pg_pack(struct hl_ctx *ctx, u64 vaddr,
{ {
struct hl_device *hdev = ctx->hdev; struct hl_device *hdev = ctx->hdev;
u64 next_vaddr, i; u64 next_vaddr, i;
bool is_host_addr;
u32 page_size; u32 page_size;
is_host_addr = !hl_is_dram_va(hdev, vaddr);
page_size = phys_pg_pack->page_size; page_size = phys_pg_pack->page_size;
next_vaddr = vaddr; next_vaddr = vaddr;
...@@ -900,9 +902,13 @@ static void unmap_phys_pg_pack(struct hl_ctx *ctx, u64 vaddr, ...@@ -900,9 +902,13 @@ static void unmap_phys_pg_pack(struct hl_ctx *ctx, u64 vaddr,
/* /*
* unmapping on Palladium can be really long, so avoid a CPU * unmapping on Palladium can be really long, so avoid a CPU
* soft lockup bug by sleeping a little between unmapping pages * soft lockup bug by sleeping a little between unmapping pages
*
* In addition, when unmapping host memory we pass through
* the Linux kernel to unpin the pages and that takes a long
* time. Therefore, sleep every 32K pages to avoid soft lockup
*/ */
if (hdev->pldm) if (hdev->pldm || (is_host_addr && (i & 0x7FFF) == 0))
usleep_range(500, 1000); usleep_range(50, 200);
} }
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "habanalabs.h" #include "habanalabs.h"
static bool is_dram_va(struct hl_device *hdev, u64 virt_addr) bool hl_is_dram_va(struct hl_device *hdev, u64 virt_addr)
{ {
struct asic_fixed_properties *prop = &hdev->asic_prop; struct asic_fixed_properties *prop = &hdev->asic_prop;
...@@ -156,7 +156,7 @@ int hl_mmu_unmap_page(struct hl_ctx *ctx, u64 virt_addr, u32 page_size, ...@@ -156,7 +156,7 @@ int hl_mmu_unmap_page(struct hl_ctx *ctx, u64 virt_addr, u32 page_size,
if (!hdev->mmu_enable) if (!hdev->mmu_enable)
return 0; return 0;
is_dram_addr = is_dram_va(hdev, virt_addr); is_dram_addr = hl_is_dram_va(hdev, virt_addr);
if (is_dram_addr) if (is_dram_addr)
mmu_prop = &prop->dmmu; mmu_prop = &prop->dmmu;
...@@ -236,7 +236,7 @@ int hl_mmu_map_page(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr, ...@@ -236,7 +236,7 @@ int hl_mmu_map_page(struct hl_ctx *ctx, u64 virt_addr, u64 phys_addr,
if (!hdev->mmu_enable) if (!hdev->mmu_enable)
return 0; return 0;
is_dram_addr = is_dram_va(hdev, virt_addr); is_dram_addr = hl_is_dram_va(hdev, virt_addr);
if (is_dram_addr) if (is_dram_addr)
mmu_prop = &prop->dmmu; mmu_prop = &prop->dmmu;
......
...@@ -467,8 +467,16 @@ static void hl_mmu_v1_fini(struct hl_device *hdev) ...@@ -467,8 +467,16 @@ static void hl_mmu_v1_fini(struct hl_device *hdev)
{ {
/* MMU H/W fini was already done in device hw_fini() */ /* MMU H/W fini was already done in device hw_fini() */
kvfree(hdev->mmu_priv.dr.mmu_shadow_hop0); if (!ZERO_OR_NULL_PTR(hdev->mmu_priv.hr.mmu_shadow_hop0)) {
gen_pool_destroy(hdev->mmu_priv.dr.mmu_pgt_pool); kvfree(hdev->mmu_priv.dr.mmu_shadow_hop0);
gen_pool_destroy(hdev->mmu_priv.dr.mmu_pgt_pool);
}
/* Make sure that if we arrive here again without init was called we
* won't cause kernel panic. This can happen for example if we fail
* during hard reset code at certain points
*/
hdev->mmu_priv.dr.mmu_shadow_hop0 = NULL;
} }
/** /**
......
...@@ -4002,7 +4002,8 @@ static int gaudi_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma, ...@@ -4002,7 +4002,8 @@ static int gaudi_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
VM_DONTCOPY | VM_NORESERVE; VM_DONTCOPY | VM_NORESERVE;
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr, dma_addr, size); rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr,
(dma_addr - HOST_PHYS_BASE), size);
if (rc) if (rc)
dev_err(hdev->dev, "dma_mmap_coherent error %d", rc); dev_err(hdev->dev, "dma_mmap_coherent error %d", rc);
......
...@@ -2719,7 +2719,8 @@ static int goya_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma, ...@@ -2719,7 +2719,8 @@ static int goya_cb_mmap(struct hl_device *hdev, struct vm_area_struct *vma,
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP |
VM_DONTCOPY | VM_NORESERVE; VM_DONTCOPY | VM_NORESERVE;
rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr, dma_addr, size); rc = dma_mmap_coherent(hdev->dev, vma, cpu_addr,
(dma_addr - HOST_PHYS_BASE), size);
if (rc) if (rc)
dev_err(hdev->dev, "dma_mmap_coherent error %d", rc); dev_err(hdev->dev, "dma_mmap_coherent error %d", rc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment