diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-05-23 21:47:09 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-06-23 01:56:59 -0400 |
commit | 310ff414b32e66d832307bedd99ba75908e4e36d (patch) | |
tree | 7bb3c0de5abf63840bd483957c001b41811fa9e2 | |
parent | 74cfad188b9e7e063ddb8d74fa20b38cbad10d79 (diff) |
drm/nvc0/fb: allocate page for some unknown PFFB object
Fixes DMAR faults during accel, more than likely a similar problem to what
was solved on nv50 previously.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_fb.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c index 26a996025dd2..08e6b118f021 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fb.c +++ b/drivers/gpu/drm/nouveau/nvc0_fb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 2010 Red Hat Inc. | 2 | * Copyright 2011 Red Hat Inc. |
3 | * | 3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), | 5 | * copy of this software and associated documentation files (the "Software"), |
@@ -23,16 +23,80 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "drmP.h" | 25 | #include "drmP.h" |
26 | 26 | #include "drm.h" | |
27 | #include "nouveau_drv.h" | 27 | #include "nouveau_drv.h" |
28 | #include "nouveau_drm.h" | ||
29 | |||
30 | struct nvc0_fb_priv { | ||
31 | struct page *r100c10_page; | ||
32 | dma_addr_t r100c10; | ||
33 | }; | ||
34 | |||
35 | static void | ||
36 | nvc0_fb_destroy(struct drm_device *dev) | ||
37 | { | ||
38 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
39 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
40 | struct nvc0_fb_priv *priv = pfb->priv; | ||
41 | |||
42 | if (priv->r100c10_page) { | ||
43 | pci_unmap_page(dev->pdev, priv->r100c10, PAGE_SIZE, | ||
44 | PCI_DMA_BIDIRECTIONAL); | ||
45 | __free_page(priv->r100c10_page); | ||
46 | } | ||
47 | |||
48 | kfree(priv); | ||
49 | pfb->priv = NULL; | ||
50 | } | ||
51 | |||
52 | static int | ||
53 | nvc0_fb_create(struct drm_device *dev) | ||
54 | { | ||
55 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
56 | struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; | ||
57 | struct nvc0_fb_priv *priv; | ||
58 | |||
59 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
60 | if (!priv) | ||
61 | return -ENOMEM; | ||
62 | pfb->priv = priv; | ||
63 | |||
64 | priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); | ||
65 | if (!priv->r100c10_page) { | ||
66 | nvc0_fb_destroy(dev); | ||
67 | return -ENOMEM; | ||
68 | } | ||
69 | |||
70 | priv->r100c10 = pci_map_page(dev->pdev, priv->r100c10_page, 0, | ||
71 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
72 | if (pci_dma_mapping_error(dev->pdev, priv->r100c10)) { | ||
73 | nvc0_fb_destroy(dev); | ||
74 | return -EFAULT; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
28 | 79 | ||
29 | int | 80 | int |
30 | nvc0_fb_init(struct drm_device *dev) | 81 | nvc0_fb_init(struct drm_device *dev) |
31 | { | 82 | { |
83 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
84 | struct nvc0_fb_priv *priv; | ||
85 | int ret; | ||
86 | |||
87 | if (!dev_priv->engine.fb.priv) { | ||
88 | ret = nvc0_fb_create(dev); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | } | ||
92 | priv = dev_priv->engine.fb.priv; | ||
93 | |||
94 | nv_wr32(dev, 0x100c10, priv->r100c10 >> 8); | ||
32 | return 0; | 95 | return 0; |
33 | } | 96 | } |
34 | 97 | ||
35 | void | 98 | void |
36 | nvc0_fb_takedown(struct drm_device *dev) | 99 | nvc0_fb_takedown(struct drm_device *dev) |
37 | { | 100 | { |
101 | nvc0_fb_destroy(dev); | ||
38 | } | 102 | } |