aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-01-13 07:13:14 -0500
committerBen Skeggs <bskeggs@redhat.com>2015-01-21 21:15:10 -0500
commitc39f472e9f14e49a9bc091977ced0ec45fc00c57 (patch)
tree75af3291cccda2482913cc0044888a8a86f4841b /drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
parent055a65d5987a7f246c3fc2297158286882dbdbcf (diff)
drm/nouveau: remove symlinks, move core/ to nvkm/ (no code changes)
The symlinks were annoying some people, and they're not used anywhere else in the kernel tree. The include directory structure has been changed so that symlinks aren't needed anymore. NVKM has been moved from core/ to nvkm/ to make it more obvious as to what the directory is for, and as some minor prep for when NVKM gets split out into its own module (virt) at a later date. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
new file mode 100644
index 000000000000..25e3b9644a3f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
@@ -0,0 +1,170 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: Ben Skeggs
23 */
24
25#include "priv.h"
26#include <core/option.h>
27
28static inline void
29nouveau_mc_unk260(struct nouveau_mc *pmc, u32 data)
30{
31 const struct nouveau_mc_oclass *impl = (void *)nv_oclass(pmc);
32 if (impl->unk260)
33 impl->unk260(pmc, data);
34}
35
36static inline u32
37nouveau_mc_intr_mask(struct nouveau_mc *pmc)
38{
39 u32 intr = nv_rd32(pmc, 0x000100);
40 if (intr == 0xffffffff) /* likely fallen off the bus */
41 intr = 0x00000000;
42 return intr;
43}
44
45static irqreturn_t
46nouveau_mc_intr(int irq, void *arg)
47{
48 struct nouveau_mc *pmc = arg;
49 const struct nouveau_mc_oclass *oclass = (void *)nv_object(pmc)->oclass;
50 const struct nouveau_mc_intr *map = oclass->intr;
51 struct nouveau_subdev *unit;
52 u32 intr;
53
54 nv_wr32(pmc, 0x000140, 0x00000000);
55 nv_rd32(pmc, 0x000140);
56 intr = nouveau_mc_intr_mask(pmc);
57 if (pmc->use_msi)
58 oclass->msi_rearm(pmc);
59
60 if (intr) {
61 u32 stat = intr = nouveau_mc_intr_mask(pmc);
62 while (map->stat) {
63 if (intr & map->stat) {
64 unit = nouveau_subdev(pmc, map->unit);
65 if (unit && unit->intr)
66 unit->intr(unit);
67 stat &= ~map->stat;
68 }
69 map++;
70 }
71
72 if (stat)
73 nv_error(pmc, "unknown intr 0x%08x\n", stat);
74 }
75
76 nv_wr32(pmc, 0x000140, 0x00000001);
77 return intr ? IRQ_HANDLED : IRQ_NONE;
78}
79
80int
81_nouveau_mc_fini(struct nouveau_object *object, bool suspend)
82{
83 struct nouveau_mc *pmc = (void *)object;
84 nv_wr32(pmc, 0x000140, 0x00000000);
85 return nouveau_subdev_fini(&pmc->base, suspend);
86}
87
88int
89_nouveau_mc_init(struct nouveau_object *object)
90{
91 struct nouveau_mc *pmc = (void *)object;
92 int ret = nouveau_subdev_init(&pmc->base);
93 if (ret)
94 return ret;
95 nv_wr32(pmc, 0x000140, 0x00000001);
96 return 0;
97}
98
99void
100_nouveau_mc_dtor(struct nouveau_object *object)
101{
102 struct nouveau_device *device = nv_device(object);
103 struct nouveau_mc *pmc = (void *)object;
104 free_irq(pmc->irq, pmc);
105 if (pmc->use_msi)
106 pci_disable_msi(device->pdev);
107 nouveau_subdev_destroy(&pmc->base);
108}
109
110int
111nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
112 struct nouveau_oclass *bclass, int length, void **pobject)
113{
114 const struct nouveau_mc_oclass *oclass = (void *)bclass;
115 struct nouveau_device *device = nv_device(parent);
116 struct nouveau_mc *pmc;
117 int ret;
118
119 ret = nouveau_subdev_create_(parent, engine, bclass, 0, "PMC",
120 "master", length, pobject);
121 pmc = *pobject;
122 if (ret)
123 return ret;
124
125 pmc->unk260 = nouveau_mc_unk260;
126
127 if (nv_device_is_pci(device)) {
128 switch (device->pdev->device & 0x0ff0) {
129 case 0x00f0:
130 case 0x02e0:
131 /* BR02? NFI how these would be handled yet exactly */
132 break;
133 default:
134 switch (device->chipset) {
135 case 0xaa:
136 /* reported broken, nv also disable it */
137 break;
138 default:
139 pmc->use_msi = true;
140 break;
141 }
142 }
143
144 pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI",
145 pmc->use_msi);
146
147 if (pmc->use_msi && oclass->msi_rearm) {
148 pmc->use_msi = pci_enable_msi(device->pdev) == 0;
149 if (pmc->use_msi) {
150 nv_info(pmc, "MSI interrupts enabled\n");
151 oclass->msi_rearm(pmc);
152 }
153 } else {
154 pmc->use_msi = false;
155 }
156 }
157
158 ret = nv_device_get_irq(device, true);
159 if (ret < 0)
160 return ret;
161 pmc->irq = ret;
162
163 ret = request_irq(pmc->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau",
164 pmc);
165
166 if (ret < 0)
167 return ret;
168
169 return 0;
170}