summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c52
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
index f71921cb..b6cdffcb 100644
--- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
+++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c
@@ -2051,7 +2051,7 @@ int gk20a_ctrl_dev_mmap(struct file *filp, struct vm_area_struct *vma)
2051 return err; 2051 return err;
2052} 2052}
2053 2053
2054static void alter_usermode_mapping(struct gk20a *g, 2054static int alter_usermode_mapping(struct gk20a *g,
2055 struct gk20a_ctrl_priv *priv, 2055 struct gk20a_ctrl_priv *priv,
2056 bool poweroff) 2056 bool poweroff)
2057{ 2057{
@@ -2059,23 +2059,34 @@ static void alter_usermode_mapping(struct gk20a *g,
2059 struct vm_area_struct *vma = priv->usermode_vma.vma; 2059 struct vm_area_struct *vma = priv->usermode_vma.vma;
2060 bool vma_mapped = priv->usermode_vma.vma_mapped; 2060 bool vma_mapped = priv->usermode_vma.vma_mapped;
2061 u64 addr; 2061 u64 addr;
2062 int err; 2062 int err = 0;
2063 2063
2064 if (!vma) { 2064 if (!vma) {
2065 /* Nothing to do - no mmap called */ 2065 /* Nothing to do - no mmap called */
2066 return; 2066 return 0;
2067 } 2067 }
2068 2068
2069 addr = l->regs_bus_addr + g->ops.fifo.usermode_base(g); 2069 addr = l->regs_bus_addr + g->ops.fifo.usermode_base(g);
2070 2070
2071 down_write(&vma->vm_mm->mmap_sem);
2072
2073 /* 2071 /*
2074 * This is a no-op for the below cases 2072 * This is a no-op for the below cases
2075 * a) poweroff and !vma_mapped - > do nothing as no map exists 2073 * a) poweroff and !vma_mapped - > do nothing as no map exists
2076 * b) !poweroff and vmap_mapped -> do nothing as already mapped 2074 * b) !poweroff and vmap_mapped -> do nothing as already mapped
2077 */ 2075 */
2078 if (poweroff && vma_mapped) { 2076 if (poweroff != vma_mapped) {
2077 return 0;
2078 }
2079
2080 /*
2081 * We use trylock due to lock inversion: we need to acquire
2082 * mmap_lock while holding ctrl_privs_lock. usermode_vma_close
2083 * does it in reverse order. Trylock is a way to avoid deadlock.
2084 */
2085 if (!down_write_trylock(&vma->vm_mm->mmap_sem)) {
2086 return -EBUSY;
2087 }
2088
2089 if (poweroff) {
2079 err = zap_vma_ptes(vma, vma->vm_start, SZ_4K); 2090 err = zap_vma_ptes(vma, vma->vm_start, SZ_4K);
2080 if (err == 0) { 2091 if (err == 0) {
2081 vma->vm_flags = VM_NONE; 2092 vma->vm_flags = VM_NONE;
@@ -2083,7 +2094,7 @@ static void alter_usermode_mapping(struct gk20a *g,
2083 } else { 2094 } else {
2084 nvgpu_err(g, "can't remove usermode mapping"); 2095 nvgpu_err(g, "can't remove usermode mapping");
2085 } 2096 }
2086 } else if (!poweroff && !vma_mapped) { 2097 } else {
2087 vma->vm_flags = priv->usermode_vma.flags; 2098 vma->vm_flags = priv->usermode_vma.flags;
2088 err = io_remap_pfn_range(vma, vma->vm_start, 2099 err = io_remap_pfn_range(vma, vma->vm_start,
2089 addr >> PAGE_SHIFT, 2100 addr >> PAGE_SHIFT,
@@ -2097,19 +2108,34 @@ static void alter_usermode_mapping(struct gk20a *g,
2097 } 2108 }
2098 2109
2099 up_write(&vma->vm_mm->mmap_sem); 2110 up_write(&vma->vm_mm->mmap_sem);
2111
2112 return err;
2100} 2113}
2101 2114
2102static void alter_usermode_mappings(struct gk20a *g, bool poweroff) 2115static void alter_usermode_mappings(struct gk20a *g, bool poweroff)
2103{ 2116{
2104 struct gk20a_ctrl_priv *priv; 2117 struct gk20a_ctrl_priv *priv;
2105 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g); 2118 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
2119 int err = 0;
2106 2120
2107 nvgpu_mutex_acquire(&l->ctrl.privs_lock); 2121 do {
2108 nvgpu_list_for_each_entry(priv, &l->ctrl.privs, 2122 nvgpu_mutex_acquire(&l->ctrl.privs_lock);
2109 gk20a_ctrl_priv, list) { 2123 nvgpu_list_for_each_entry(priv, &l->ctrl.privs,
2110 alter_usermode_mapping(g, priv, poweroff); 2124 gk20a_ctrl_priv, list) {
2111 } 2125 err = alter_usermode_mapping(g, priv, poweroff);
2112 nvgpu_mutex_release(&l->ctrl.privs_lock); 2126 if (err != 0) {
2127 break;
2128 }
2129 }
2130 nvgpu_mutex_release(&l->ctrl.privs_lock);
2131
2132 if (err == -EBUSY) {
2133 nvgpu_log_info(g, "ctrl_privs_lock lock contended. retry altering usermode mappings");
2134 nvgpu_udelay(10);
2135 } else if (err != 0) {
2136 nvgpu_err(g, "can't alter usermode mapping. err = %d", err);
2137 }
2138 } while (err == -EBUSY);
2113} 2139}
2114 2140
2115void nvgpu_hide_usermode_for_poweroff(struct gk20a *g) 2141void nvgpu_hide_usermode_for_poweroff(struct gk20a *g)