diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-08-20 00:54:23 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-08-27 22:40:49 -0400 |
commit | 340b0e7c500a0ac8fb649c58cf8528550642c1d8 (patch) | |
tree | 5d0e79108aee9874fd4eabdb138cf7415ad770c0 | |
parent | 26c9e8effebb9166eb1cfba2d164676e98c505c7 (diff) |
drm/nouveau/pci: merge agp handling from nouveau drm
This commit reinstates the pre-DEVINIT AGP fiddling that was broken in
an earlier commit.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/device.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvif/os.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/core/option.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_abi16.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_agp.c | 198 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_agp.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 17 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_ttm.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/core/option.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c | 171 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c | 26 |
18 files changed, 271 insertions, 239 deletions
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 2b765663c1a3..a34b437dbc8f 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild | |||
@@ -18,7 +18,6 @@ nouveau-y += $(nvkm-y) | |||
18 | ifdef CONFIG_X86 | 18 | ifdef CONFIG_X86 |
19 | nouveau-$(CONFIG_ACPI) += nouveau_acpi.o | 19 | nouveau-$(CONFIG_ACPI) += nouveau_acpi.o |
20 | endif | 20 | endif |
21 | nouveau-y += nouveau_agp.o | ||
22 | nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o | 21 | nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o |
23 | nouveau-y += nouveau_drm.o | 22 | nouveau-y += nouveau_drm.o |
24 | nouveau-y += nouveau_hwmon.o | 23 | nouveau-y += nouveau_hwmon.o |
diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h index 900e492549d1..700a9b206726 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/device.h +++ b/drivers/gpu/drm/nouveau/include/nvif/device.h | |||
@@ -45,6 +45,7 @@ u64 nvif_device_time(struct nvif_device *); | |||
45 | #include <subdev/i2c.h> | 45 | #include <subdev/i2c.h> |
46 | #include <subdev/timer.h> | 46 | #include <subdev/timer.h> |
47 | #include <subdev/therm.h> | 47 | #include <subdev/therm.h> |
48 | #include <subdev/pci.h> | ||
48 | 49 | ||
49 | #define nvxx_device(a) ({ \ | 50 | #define nvxx_device(a) ({ \ |
50 | struct nvif_device *_device = (a); \ | 51 | struct nvif_device *_device = (a); \ |
diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h index 54492cb5011b..97317f7fe4e5 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/os.h +++ b/drivers/gpu/drm/nouveau/include/nvif/os.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/power_supply.h> | 24 | #include <linux/power_supply.h> |
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/regulator/consumer.h> | 26 | #include <linux/regulator/consumer.h> |
27 | #include <linux/agp_backend.h> | ||
27 | 28 | ||
28 | #include <asm/unaligned.h> | 29 | #include <asm/unaligned.h> |
29 | 30 | ||
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/option.h b/drivers/gpu/drm/nouveau/include/nvkm/core/option.h index 532bfa8e3f72..80fdc146e816 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/option.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/option.h | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | const char *nvkm_stropt(const char *optstr, const char *opt, int *len); | 5 | const char *nvkm_stropt(const char *optstr, const char *opt, int *len); |
6 | bool nvkm_boolopt(const char *optstr, const char *opt, bool value); | 6 | bool nvkm_boolopt(const char *optstr, const char *opt, bool value); |
7 | long nvkm_longopt(const char *optstr, const char *opt, long value); | ||
7 | int nvkm_dbgopt(const char *optstr, const char *sub); | 8 | int nvkm_dbgopt(const char *optstr, const char *sub); |
8 | 9 | ||
9 | /* compares unterminated string 'str' with zero-terminated string 'cmp' */ | 10 | /* compares unterminated string 'str' with zero-terminated string 'cmp' */ |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h index ac14fdf2f967..5b3c054f3b55 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h | |||
@@ -7,6 +7,17 @@ struct nvkm_pci { | |||
7 | struct nvkm_subdev subdev; | 7 | struct nvkm_subdev subdev; |
8 | struct pci_dev *pdev; | 8 | struct pci_dev *pdev; |
9 | int irq; | 9 | int irq; |
10 | |||
11 | struct { | ||
12 | struct agp_bridge_data *bridge; | ||
13 | u32 mode; | ||
14 | u64 base; | ||
15 | u64 size; | ||
16 | int mtrr; | ||
17 | bool cma; | ||
18 | bool acquired; | ||
19 | } agp; | ||
20 | |||
10 | bool msi; | 21 | bool msi; |
11 | }; | 22 | }; |
12 | 23 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 4252e7796c4c..d336c2247d6a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
@@ -498,7 +498,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) | |||
498 | args.start += chan->ntfy_vma.offset; | 498 | args.start += chan->ntfy_vma.offset; |
499 | args.limit += chan->ntfy_vma.offset; | 499 | args.limit += chan->ntfy_vma.offset; |
500 | } else | 500 | } else |
501 | if (drm->agp.stat == ENABLED) { | 501 | if (drm->agp.bridge) { |
502 | args.target = NV_DMA_V0_TARGET_AGP; | 502 | args.target = NV_DMA_V0_TARGET_AGP; |
503 | args.access = NV_DMA_V0_ACCESS_RDWR; | 503 | args.access = NV_DMA_V0_ACCESS_RDWR; |
504 | args.start += drm->agp.base + chan->ntfy->bo.offset; | 504 | args.start += drm->agp.base + chan->ntfy->bo.offset; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c deleted file mode 100644 index c3f3e49e5f8f..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_agp.c +++ /dev/null | |||
@@ -1,198 +0,0 @@ | |||
1 | #include <linux/module.h> | ||
2 | |||
3 | #include "nouveau_drm.h" | ||
4 | #include "nouveau_agp.h" | ||
5 | #include "nouveau_reg.h" | ||
6 | |||
7 | #include <core/pci.h> | ||
8 | |||
9 | #if __OS_HAS_AGP | ||
10 | MODULE_PARM_DESC(agpmode, "AGP mode (0 to disable AGP)"); | ||
11 | static int nouveau_agpmode = -1; | ||
12 | module_param_named(agpmode, nouveau_agpmode, int, 0400); | ||
13 | |||
14 | struct nouveau_agpmode_quirk { | ||
15 | u16 hostbridge_vendor; | ||
16 | u16 hostbridge_device; | ||
17 | u16 chip_vendor; | ||
18 | u16 chip_device; | ||
19 | int mode; | ||
20 | }; | ||
21 | |||
22 | static struct nouveau_agpmode_quirk nouveau_agpmode_quirk_list[] = { | ||
23 | /* VIA Apollo PRO133x / GeForce FX 5600 Ultra, max agpmode 2, fdo #20341 */ | ||
24 | { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, | ||
25 | |||
26 | {}, | ||
27 | }; | ||
28 | |||
29 | static unsigned long | ||
30 | get_agp_mode(struct nouveau_drm *drm, const struct drm_agp_info *info) | ||
31 | { | ||
32 | struct nvif_device *device = &drm->device; | ||
33 | struct pci_dev *pdev = nvxx_device(device)->func->pci(nvxx_device(device))->pdev; | ||
34 | struct nouveau_agpmode_quirk *quirk = nouveau_agpmode_quirk_list; | ||
35 | int agpmode = nouveau_agpmode; | ||
36 | unsigned long mode = info->mode; | ||
37 | |||
38 | /* | ||
39 | * FW seems to be broken on nv18, it makes the card lock up | ||
40 | * randomly. | ||
41 | */ | ||
42 | if (device->info.chipset == 0x18) | ||
43 | mode &= ~PCI_AGP_COMMAND_FW; | ||
44 | |||
45 | /* | ||
46 | * Go through the quirks list and adjust the agpmode accordingly. | ||
47 | */ | ||
48 | while (agpmode == -1 && quirk->hostbridge_vendor) { | ||
49 | if (info->id_vendor == quirk->hostbridge_vendor && | ||
50 | info->id_device == quirk->hostbridge_device && | ||
51 | pdev->vendor == quirk->chip_vendor && | ||
52 | pdev->device == quirk->chip_device) { | ||
53 | agpmode = quirk->mode; | ||
54 | NV_INFO(drm, "Forcing agp mode to %dX. Use agpmode to override.\n", | ||
55 | agpmode); | ||
56 | break; | ||
57 | } | ||
58 | ++quirk; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * AGP mode set in the command line. | ||
63 | */ | ||
64 | if (agpmode > 0) { | ||
65 | bool agpv3 = mode & 0x8; | ||
66 | int rate = agpv3 ? agpmode / 4 : agpmode; | ||
67 | |||
68 | mode = (mode & ~0x7) | (rate & 0x7); | ||
69 | } | ||
70 | |||
71 | return mode; | ||
72 | } | ||
73 | |||
74 | static bool | ||
75 | nouveau_agp_enabled(struct nouveau_drm *drm) | ||
76 | { | ||
77 | struct drm_device *dev = drm->dev; | ||
78 | |||
79 | if (!dev->pdev || !drm_pci_device_is_agp(dev) || !dev->agp) | ||
80 | return false; | ||
81 | |||
82 | if (drm->agp.stat == UNKNOWN) { | ||
83 | if (!nouveau_agpmode) | ||
84 | return false; | ||
85 | #ifdef __powerpc__ | ||
86 | /* Disable AGP by default on all PowerPC machines for | ||
87 | * now -- At least some UniNorth-2 AGP bridges are | ||
88 | * known to be broken: DMA from the host to the card | ||
89 | * works just fine, but writeback from the card to the | ||
90 | * host goes straight to memory untranslated bypassing | ||
91 | * the GATT somehow, making them quite painful to deal | ||
92 | * with... | ||
93 | */ | ||
94 | if (nouveau_agpmode == -1) | ||
95 | return false; | ||
96 | #endif | ||
97 | return true; | ||
98 | } | ||
99 | |||
100 | return (drm->agp.stat == ENABLED); | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | void | ||
105 | nouveau_agp_reset(struct nouveau_drm *drm) | ||
106 | { | ||
107 | #if __OS_HAS_AGP | ||
108 | struct nvif_object *device = &drm->device.object; | ||
109 | struct drm_device *dev = drm->dev; | ||
110 | u32 save[2]; | ||
111 | int ret; | ||
112 | |||
113 | if (!nouveau_agp_enabled(drm)) | ||
114 | return; | ||
115 | |||
116 | /* First of all, disable fast writes, otherwise if it's | ||
117 | * already enabled in the AGP bridge and we disable the card's | ||
118 | * AGP controller we might be locking ourselves out of it. */ | ||
119 | if ((nvif_rd32(device, NV04_PBUS_PCI_NV_19) | | ||
120 | dev->agp->mode) & PCI_AGP_COMMAND_FW) { | ||
121 | struct drm_agp_info info; | ||
122 | struct drm_agp_mode mode; | ||
123 | |||
124 | ret = drm_agp_info(dev, &info); | ||
125 | if (ret) | ||
126 | return; | ||
127 | |||
128 | mode.mode = get_agp_mode(drm, &info); | ||
129 | mode.mode &= ~PCI_AGP_COMMAND_FW; | ||
130 | |||
131 | ret = drm_agp_enable(dev, mode); | ||
132 | if (ret) | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | |||
137 | /* clear busmaster bit, and disable AGP */ | ||
138 | save[0] = nvif_mask(device, NV04_PBUS_PCI_NV_1, 0x00000004, 0x00000000); | ||
139 | nvif_wr32(device, NV04_PBUS_PCI_NV_19, 0); | ||
140 | |||
141 | /* reset PGRAPH, PFIFO and PTIMER */ | ||
142 | save[1] = nvif_mask(device, 0x000200, 0x00011100, 0x00000000); | ||
143 | nvif_mask(device, 0x000200, 0x00011100, save[1]); | ||
144 | |||
145 | /* and restore bustmaster bit (gives effect of resetting AGP) */ | ||
146 | nvif_wr32(device, NV04_PBUS_PCI_NV_1, save[0]); | ||
147 | #endif | ||
148 | } | ||
149 | |||
150 | void | ||
151 | nouveau_agp_init(struct nouveau_drm *drm) | ||
152 | { | ||
153 | #if __OS_HAS_AGP | ||
154 | struct drm_device *dev = drm->dev; | ||
155 | struct drm_agp_info info; | ||
156 | struct drm_agp_mode mode; | ||
157 | int ret; | ||
158 | |||
159 | if (!nouveau_agp_enabled(drm)) | ||
160 | return; | ||
161 | drm->agp.stat = DISABLE; | ||
162 | |||
163 | ret = drm_agp_acquire(dev); | ||
164 | if (ret) { | ||
165 | NV_ERROR(drm, "unable to acquire AGP: %d\n", ret); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | ret = drm_agp_info(dev, &info); | ||
170 | if (ret) { | ||
171 | NV_ERROR(drm, "unable to get AGP info: %d\n", ret); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | /* see agp.h for the AGPSTAT_* modes available */ | ||
176 | mode.mode = get_agp_mode(drm, &info); | ||
177 | |||
178 | ret = drm_agp_enable(dev, mode); | ||
179 | if (ret) { | ||
180 | NV_ERROR(drm, "unable to enable AGP: %d\n", ret); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | drm->agp.stat = ENABLED; | ||
185 | drm->agp.base = info.aperture_base; | ||
186 | drm->agp.size = info.aperture_size; | ||
187 | #endif | ||
188 | } | ||
189 | |||
190 | void | ||
191 | nouveau_agp_fini(struct nouveau_drm *drm) | ||
192 | { | ||
193 | #if __OS_HAS_AGP | ||
194 | struct drm_device *dev = drm->dev; | ||
195 | if (dev->agp && dev->agp->acquired) | ||
196 | drm_agp_release(dev); | ||
197 | #endif | ||
198 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.h b/drivers/gpu/drm/nouveau/nouveau_agp.h deleted file mode 100644 index b55c08652963..000000000000 --- a/drivers/gpu/drm/nouveau/nouveau_agp.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | #ifndef __NOUVEAU_AGP_H__ | ||
2 | #define __NOUVEAU_AGP_H__ | ||
3 | |||
4 | struct nouveau_drm; | ||
5 | |||
6 | void nouveau_agp_reset(struct nouveau_drm *); | ||
7 | void nouveau_agp_init(struct nouveau_drm *); | ||
8 | void nouveau_agp_fini(struct nouveau_drm *); | ||
9 | |||
10 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 373fbd2d14ff..15057b39491c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -576,10 +576,9 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, | |||
576 | { | 576 | { |
577 | #if __OS_HAS_AGP | 577 | #if __OS_HAS_AGP |
578 | struct nouveau_drm *drm = nouveau_bdev(bdev); | 578 | struct nouveau_drm *drm = nouveau_bdev(bdev); |
579 | struct drm_device *dev = drm->dev; | ||
580 | 579 | ||
581 | if (drm->agp.stat == ENABLED) { | 580 | if (drm->agp.bridge) { |
582 | return ttm_agp_tt_create(bdev, dev->agp->bridge, size, | 581 | return ttm_agp_tt_create(bdev, drm->agp.bridge, size, |
583 | page_flags, dummy_read); | 582 | page_flags, dummy_read); |
584 | } | 583 | } |
585 | #endif | 584 | #endif |
@@ -631,12 +630,12 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | |||
631 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) | 630 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) |
632 | man->func = &nouveau_gart_manager; | 631 | man->func = &nouveau_gart_manager; |
633 | else | 632 | else |
634 | if (drm->agp.stat != ENABLED) | 633 | if (!drm->agp.bridge) |
635 | man->func = &nv04_gart_manager; | 634 | man->func = &nv04_gart_manager; |
636 | else | 635 | else |
637 | man->func = &ttm_bo_manager_func; | 636 | man->func = &ttm_bo_manager_func; |
638 | 637 | ||
639 | if (drm->agp.stat == ENABLED) { | 638 | if (drm->agp.bridge) { |
640 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; | 639 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; |
641 | man->available_caching = TTM_PL_FLAG_UNCACHED | | 640 | man->available_caching = TTM_PL_FLAG_UNCACHED | |
642 | TTM_PL_FLAG_WC; | 641 | TTM_PL_FLAG_WC; |
@@ -1368,10 +1367,10 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | |||
1368 | return 0; | 1367 | return 0; |
1369 | case TTM_PL_TT: | 1368 | case TTM_PL_TT: |
1370 | #if __OS_HAS_AGP | 1369 | #if __OS_HAS_AGP |
1371 | if (drm->agp.stat == ENABLED) { | 1370 | if (drm->agp.bridge) { |
1372 | mem->bus.offset = mem->start << PAGE_SHIFT; | 1371 | mem->bus.offset = mem->start << PAGE_SHIFT; |
1373 | mem->bus.base = drm->agp.base; | 1372 | mem->bus.base = drm->agp.base; |
1374 | mem->bus.is_iomem = !drm->dev->agp->cant_use_aperture; | 1373 | mem->bus.is_iomem = !drm->agp.cma; |
1375 | } | 1374 | } |
1376 | #endif | 1375 | #endif |
1377 | if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype) | 1376 | if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA || !node->memtype) |
@@ -1498,7 +1497,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) | |||
1498 | return ttm_dma_populate(ttm_dma, dev->dev); | 1497 | return ttm_dma_populate(ttm_dma, dev->dev); |
1499 | 1498 | ||
1500 | #if __OS_HAS_AGP | 1499 | #if __OS_HAS_AGP |
1501 | if (drm->agp.stat == ENABLED) { | 1500 | if (drm->agp.bridge) { |
1502 | return ttm_agp_tt_populate(ttm); | 1501 | return ttm_agp_tt_populate(ttm); |
1503 | } | 1502 | } |
1504 | #endif | 1503 | #endif |
@@ -1565,7 +1564,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) | |||
1565 | } | 1564 | } |
1566 | 1565 | ||
1567 | #if __OS_HAS_AGP | 1566 | #if __OS_HAS_AGP |
1568 | if (drm->agp.stat == ENABLED) { | 1567 | if (drm->agp.bridge) { |
1569 | ttm_agp_tt_unpopulate(ttm); | 1568 | ttm_agp_tt_unpopulate(ttm); |
1570 | return; | 1569 | return; |
1571 | } | 1570 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index f59c4f5716cc..ff5e59db49db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c | |||
@@ -160,7 +160,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, | |||
160 | args.limit = device->info.ram_user - 1; | 160 | args.limit = device->info.ram_user - 1; |
161 | } | 161 | } |
162 | } else { | 162 | } else { |
163 | if (chan->drm->agp.stat == ENABLED) { | 163 | if (chan->drm->agp.bridge) { |
164 | args.target = NV_DMA_V0_TARGET_AGP; | 164 | args.target = NV_DMA_V0_TARGET_AGP; |
165 | args.access = NV_DMA_V0_ACCESS_RDWR; | 165 | args.access = NV_DMA_V0_ACCESS_RDWR; |
166 | args.start = chan->drm->agp.base; | 166 | args.start = chan->drm->agp.base; |
@@ -328,7 +328,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
328 | args.start = 0; | 328 | args.start = 0; |
329 | args.limit = cli->vm->mmu->limit - 1; | 329 | args.limit = cli->vm->mmu->limit - 1; |
330 | } else | 330 | } else |
331 | if (chan->drm->agp.stat == ENABLED) { | 331 | if (chan->drm->agp.bridge) { |
332 | args.target = NV_DMA_V0_TARGET_AGP; | 332 | args.target = NV_DMA_V0_TARGET_AGP; |
333 | args.access = NV_DMA_V0_ACCESS_RDWR; | 333 | args.access = NV_DMA_V0_ACCESS_RDWR; |
334 | args.start = chan->drm->agp.base; | 334 | args.start = chan->drm->agp.base; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 14a13486c27f..ccefb645fd55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include "nouveau_dma.h" | 41 | #include "nouveau_dma.h" |
42 | #include "nouveau_ttm.h" | 42 | #include "nouveau_ttm.h" |
43 | #include "nouveau_gem.h" | 43 | #include "nouveau_gem.h" |
44 | #include "nouveau_agp.h" | ||
45 | #include "nouveau_vga.h" | 44 | #include "nouveau_vga.h" |
46 | #include "nouveau_sysfs.h" | 45 | #include "nouveau_sysfs.h" |
47 | #include "nouveau_hwmon.h" | 46 | #include "nouveau_hwmon.h" |
@@ -423,7 +422,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
423 | nvif_mask(&drm->device.object, 0x00088080, 0x00000800, 0x00000000); | 422 | nvif_mask(&drm->device.object, 0x00088080, 0x00000800, 0x00000000); |
424 | 423 | ||
425 | nouveau_vga_init(drm); | 424 | nouveau_vga_init(drm); |
426 | nouveau_agp_init(drm); | ||
427 | 425 | ||
428 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { | 426 | if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { |
429 | ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40), | 427 | ret = nvkm_vm_new(nvxx_device(&drm->device), 0, (1ULL << 40), |
@@ -474,7 +472,6 @@ fail_dispctor: | |||
474 | fail_bios: | 472 | fail_bios: |
475 | nouveau_ttm_fini(drm); | 473 | nouveau_ttm_fini(drm); |
476 | fail_ttm: | 474 | fail_ttm: |
477 | nouveau_agp_fini(drm); | ||
478 | nouveau_vga_fini(drm); | 475 | nouveau_vga_fini(drm); |
479 | fail_device: | 476 | fail_device: |
480 | nvif_device_fini(&drm->device); | 477 | nvif_device_fini(&drm->device); |
@@ -500,7 +497,6 @@ nouveau_drm_unload(struct drm_device *dev) | |||
500 | nouveau_bios_takedown(dev); | 497 | nouveau_bios_takedown(dev); |
501 | 498 | ||
502 | nouveau_ttm_fini(drm); | 499 | nouveau_ttm_fini(drm); |
503 | nouveau_agp_fini(drm); | ||
504 | nouveau_vga_fini(drm); | 500 | nouveau_vga_fini(drm); |
505 | 501 | ||
506 | nvif_device_fini(&drm->device); | 502 | nvif_device_fini(&drm->device); |
@@ -584,7 +580,6 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) | |||
584 | if (ret) | 580 | if (ret) |
585 | goto fail_client; | 581 | goto fail_client; |
586 | 582 | ||
587 | nouveau_agp_fini(drm); | ||
588 | return 0; | 583 | return 0; |
589 | 584 | ||
590 | fail_client: | 585 | fail_client: |
@@ -609,13 +604,8 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) | |||
609 | struct nouveau_drm *drm = nouveau_drm(dev); | 604 | struct nouveau_drm *drm = nouveau_drm(dev); |
610 | struct nouveau_cli *cli; | 605 | struct nouveau_cli *cli; |
611 | 606 | ||
612 | NV_INFO(drm, "re-enabling device...\n"); | ||
613 | |||
614 | nouveau_agp_reset(drm); | ||
615 | |||
616 | NV_INFO(drm, "resuming kernel object tree...\n"); | 607 | NV_INFO(drm, "resuming kernel object tree...\n"); |
617 | nvif_client_resume(&drm->client.base); | 608 | nvif_client_resume(&drm->client.base); |
618 | nouveau_agp_init(drm); | ||
619 | 609 | ||
620 | NV_INFO(drm, "resuming client object trees...\n"); | 610 | NV_INFO(drm, "resuming client object trees...\n"); |
621 | if (drm->fence && nouveau_fence(drm)->resume) | 611 | if (drm->fence && nouveau_fence(drm)->resume) |
@@ -929,7 +919,6 @@ nouveau_driver_fops = { | |||
929 | static struct drm_driver | 919 | static struct drm_driver |
930 | driver_stub = { | 920 | driver_stub = { |
931 | .driver_features = | 921 | .driver_features = |
932 | DRIVER_USE_AGP | | ||
933 | DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | | 922 | DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | |
934 | DRIVER_KMS_LEGACY_CONTEXT, | 923 | DRIVER_KMS_LEGACY_CONTEXT, |
935 | 924 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index f18710afcfd3..7fb3a8ad12d7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h | |||
@@ -111,13 +111,10 @@ struct nouveau_drm { | |||
111 | struct list_head clients; | 111 | struct list_head clients; |
112 | 112 | ||
113 | struct { | 113 | struct { |
114 | enum { | 114 | struct agp_bridge_data *bridge; |
115 | UNKNOWN = 0, | ||
116 | DISABLE = 1, | ||
117 | ENABLED = 2 | ||
118 | } stat; | ||
119 | u32 base; | 115 | u32 base; |
120 | u32 size; | 116 | u32 size; |
117 | bool cma; | ||
121 | } agp; | 118 | } agp; |
122 | 119 | ||
123 | /* TTM interface support */ | 120 | /* TTM interface support */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index ba9fd151bd28..3f0fb55cb473 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
@@ -336,13 +336,21 @@ int | |||
336 | nouveau_ttm_init(struct nouveau_drm *drm) | 336 | nouveau_ttm_init(struct nouveau_drm *drm) |
337 | { | 337 | { |
338 | struct nvkm_device *device = nvxx_device(&drm->device); | 338 | struct nvkm_device *device = nvxx_device(&drm->device); |
339 | struct nvkm_pci *pci = device->pci; | ||
339 | struct drm_device *dev = drm->dev; | 340 | struct drm_device *dev = drm->dev; |
340 | u32 bits; | 341 | u32 bits; |
341 | int ret; | 342 | int ret; |
342 | 343 | ||
344 | if (pci && pci->agp.bridge) { | ||
345 | drm->agp.bridge = pci->agp.bridge; | ||
346 | drm->agp.base = pci->agp.base; | ||
347 | drm->agp.size = pci->agp.size; | ||
348 | drm->agp.cma = pci->agp.cma; | ||
349 | } | ||
350 | |||
343 | bits = nvxx_mmu(&drm->device)->dma_bits; | 351 | bits = nvxx_mmu(&drm->device)->dma_bits; |
344 | if (nvxx_device(&drm->device)->func->pci) { | 352 | if (nvxx_device(&drm->device)->func->pci) { |
345 | if (drm->agp.stat == ENABLED || | 353 | if (drm->agp.bridge || |
346 | !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) | 354 | !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) |
347 | bits = 32; | 355 | bits = 32; |
348 | 356 | ||
@@ -386,7 +394,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) | |||
386 | device->func->resource_size(device, 1)); | 394 | device->func->resource_size(device, 1)); |
387 | 395 | ||
388 | /* GART init */ | 396 | /* GART init */ |
389 | if (drm->agp.stat != ENABLED) { | 397 | if (!drm->agp.bridge) { |
390 | drm->gem.gart_available = nvxx_mmu(&drm->device)->limit; | 398 | drm->gem.gart_available = nvxx_mmu(&drm->device)->limit; |
391 | } else { | 399 | } else { |
392 | drm->gem.gart_available = drm->agp.size; | 400 | drm->gem.gart_available = drm->agp.size; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/option.c b/drivers/gpu/drm/nouveau/nvkm/core/option.c index 98ebde3b7269..3e62cf8cde08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/option.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/option.c | |||
@@ -73,6 +73,24 @@ nvkm_boolopt(const char *optstr, const char *opt, bool value) | |||
73 | return value; | 73 | return value; |
74 | } | 74 | } |
75 | 75 | ||
76 | long | ||
77 | nvkm_longopt(const char *optstr, const char *opt, long value) | ||
78 | { | ||
79 | long result = value; | ||
80 | int arglen; | ||
81 | char *s; | ||
82 | |||
83 | optstr = nvkm_stropt(optstr, opt, &arglen); | ||
84 | if (optstr && (s = kstrndup(optstr, arglen, GFP_KERNEL))) { | ||
85 | int ret = kstrtol(s, 0, &value); | ||
86 | if (ret == 0) | ||
87 | result = value; | ||
88 | kfree(s); | ||
89 | } | ||
90 | |||
91 | return result; | ||
92 | } | ||
93 | |||
76 | int | 94 | int |
77 | nvkm_dbgopt(const char *optstr, const char *sub) | 95 | nvkm_dbgopt(const char *optstr, const char *sub) |
78 | { | 96 | { |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild index a8e9b0fc447e..99672c3d0bad 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | nvkm-y += nvkm/subdev/pci/agp.o | ||
1 | nvkm-y += nvkm/subdev/pci/base.o | 2 | nvkm-y += nvkm/subdev/pci/base.o |
2 | nvkm-y += nvkm/subdev/pci/nv04.o | 3 | nvkm-y += nvkm/subdev/pci/nv04.o |
3 | nvkm-y += nvkm/subdev/pci/nv40.o | 4 | nvkm-y += nvkm/subdev/pci/nv40.o |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c new file mode 100644 index 000000000000..814cb51cc873 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Nouveau Project | ||
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 | #include "agp.h" | ||
23 | #ifdef __NVKM_PCI_AGP_H__ | ||
24 | #include <core/option.h> | ||
25 | |||
26 | struct nvkm_device_agp_quirk { | ||
27 | u16 hostbridge_vendor; | ||
28 | u16 hostbridge_device; | ||
29 | u16 chip_vendor; | ||
30 | u16 chip_device; | ||
31 | int mode; | ||
32 | }; | ||
33 | |||
34 | static const struct nvkm_device_agp_quirk | ||
35 | nvkm_device_agp_quirks[] = { | ||
36 | /* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */ | ||
37 | { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 }, | ||
38 | {}, | ||
39 | }; | ||
40 | |||
41 | void | ||
42 | nvkm_agp_fini(struct nvkm_pci *pci) | ||
43 | { | ||
44 | if (pci->agp.acquired) { | ||
45 | agp_backend_release(pci->agp.bridge); | ||
46 | pci->agp.acquired = false; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | /* Ensure AGP controller is in a consistent state in case we need to | ||
51 | * execute the VBIOS DEVINIT scripts. | ||
52 | */ | ||
53 | void | ||
54 | nvkm_agp_preinit(struct nvkm_pci *pci) | ||
55 | { | ||
56 | struct nvkm_device *device = pci->subdev.device; | ||
57 | u32 mode = nvkm_pci_rd32(pci, 0x004c); | ||
58 | u32 save[2]; | ||
59 | |||
60 | /* First of all, disable fast writes, otherwise if it's already | ||
61 | * enabled in the AGP bridge and we disable the card's AGP | ||
62 | * controller we might be locking ourselves out of it. | ||
63 | */ | ||
64 | if ((mode | pci->agp.mode) & PCI_AGP_COMMAND_FW) { | ||
65 | mode = pci->agp.mode & ~PCI_AGP_COMMAND_FW; | ||
66 | agp_enable(pci->agp.bridge, mode); | ||
67 | } | ||
68 | |||
69 | /* clear busmaster bit, and disable AGP */ | ||
70 | save[0] = nvkm_pci_rd32(pci, 0x0004); | ||
71 | nvkm_pci_wr32(pci, 0x0004, save[0] & ~0x00000004); | ||
72 | nvkm_pci_wr32(pci, 0x004c, 0x00000000); | ||
73 | |||
74 | /* reset PGRAPH, PFIFO and PTIMER */ | ||
75 | save[1] = nvkm_mask(device, 0x000200, 0x00011100, 0x00000000); | ||
76 | nvkm_mask(device, 0x000200, 0x00011100, save[1]); | ||
77 | |||
78 | /* and restore busmaster bit (gives effect of resetting AGP) */ | ||
79 | nvkm_pci_wr32(pci, 0x0004, save[0]); | ||
80 | } | ||
81 | |||
82 | int | ||
83 | nvkm_agp_init(struct nvkm_pci *pci) | ||
84 | { | ||
85 | if (!agp_backend_acquire(pci->pdev)) { | ||
86 | nvkm_error(&pci->subdev, "failed to acquire agp\n"); | ||
87 | return -ENODEV; | ||
88 | } | ||
89 | |||
90 | agp_enable(pci->agp.bridge, pci->agp.mode); | ||
91 | pci->agp.acquired = true; | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | void | ||
96 | nvkm_agp_dtor(struct nvkm_pci *pci) | ||
97 | { | ||
98 | arch_phys_wc_del(pci->agp.mtrr); | ||
99 | } | ||
100 | |||
101 | void | ||
102 | nvkm_agp_ctor(struct nvkm_pci *pci) | ||
103 | { | ||
104 | const struct nvkm_device_agp_quirk *quirk = nvkm_device_agp_quirks; | ||
105 | struct nvkm_subdev *subdev = &pci->subdev; | ||
106 | struct nvkm_device *device = subdev->device; | ||
107 | struct agp_kern_info info; | ||
108 | int mode = -1; | ||
109 | |||
110 | #ifdef __powerpc__ | ||
111 | /* Disable AGP by default on all PowerPC machines for now -- At | ||
112 | * least some UniNorth-2 AGP bridges are known to be broken: | ||
113 | * DMA from the host to the card works just fine, but writeback | ||
114 | * from the card to the host goes straight to memory | ||
115 | * untranslated bypassing that GATT somehow, making them quite | ||
116 | * painful to deal with... | ||
117 | */ | ||
118 | mode = 0; | ||
119 | #endif | ||
120 | mode = nvkm_longopt(device->cfgopt, "NvAGP", mode); | ||
121 | |||
122 | /* acquire bridge temporarily, so that we can copy its info */ | ||
123 | if (!(pci->agp.bridge = agp_backend_acquire(pci->pdev))) { | ||
124 | nvkm_warn(subdev, "failed to acquire agp\n"); | ||
125 | return; | ||
126 | } | ||
127 | agp_copy_info(pci->agp.bridge, &info); | ||
128 | agp_backend_release(pci->agp.bridge); | ||
129 | |||
130 | pci->agp.mode = info.mode; | ||
131 | pci->agp.base = info.aper_base; | ||
132 | pci->agp.size = info.aper_size * 1024 * 1024; | ||
133 | pci->agp.cma = info.cant_use_aperture; | ||
134 | pci->agp.mtrr = -1; | ||
135 | |||
136 | /* determine if bridge + chipset combination needs a workaround */ | ||
137 | while (quirk->hostbridge_vendor) { | ||
138 | if (info.device->vendor == quirk->hostbridge_vendor && | ||
139 | info.device->device == quirk->hostbridge_device && | ||
140 | pci->pdev->vendor == quirk->chip_vendor && | ||
141 | pci->pdev->device == quirk->chip_device) { | ||
142 | nvkm_info(subdev, "forcing default agp mode to %dX, " | ||
143 | "use NvAGP=<mode> to override\n", | ||
144 | quirk->mode); | ||
145 | mode = quirk->mode; | ||
146 | break; | ||
147 | } | ||
148 | quirk++; | ||
149 | } | ||
150 | |||
151 | /* apply quirk / user-specified mode */ | ||
152 | if (mode >= 1) { | ||
153 | if (pci->agp.mode & 0x00000008) | ||
154 | mode /= 4; /* AGPv3 */ | ||
155 | pci->agp.mode &= ~0x00000007; | ||
156 | pci->agp.mode |= (mode & 0x7); | ||
157 | } else | ||
158 | if (mode == 0) { | ||
159 | pci->agp.bridge = NULL; | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | /* fast writes appear to be broken on nv18, they make the card | ||
164 | * lock up randomly. | ||
165 | */ | ||
166 | if (device->chipset == 0x18) | ||
167 | pci->agp.mode &= ~PCI_AGP_COMMAND_FW; | ||
168 | |||
169 | pci->agp.mtrr = arch_phys_wc_add(pci->agp.base, pci->agp.size); | ||
170 | } | ||
171 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h new file mode 100644 index 000000000000..df2dd08363ad --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #include "priv.h" | ||
2 | #if defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)) | ||
3 | #ifndef __NVKM_PCI_AGP_H__ | ||
4 | #define __NVKM_PCI_AGP_H__ | ||
5 | |||
6 | void nvkm_agp_ctor(struct nvkm_pci *); | ||
7 | void nvkm_agp_dtor(struct nvkm_pci *); | ||
8 | void nvkm_agp_preinit(struct nvkm_pci *); | ||
9 | int nvkm_agp_init(struct nvkm_pci *); | ||
10 | void nvkm_agp_fini(struct nvkm_pci *); | ||
11 | #endif | ||
12 | #else | ||
13 | static inline void nvkm_agp_ctor(struct nvkm_pci *pci) {} | ||
14 | static inline void nvkm_agp_dtor(struct nvkm_pci *pci) {} | ||
15 | static inline void nvkm_agp_preinit(struct nvkm_pci *pci) {} | ||
16 | static inline int nvkm_agp_init(struct nvkm_pci *pci) { return -ENOSYS; } | ||
17 | static inline void nvkm_agp_fini(struct nvkm_pci *pci) {} | ||
18 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index e5e0d02f3d88..d1c148e51922 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c | |||
@@ -22,6 +22,7 @@ | |||
22 | * Authors: Ben Skeggs <bskeggs@redhat.com> | 22 | * Authors: Ben Skeggs <bskeggs@redhat.com> |
23 | */ | 23 | */ |
24 | #include "priv.h" | 24 | #include "priv.h" |
25 | #include "agp.h" | ||
25 | 26 | ||
26 | #include <core/option.h> | 27 | #include <core/option.h> |
27 | #include <core/pci.h> | 28 | #include <core/pci.h> |
@@ -76,10 +77,24 @@ static int | |||
76 | nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) | 77 | nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) |
77 | { | 78 | { |
78 | struct nvkm_pci *pci = nvkm_pci(subdev); | 79 | struct nvkm_pci *pci = nvkm_pci(subdev); |
80 | |||
79 | if (pci->irq >= 0) { | 81 | if (pci->irq >= 0) { |
80 | free_irq(pci->irq, pci); | 82 | free_irq(pci->irq, pci); |
81 | pci->irq = -1; | 83 | pci->irq = -1; |
82 | }; | 84 | }; |
85 | |||
86 | if (pci->agp.bridge) | ||
87 | nvkm_agp_fini(pci); | ||
88 | |||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int | ||
93 | nvkm_pci_preinit(struct nvkm_subdev *subdev) | ||
94 | { | ||
95 | struct nvkm_pci *pci = nvkm_pci(subdev); | ||
96 | if (pci->agp.bridge) | ||
97 | nvkm_agp_preinit(pci); | ||
83 | return 0; | 98 | return 0; |
84 | } | 99 | } |
85 | 100 | ||
@@ -90,6 +105,12 @@ nvkm_pci_init(struct nvkm_subdev *subdev) | |||
90 | struct pci_dev *pdev = pci->pdev; | 105 | struct pci_dev *pdev = pci->pdev; |
91 | int ret; | 106 | int ret; |
92 | 107 | ||
108 | if (pci->agp.bridge) { | ||
109 | ret = nvkm_agp_init(pci); | ||
110 | if (ret) | ||
111 | return ret; | ||
112 | } | ||
113 | |||
93 | ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); | 114 | ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); |
94 | if (ret) | 115 | if (ret) |
95 | return ret; | 116 | return ret; |
@@ -102,6 +123,7 @@ static void * | |||
102 | nvkm_pci_dtor(struct nvkm_subdev *subdev) | 123 | nvkm_pci_dtor(struct nvkm_subdev *subdev) |
103 | { | 124 | { |
104 | struct nvkm_pci *pci = nvkm_pci(subdev); | 125 | struct nvkm_pci *pci = nvkm_pci(subdev); |
126 | nvkm_agp_dtor(pci); | ||
105 | if (pci->msi) | 127 | if (pci->msi) |
106 | pci_disable_msi(pci->pdev); | 128 | pci_disable_msi(pci->pdev); |
107 | return nvkm_pci(subdev); | 129 | return nvkm_pci(subdev); |
@@ -110,6 +132,7 @@ nvkm_pci_dtor(struct nvkm_subdev *subdev) | |||
110 | static const struct nvkm_subdev_func | 132 | static const struct nvkm_subdev_func |
111 | nvkm_pci_func = { | 133 | nvkm_pci_func = { |
112 | .dtor = nvkm_pci_dtor, | 134 | .dtor = nvkm_pci_dtor, |
135 | .preinit = nvkm_pci_preinit, | ||
113 | .init = nvkm_pci_init, | 136 | .init = nvkm_pci_init, |
114 | .fini = nvkm_pci_fini, | 137 | .fini = nvkm_pci_fini, |
115 | }; | 138 | }; |
@@ -127,6 +150,9 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device, | |||
127 | pci->pdev = device->func->pci(device)->pdev; | 150 | pci->pdev = device->func->pci(device)->pdev; |
128 | pci->irq = -1; | 151 | pci->irq = -1; |
129 | 152 | ||
153 | if (device->type == NVKM_DEVICE_AGP) | ||
154 | nvkm_agp_ctor(pci); | ||
155 | |||
130 | switch (pci->pdev->device & 0x0ff0) { | 156 | switch (pci->pdev->device & 0x0ff0) { |
131 | case 0x00f0: | 157 | case 0x00f0: |
132 | case 0x02e0: | 158 | case 0x02e0: |