Commit 090cbdd0 authored by Dave Airlie's avatar Dave Airlie
parents 539c475d d00ddd9d
...@@ -1151,6 +1151,11 @@ int arm_dma_supported(struct device *dev, u64 mask) ...@@ -1151,6 +1151,11 @@ int arm_dma_supported(struct device *dev, u64 mask)
return __dma_supported(dev, mask, false); return __dma_supported(dev, mask, false);
} }
static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
{
return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
}
#ifdef CONFIG_ARM_DMA_USE_IOMMU #ifdef CONFIG_ARM_DMA_USE_IOMMU
static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs) static int __dma_info_to_prot(enum dma_data_direction dir, unsigned long attrs)
...@@ -2296,7 +2301,7 @@ void arm_iommu_detach_device(struct device *dev) ...@@ -2296,7 +2301,7 @@ void arm_iommu_detach_device(struct device *dev)
iommu_detach_device(mapping->domain, dev); iommu_detach_device(mapping->domain, dev);
kref_put(&mapping->kref, release_iommu_mapping); kref_put(&mapping->kref, release_iommu_mapping);
to_dma_iommu_mapping(dev) = NULL; to_dma_iommu_mapping(dev) = NULL;
set_dma_ops(dev, NULL); set_dma_ops(dev, arm_get_dma_map_ops(dev->archdata.dma_coherent));
pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
} }
...@@ -2357,11 +2362,6 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { } ...@@ -2357,11 +2362,6 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) { }
#endif /* CONFIG_ARM_DMA_USE_IOMMU */ #endif /* CONFIG_ARM_DMA_USE_IOMMU */
static const struct dma_map_ops *arm_get_dma_map_ops(bool coherent)
{
return coherent ? &arm_coherent_dma_ops : &arm_dma_ops;
}
void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
const struct iommu_ops *iommu, bool coherent) const struct iommu_ops *iommu, bool coherent)
{ {
......
...@@ -1017,7 +1017,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -1017,7 +1017,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
nv_crtc->cursor.show(nv_crtc, true); nv_crtc->cursor.show(nv_crtc, true);
out: out:
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return ret; return ret;
} }
......
...@@ -136,12 +136,24 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, ...@@ -136,12 +136,24 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
{ {
struct nouveau_cli *cli = (void *)device->object.client; struct nouveau_cli *cli = (void *)device->object.client;
struct nv50_disp_core_channel_dma_v0 *args = data; struct nv50_disp_core_channel_dma_v0 *args = data;
u8 type = NVIF_MEM_COHERENT;
int ret; int ret;
mutex_init(&dmac->lock); mutex_init(&dmac->lock);
ret = nvif_mem_init_map(&cli->mmu, NVIF_MEM_COHERENT, 0x1000, /* Pascal added support for 47-bit physical addresses, but some
&dmac->push); * parts of EVO still only accept 40-bit PAs.
*
* To avoid issues on systems with large amounts of RAM, and on
* systems where an IOMMU maps pages at a high address, we need
* to allocate push buffers in VRAM instead.
*
* This appears to match NVIDIA's behaviour on Pascal.
*/
if (device->info.family == NV_DEVICE_INFO_V0_PASCAL)
type |= NVIF_MEM_VRAM;
ret = nvif_mem_init_map(&cli->mmu, type, 0x1000, &dmac->push);
if (ret) if (ret)
return ret; return ret;
...@@ -216,6 +228,19 @@ void ...@@ -216,6 +228,19 @@ void
evo_kick(u32 *push, struct nv50_dmac *evoc) evo_kick(u32 *push, struct nv50_dmac *evoc)
{ {
struct nv50_dmac *dmac = evoc; struct nv50_dmac *dmac = evoc;
/* Push buffer fetches are not coherent with BAR1, we need to ensure
* writes have been flushed right through to VRAM before writing PUT.
*/
if (dmac->push.type & NVIF_MEM_VRAM) {
struct nvif_device *device = dmac->base.device;
nvif_wr32(&device->object, 0x070000, 0x00000001);
nvif_msec(device, 2000,
if (!(nvif_rd32(&device->object, 0x070000) & 0x00000002))
break;
);
}
nvif_wr32(&dmac->base.user, 0x0000, (push - dmac->ptr) << 2); nvif_wr32(&dmac->base.user, 0x0000, (push - dmac->ptr) << 2);
mutex_unlock(&dmac->lock); mutex_unlock(&dmac->lock);
} }
...@@ -1007,7 +1032,7 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, ...@@ -1007,7 +1032,7 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
mstc->port = NULL; mstc->port = NULL;
drm_modeset_unlock(&drm->dev->mode_config.connection_mutex); drm_modeset_unlock(&drm->dev->mode_config.connection_mutex);
drm_connector_unreference(&mstc->connector); drm_connector_put(&mstc->connector);
} }
static void static void
...@@ -2231,6 +2256,9 @@ nv50_display_create(struct drm_device *dev) ...@@ -2231,6 +2256,9 @@ nv50_display_create(struct drm_device *dev)
connector->funcs->destroy(connector); connector->funcs->destroy(connector);
} }
/* Disable vblank irqs aggressively for power-saving, safe on nv50+ */
dev->vblank_disable_immediate = true;
out: out:
if (ret) if (ret)
nv50_display_destroy(dev); nv50_display_destroy(dev);
......
...@@ -586,7 +586,6 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, ...@@ -586,7 +586,6 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev,
wndw->id = index; wndw->id = index;
wndw->interlock.type = interlock_type; wndw->interlock.type = interlock_type;
wndw->interlock.data = interlock_data; wndw->interlock.data = interlock_data;
wndw->ctxdma.parent = &wndw->wndw.base.user;
wndw->ctxdma.parent = &wndw->wndw.base.user; wndw->ctxdma.parent = &wndw->wndw.base.user;
INIT_LIST_HEAD(&wndw->ctxdma.list); INIT_LIST_HEAD(&wndw->ctxdma.list);
......
...@@ -78,7 +78,7 @@ struct nvif_mclass { ...@@ -78,7 +78,7 @@ struct nvif_mclass {
#define nvif_mclass(o,m) ({ \ #define nvif_mclass(o,m) ({ \
struct nvif_object *object = (o); \ struct nvif_object *object = (o); \
struct nvif_sclass *sclass; \ struct nvif_sclass *sclass; \
const typeof(m[0]) *mclass = (m); \ typeof(m[0]) *mclass = (m); \
int ret = -ENODEV; \ int ret = -ENODEV; \
int cnt, i, j; \ int cnt, i, j; \
\ \
......
...@@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, ...@@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
if (chan->ntfy) { if (chan->ntfy) {
nouveau_vma_del(&chan->ntfy_vma); nouveau_vma_del(&chan->ntfy_vma);
nouveau_bo_unpin(chan->ntfy); nouveau_bo_unpin(chan->ntfy);
drm_gem_object_unreference_unlocked(&chan->ntfy->gem); drm_gem_object_put_unlocked(&chan->ntfy->gem);
} }
if (chan->heap.block_size) if (chan->heap.block_size)
......
...@@ -160,7 +160,11 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf, ...@@ -160,7 +160,11 @@ nouveau_debugfs_pstate_set(struct file *file, const char __user *ubuf,
args.ustate = value; args.ustate = value;
} }
ret = pm_runtime_get_sync(drm->dev);
if (IS_ERR_VALUE(ret) && ret != -EACCES)
return ret;
ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args)); ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
pm_runtime_put_autosuspend(drm->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -205,7 +205,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) ...@@ -205,7 +205,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
if (fb->nvbo) if (fb->nvbo)
drm_gem_object_unreference_unlocked(&fb->nvbo->gem); drm_gem_object_put_unlocked(&fb->nvbo->gem);
drm_framebuffer_cleanup(drm_fb); drm_framebuffer_cleanup(drm_fb);
kfree(fb); kfree(fb);
...@@ -287,7 +287,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev, ...@@ -287,7 +287,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
if (ret == 0) if (ret == 0)
return &fb->base; return &fb->base;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -939,7 +939,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, ...@@ -939,7 +939,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
return ret; return ret;
ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle);
drm_gem_object_unreference_unlocked(&bo->gem); drm_gem_object_put_unlocked(&bo->gem);
return ret; return ret;
} }
...@@ -954,7 +954,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, ...@@ -954,7 +954,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv,
if (gem) { if (gem) {
struct nouveau_bo *bo = nouveau_gem_object(gem); struct nouveau_bo *bo = nouveau_gem_object(gem);
*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return 0; return 0;
} }
......
...@@ -912,8 +912,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) ...@@ -912,8 +912,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
get_task_comm(tmpname, current); get_task_comm(tmpname, current);
snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
if (!(cli = kzalloc(sizeof(*cli), GFP_KERNEL))) if (!(cli = kzalloc(sizeof(*cli), GFP_KERNEL))) {
return ret; ret = -ENOMEM;
goto done;
}
ret = nouveau_cli_init(drm, name, cli); ret = nouveau_cli_init(drm, name, cli);
if (ret) if (ret)
......
...@@ -429,7 +429,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) ...@@ -429,7 +429,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
nouveau_vma_del(&nouveau_fb->vma); nouveau_vma_del(&nouveau_fb->vma);
nouveau_bo_unmap(nouveau_fb->nvbo); nouveau_bo_unmap(nouveau_fb->nvbo);
nouveau_bo_unpin(nouveau_fb->nvbo); nouveau_bo_unpin(nouveau_fb->nvbo);
drm_framebuffer_unreference(&nouveau_fb->base); drm_framebuffer_put(&nouveau_fb->base);
} }
return 0; return 0;
......
...@@ -274,7 +274,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, ...@@ -274,7 +274,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
} }
/* drop reference from allocate - handle holds it now */ /* drop reference from allocate - handle holds it now */
drm_gem_object_unreference_unlocked(&nvbo->gem); drm_gem_object_put_unlocked(&nvbo->gem);
return ret; return ret;
} }
...@@ -354,7 +354,7 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence, ...@@ -354,7 +354,7 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence,
list_del(&nvbo->entry); list_del(&nvbo->entry);
nvbo->reserved_by = NULL; nvbo->reserved_by = NULL;
ttm_bo_unreserve(&nvbo->bo); ttm_bo_unreserve(&nvbo->bo);
drm_gem_object_unreference_unlocked(&nvbo->gem); drm_gem_object_put_unlocked(&nvbo->gem);
} }
} }
...@@ -400,14 +400,14 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, ...@@ -400,14 +400,14 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
nvbo = nouveau_gem_object(gem); nvbo = nouveau_gem_object(gem);
if (nvbo == res_bo) { if (nvbo == res_bo) {
res_bo = NULL; res_bo = NULL;
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
continue; continue;
} }
if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { if (nvbo->reserved_by && nvbo->reserved_by == file_priv) {
NV_PRINTK(err, cli, "multiple instances of buffer %d on " NV_PRINTK(err, cli, "multiple instances of buffer %d on "
"validation list\n", b->handle); "validation list\n", b->handle);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
...@@ -894,7 +894,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, ...@@ -894,7 +894,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
ret = lret; ret = lret;
nouveau_bo_sync_for_cpu(nvbo); nouveau_bo_sync_for_cpu(nvbo);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return ret; return ret;
} }
...@@ -913,7 +913,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, ...@@ -913,7 +913,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
nvbo = nouveau_gem_object(gem); nvbo = nouveau_gem_object(gem);
nouveau_bo_sync_for_device(nvbo); nouveau_bo_sync_for_device(nvbo);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return 0; return 0;
} }
...@@ -930,7 +930,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, ...@@ -930,7 +930,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
return -ENOENT; return -ENOENT;
ret = nouveau_gem_info(file_priv, gem, req); ret = nouveau_gem_info(file_priv, gem, req);
drm_gem_object_unreference_unlocked(gem); drm_gem_object_put_unlocked(gem);
return ret; return ret;
} }
...@@ -69,8 +69,8 @@ nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, ...@@ -69,8 +69,8 @@ nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d,
struct nvkm_therm *therm = nvxx_therm(&drm->client.device); struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
long value; long value;
if (kstrtol(buf, 10, &value) == -EINVAL) if (kstrtol(buf, 10, &value))
return count; return -EINVAL;
therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST, therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST,
value / 1000); value / 1000);
...@@ -102,8 +102,8 @@ nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, ...@@ -102,8 +102,8 @@ nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
struct nvkm_therm *therm = nvxx_therm(&drm->client.device); struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
long value; long value;
if (kstrtol(buf, 10, &value) == -EINVAL) if (kstrtol(buf, 10, &value))
return count; return -EINVAL;
therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST, therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
value / 1000); value / 1000);
...@@ -156,7 +156,7 @@ nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a, ...@@ -156,7 +156,7 @@ nouveau_hwmon_set_pwm1_min(struct device *d, struct device_attribute *a,
long value; long value;
int ret; int ret;
if (kstrtol(buf, 10, &value) == -EINVAL) if (kstrtol(buf, 10, &value))
return -EINVAL; return -EINVAL;
ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value); ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MIN_DUTY, value);
...@@ -179,7 +179,7 @@ nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a, ...@@ -179,7 +179,7 @@ nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
long value; long value;
int ret; int ret;
if (kstrtol(buf, 10, &value) == -EINVAL) if (kstrtol(buf, 10, &value))
return -EINVAL; return -EINVAL;
ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value); ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
......
...@@ -36,7 +36,7 @@ static int nouveau_platform_probe(struct platform_device *pdev) ...@@ -36,7 +36,7 @@ static int nouveau_platform_probe(struct platform_device *pdev)
ret = drm_dev_register(drm, 0); ret = drm_dev_register(drm, 0);
if (ret < 0) { if (ret < 0) {
drm_dev_unref(drm); drm_dev_put(drm);
return ret; return ret;
} }
......
...@@ -87,11 +87,12 @@ nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data) ...@@ -87,11 +87,12 @@ nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
{ {
struct nvkm_engine *engine = nvkm_engine(subdev); struct nvkm_engine *engine = nvkm_engine(subdev);
if (engine->func->info) { if (engine->func->info) {
if ((engine = nvkm_engine_ref(engine))) { if (!IS_ERR((engine = nvkm_engine_ref(engine)))) {
int ret = engine->func->info(engine, mthd, data); int ret = engine->func->info(engine, mthd, data);
nvkm_engine_unref(&engine); nvkm_engine_unref(&engine);
return ret; return ret;
} }
return PTR_ERR(engine);
} }
return -ENOSYS; return -ENOSYS;
} }
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
#include "priv.h" #include "priv.h"
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
#include <asm/dma-iommu.h>
#endif
static int static int
nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
{ {
...@@ -105,6 +109,15 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) ...@@ -105,6 +109,15 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
unsigned long pgsize_bitmap; unsigned long pgsize_bitmap;
int ret; int ret;
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
if (dev->archdata.mapping) {
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
arm_iommu_detach_device(dev);
arm_iommu_release_mapping(mapping);
}
#endif
if (!tdev->func->iommu_bit) if (!tdev->func->iommu_bit)
return; return;
......
...@@ -52,7 +52,7 @@ void ...@@ -52,7 +52,7 @@ void
gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en) gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en)
{ {
struct nvkm_device *device = chan->disp->base.engine.subdev.device; struct nvkm_device *device = chan->disp->base.engine.subdev.device;
const u64 mask = 0x00000001 << chan->chid.user; const u32 mask = 0x00000001 << chan->chid.user;
if (!en) { if (!en) {
nvkm_mask(device, 0x610090, mask, 0x00000000); nvkm_mask(device, 0x610090, mask, 0x00000000);
nvkm_mask(device, 0x6100a0, mask, 0x00000000); nvkm_mask(device, 0x6100a0, mask, 0x00000000);
......
...@@ -166,8 +166,8 @@ void ...@@ -166,8 +166,8 @@ void
nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en) nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en)
{ {
struct nvkm_device *device = chan->disp->base.engine.subdev.device; struct nvkm_device *device = chan->disp->base.engine.subdev.device;
const u64 mask = 0x00010001 << chan->chid.user; const u32 mask = 0x00010001 << chan->chid.user;
const u64 data = en ? 0x00010000 : 0x00000000; const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000;
nvkm_mask(device, 0x610028, mask, data); nvkm_mask(device, 0x610028, mask, data);
} }
......
...@@ -25,24 +25,31 @@ ...@@ -25,24 +25,31 @@
#include <nvif/class.h> #include <nvif/class.h>
static void static void
gv100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc) gv100_gr_trap_sm(struct gf100_gr *gr, int gpc, int tpc, int sm)
{ {
struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device; struct nvkm_device *device = subdev->device;
u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x730)); u32 werr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x730 + (sm * 0x80)));
u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x734)); u32 gerr = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x734 + (sm * 0x80)));
const struct nvkm_enum *warp; const struct nvkm_enum *warp;
char glob[128]; char glob[128];
nvkm_snprintbf(glob, sizeof(glob), gf100_mp_global_error, gerr); nvkm_snprintbf(glob, sizeof(glob), gf100_mp_global_error, gerr);
warp = nvkm_enum_find(gf100_mp_warp_error, werr & 0xffff); warp = nvkm_enum_find(gf100_mp_warp_error, werr & 0xffff);
nvkm_error(subdev, "GPC%i/TPC%i/MP trap: " nvkm_error(subdev, "GPC%i/TPC%i/SM%d trap: "
"global %08x [%s] warp %04x [%s]\n", "global %08x [%s] warp %04x [%s]\n",
gpc, tpc, gerr, glob, werr, warp ? warp->name : ""); gpc, tpc, sm, gerr, glob, werr, warp ? warp->name : "");
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x730 + sm * 0x80), 0x00000000);
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x734 + sm * 0x80), gerr);
}
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x730), 0x00000000); static void
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x734), gerr); gv100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc)
{
gv100_gr_trap_sm(gr, gpc, tpc, 0);
gv100_gr_trap_sm(gr, gpc, tpc, 1);
} }
static void static void
......
...@@ -58,8 +58,14 @@ nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h) ...@@ -58,8 +58,14 @@ nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h)
h->ecount = nvbios_rd08(b, h->offset + 0x5); h->ecount = nvbios_rd08(b, h->offset + 0x5);
h->base_id = nvbios_rd08(b, h->offset + 0x0f); h->base_id = nvbios_rd08(b, h->offset + 0x0f);
if (h->hlen > 0x10)
h->boost_id = nvbios_rd08(b, h->offset + 0x10); h->boost_id = nvbios_rd08(b, h->offset + 0x10);
else
h->boost_id = 0xff;
if (h->hlen > 0x11)
h->tdp_id = nvbios_rd08(b, h->offset + 0x11); h->tdp_id = nvbios_rd08(b, h->offset + 0x11);
else
h->tdp_id = 0xff;
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -133,8 +133,14 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev) ...@@ -133,8 +133,14 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev)
} }
} }
return nvkm_event_init(&nvkm_fault_ntfy, 1, fault->buffer_nr, ret = nvkm_event_init(&nvkm_fault_ntfy, 1, fault->buffer_nr,
&fault->event); &fault->event);
if (ret)
return ret;
if (fault->func->oneinit)
ret = fault->func->oneinit(fault);
return ret;
} }
static void * static void *
......
...@@ -176,8 +176,17 @@ gv100_fault_init(struct nvkm_fault *fault) ...@@ -176,8 +176,17 @@ gv100_fault_init(struct nvkm_fault *fault)
nvkm_notify_get(&fault->nrpfb); nvkm_notify_get(&fault->nrpfb);
} }
static int
gv100_fault_oneinit(struct nvkm_fault *fault)
{
return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
gv100_fault_ntfy_nrpfb, false, NULL, 0, 0,
&fault->nrpfb);
}
static const struct nvkm_fault_func static const struct nvkm_fault_func
gv100_fault = { gv100_fault = {
.oneinit = gv100_fault_oneinit,
.init = gv100_fault_init, .init = gv100_fault_init,
.fini = gv100_fault_fini, .fini = gv100_fault_fini,
.intr = gv100_fault_intr, .intr = gv100_fault_intr,
...@@ -192,15 +201,5 @@ int ...@@ -192,15 +201,5 @@ int
gv100_fault_new(struct nvkm_device *device, int index, gv100_fault_new(struct nvkm_device *device, int index,
struct nvkm_fault **pfault) struct nvkm_fault **pfault)
{ {
struct nvkm_fault *fault; return nvkm_fault_new_(&gv100_fault, device, index, pfault);
int ret;
ret = nvkm_fault_new_(&gv100_fault, device, index, &fault);
*pfault = fault;
if (ret)
return ret;
return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
gv100_fault_ntfy_nrpfb, false, NULL, 0, 0,
&fault->nrpfb);
} }
...@@ -20,6 +20,7 @@ int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *, ...@@ -20,6 +20,7 @@ int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *,
int index, struct nvkm_fault **); int index, struct nvkm_fault **);
struct nvkm_fault_func { struct nvkm_fault_func {
int (*oneinit)(struct nvkm_fault *);
void (*init)(struct nvkm_fault *); void (*init)(struct nvkm_fault *);
void (*fini)(struct nvkm_fault *); void (*fini)(struct nvkm_fault *);
void (*intr)(struct nvkm_fault *); void (*intr)(struct nvkm_fault *);
......
...@@ -414,6 +414,20 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -414,6 +414,20 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
{ {
struct ls_ucode_img *_img; struct ls_ucode_img *_img;
u32 pos = 0; u32 pos = 0;
u32 max_desc_size = 0;
u8 *gdesc;
/* Figure out how large we need gdesc to be. */
list_for_each_entry(_img, imgs, node) {
const struct acr_r352_ls_func *ls_func =
acr->func->ls_func[_img->falcon_id];
max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
}
gdesc = kmalloc(max_desc_size, GFP_KERNEL);
if (!gdesc)
return -ENOMEM;
nvkm_kmap(wpr_blob); nvkm_kmap(wpr_blob);
...@@ -421,7 +435,6 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -421,7 +435,6 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img); struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
const struct acr_r352_ls_func *ls_func = const struct acr_r352_ls_func *ls_func =
acr->func->ls_func[_img->falcon_id]; acr->func->ls_func[_img->falcon_id];
u8 gdesc[ls_func->bl_desc_size];
nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
sizeof(img->wpr_header)); sizeof(img->wpr_header));
...@@ -447,6 +460,8 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -447,6 +460,8 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
nvkm_done(wpr_blob); nvkm_done(wpr_blob);
kfree(gdesc);
return 0; return 0;
} }
...@@ -771,7 +786,11 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon, ...@@ -771,7 +786,11 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
struct fw_bl_desc *hsbl_desc; struct fw_bl_desc *hsbl_desc;
void *bl, *blob_data, *hsbl_code, *hsbl_data; void *bl, *blob_data, *hsbl_code, *hsbl_data;
u32 code_size; u32 code_size;
u8 bl_desc[bl_desc_size]; u8 *bl_desc;
bl_desc = kzalloc(bl_desc_size, GFP_KERNEL);
if (!bl_desc)
return -ENOMEM;
/* Find the bootloader descriptor for our blob and copy it */ /* Find the bootloader descriptor for our blob and copy it */
if (blob == acr->load_blob) { if (blob == acr->load_blob) {
...@@ -802,7 +821,6 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon, ...@@ -802,7 +821,6 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
code_size, hsbl_desc->start_tag, 0, false); code_size, hsbl_desc->start_tag, 0, false);
/* Generate the BL header */ /* Generate the BL header */
memset(bl_desc, 0, bl_desc_size);
acr->func->generate_hs_bl_desc(load_hdr, bl_desc, offset); acr->func->generate_hs_bl_desc(load_hdr, bl_desc, offset);
/* /*
...@@ -811,6 +829,7 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon, ...@@ -811,6 +829,7 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
nvkm_falcon_load_dmem(falcon, bl_desc, hsbl_desc->dmem_load_off, nvkm_falcon_load_dmem(falcon, bl_desc, hsbl_desc->dmem_load_off,
bl_desc_size, 0); bl_desc_size, 0);
kfree(bl_desc);
return hsbl_desc->start_tag << 8; return hsbl_desc->start_tag << 8;
} }
......
...@@ -265,6 +265,19 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -265,6 +265,19 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
{ {
struct ls_ucode_img *_img; struct ls_ucode_img *_img;
u32 pos = 0; u32 pos = 0;
u32 max_desc_size = 0;
u8 *gdesc;
list_for_each_entry(_img, imgs, node) {
const struct acr_r352_ls_func *ls_func =
acr->func->ls_func[_img->falcon_id];
max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
}
gdesc = kmalloc(max_desc_size, GFP_KERNEL);
if (!gdesc)
return -ENOMEM;
nvkm_kmap(wpr_blob); nvkm_kmap(wpr_blob);
...@@ -272,7 +285,6 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -272,7 +285,6 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img); struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img);
const struct acr_r352_ls_func *ls_func = const struct acr_r352_ls_func *ls_func =
acr->func->ls_func[_img->falcon_id]; acr->func->ls_func[_img->falcon_id];
u8 gdesc[ls_func->bl_desc_size];
nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
sizeof(img->wpr_header)); sizeof(img->wpr_header));
...@@ -298,6 +310,8 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -298,6 +310,8 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
nvkm_done(wpr_blob); nvkm_done(wpr_blob);
kfree(gdesc);
return 0; return 0;
} }
......
...@@ -129,6 +129,7 @@ gm20b_secboot_new(struct nvkm_device *device, int index, ...@@ -129,6 +129,7 @@ gm20b_secboot_new(struct nvkm_device *device, int index,
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
MODULE_FIRMWARE("nvidia/gm20b/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gm20b/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin");
MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gm20b/gr/fecs_bl.bin");
...@@ -144,3 +145,4 @@ MODULE_FIRMWARE("nvidia/gm20b/gr/sw_method_init.bin"); ...@@ -144,3 +145,4 @@ MODULE_FIRMWARE("nvidia/gm20b/gr/sw_method_init.bin");
MODULE_FIRMWARE("nvidia/gm20b/pmu/desc.bin"); MODULE_FIRMWARE("nvidia/gm20b/pmu/desc.bin");
MODULE_FIRMWARE("nvidia/gm20b/pmu/image.bin"); MODULE_FIRMWARE("nvidia/gm20b/pmu/image.bin");
MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin"); MODULE_FIRMWARE("nvidia/gm20b/pmu/sig.bin");
#endif
...@@ -74,6 +74,7 @@ gp10b_secboot_new(struct nvkm_device *device, int index, ...@@ -74,6 +74,7 @@ gp10b_secboot_new(struct nvkm_device *device, int index,
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC)
MODULE_FIRMWARE("nvidia/gp10b/acr/bl.bin"); MODULE_FIRMWARE("nvidia/gp10b/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin"); MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin");
MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_bl.bin"); MODULE_FIRMWARE("nvidia/gp10b/gr/fecs_bl.bin");
...@@ -91,3 +92,4 @@ MODULE_FIRMWARE("nvidia/gp10b/gr/sw_method_init.bin"); ...@@ -91,3 +92,4 @@ MODULE_FIRMWARE("nvidia/gp10b/gr/sw_method_init.bin");
MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin");
MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin");
MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin"); MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin");
#endif
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