Commit dc1e5c0d authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau: simplify gpuobj suspend/resume

parent fce2bad0
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -222,17 +222,17 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
	pfifo->unload_context(dev);
	pgraph->unload_context(dev);

	NV_INFO(dev, "Suspending GPU objects...\n");
	ret = nouveau_gpuobj_suspend(dev);
	ret = pinstmem->suspend(dev);
	if (ret) {
		NV_ERROR(dev, "... failed: %d\n", ret);
		goto out_abort;
	}

	ret = pinstmem->suspend(dev);
	NV_INFO(dev, "Suspending GPU objects...\n");
	ret = nouveau_gpuobj_suspend(dev);
	if (ret) {
		NV_ERROR(dev, "... failed: %d\n", ret);
		nouveau_gpuobj_suspend_cleanup(dev);
		pinstmem->resume(dev);
		goto out_abort;
	}

@@ -297,6 +297,9 @@ nouveau_pci_resume(struct pci_dev *pdev)
		}
	}

	NV_INFO(dev, "Restoring GPU objects...\n");
	nouveau_gpuobj_resume(dev);

	NV_INFO(dev, "Reinitialising engines...\n");
	engine->instmem.resume(dev);
	engine->mc.init(dev);
@@ -306,9 +309,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
	engine->crypt.init(dev);
	engine->fifo.init(dev);

	NV_INFO(dev, "Restoring GPU objects...\n");
	nouveau_gpuobj_resume(dev);

	nouveau_irq_postinstall(dev);

	/* Re-write SKIPS, they'll have been lost over the suspend */
+1 −2
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ struct nouveau_gpuobj {

	struct drm_mm_node *im_pramin;
	struct nouveau_bo *im_backing;
	uint32_t *im_backing_suspend;
	u32 *suspend;
	int im_bound;

	uint32_t flags;
@@ -865,7 +865,6 @@ extern int nouveau_gpuobj_early_init(struct drm_device *);
extern int  nouveau_gpuobj_init(struct drm_device *);
extern void nouveau_gpuobj_takedown(struct drm_device *);
extern int  nouveau_gpuobj_suspend(struct drm_device *dev);
extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev);
extern void nouveau_gpuobj_resume(struct drm_device *dev);
extern int  nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng);
extern int  nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd,
+10 −46
Original line number Diff line number Diff line
@@ -934,54 +934,23 @@ nouveau_gpuobj_suspend(struct drm_device *dev)
	struct nouveau_gpuobj *gpuobj;
	int i;

	if (dev_priv->card_type < NV_50) {
		dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram);
		if (!dev_priv->susres.ramin_copy)
			return -ENOMEM;

		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
			dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i);
		return 0;
	}

	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
		if (!gpuobj->im_backing)
		if (gpuobj->cinst != 0xdeadbeef)
			continue;

		gpuobj->im_backing_suspend = vmalloc(gpuobj->size);
		if (!gpuobj->im_backing_suspend) {
		gpuobj->suspend = vmalloc(gpuobj->size);
		if (!gpuobj->suspend) {
			nouveau_gpuobj_resume(dev);
			return -ENOMEM;
		}

		for (i = 0; i < gpuobj->size; i += 4)
			gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i);
			gpuobj->suspend[i/4] = nv_ro32(gpuobj, i);
	}

	return 0;
}

void
nouveau_gpuobj_suspend_cleanup(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_gpuobj *gpuobj;

	if (dev_priv->card_type < NV_50) {
		vfree(dev_priv->susres.ramin_copy);
		dev_priv->susres.ramin_copy = NULL;
		return;
	}

	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
		if (!gpuobj->im_backing_suspend)
			continue;

		vfree(gpuobj->im_backing_suspend);
		gpuobj->im_backing_suspend = NULL;
	}
}

void
nouveau_gpuobj_resume(struct drm_device *dev)
{
@@ -989,23 +958,18 @@ nouveau_gpuobj_resume(struct drm_device *dev)
	struct nouveau_gpuobj *gpuobj;
	int i;

	if (dev_priv->card_type < NV_50) {
		for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4)
			nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]);
		nouveau_gpuobj_suspend_cleanup(dev);
		return;
	}

	list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
		if (!gpuobj->im_backing_suspend)
		if (!gpuobj->suspend)
			continue;

		for (i = 0; i < gpuobj->size; i += 4)
			nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]);
		dev_priv->engine.instmem.flush(dev);
			nv_wo32(gpuobj, i, gpuobj->suspend[i/4]);

		vfree(gpuobj->suspend);
		gpuobj->suspend = NULL;
	}

	nouveau_gpuobj_suspend_cleanup(dev);
	dev_priv->engine.instmem.flush(dev);
}

int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
+3 −18
Original line number Diff line number Diff line
@@ -276,16 +276,8 @@ int
nv50_instmem_suspend(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nouveau_channel *chan = dev_priv->channels.ptr[0];
	struct nouveau_gpuobj *ramin = chan->ramin;
	int i;

	ramin->im_backing_suspend = vmalloc(ramin->size);
	if (!ramin->im_backing_suspend)
		return -ENOMEM;

	for (i = 0; i < ramin->size; i += 4)
		ramin->im_backing_suspend[i/4] = nv_ri32(dev, i);
	dev_priv->ramin_available = false;
	return 0;
}

@@ -295,17 +287,8 @@ nv50_instmem_resume(struct drm_device *dev)
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv;
	struct nouveau_channel *chan = dev_priv->channels.ptr[0];
	struct nouveau_gpuobj *ramin = chan->ramin;
	int i;

	dev_priv->ramin_available = false;
	dev_priv->ramin_base = ~0;
	for (i = 0; i < ramin->size; i += 4)
		nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]);
	dev_priv->ramin_available = true;
	vfree(ramin->im_backing_suspend);
	ramin->im_backing_suspend = NULL;

	/* Poke the relevant regs, and pray it works :) */
	nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12));
	nv_wr32(dev, NV50_PUNK_UNK1710, 0);
@@ -318,6 +301,8 @@ nv50_instmem_resume(struct drm_device *dev)

	for (i = 0; i < 8; i++)
		nv_wr32(dev, 0x1900 + (i*4), 0);

	dev_priv->ramin_available = true;
}

int