1 /*	$NetBSD: nouveau_engine_device_base.c,v 1.11 2016/05/11 02:28:33 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2012 Red Hat Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Ben Skeggs
25  */
26 
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: nouveau_engine_device_base.c,v 1.11 2016/05/11 02:28:33 riastradh Exp $");
29 
30 #include <core/object.h>
31 #include <core/device.h>
32 #include <core/client.h>
33 #include <core/option.h>
34 
35 #include <core/class.h>
36 
37 #include "priv.h"
38 
39 #ifdef __NetBSD__
40 static struct mutex nv_devices_mutex;
41 static struct list_head nv_devices = LIST_HEAD_INIT(nv_devices);
42 
43 void
nouveau_devices_init(void)44 nouveau_devices_init(void)
45 {
46 
47 	linux_mutex_init(&nv_devices_mutex);
48 }
49 
50 void
nouveau_devices_fini(void)51 nouveau_devices_fini(void)
52 {
53 
54 	linux_mutex_destroy(&nv_devices_mutex);
55 }
56 #else
57 static DEFINE_MUTEX(nv_devices_mutex);
58 static LIST_HEAD(nv_devices);
59 #endif
60 
61 struct nouveau_device *
nouveau_device_find(u64 name)62 nouveau_device_find(u64 name)
63 {
64 	struct nouveau_device *device, *match = NULL;
65 	mutex_lock(&nv_devices_mutex);
66 	list_for_each_entry(device, &nv_devices, head) {
67 		if (device->handle == name) {
68 			match = device;
69 			break;
70 		}
71 	}
72 	mutex_unlock(&nv_devices_mutex);
73 	return match;
74 }
75 
76 /******************************************************************************
77  * nouveau_devobj (0x0080): class implementation
78  *****************************************************************************/
79 struct nouveau_devobj {
80 	struct nouveau_parent base;
81 	struct nouveau_object *subdev[NVDEV_SUBDEV_NR];
82 };
83 
84 static const u64 disable_map[] = {
85 	[NVDEV_SUBDEV_VBIOS]	= NV_DEVICE_DISABLE_VBIOS,
86 	[NVDEV_SUBDEV_DEVINIT]	= NV_DEVICE_DISABLE_CORE,
87 	[NVDEV_SUBDEV_GPIO]	= NV_DEVICE_DISABLE_CORE,
88 	[NVDEV_SUBDEV_I2C]	= NV_DEVICE_DISABLE_CORE,
89 	[NVDEV_SUBDEV_CLOCK]	= NV_DEVICE_DISABLE_CORE,
90 	[NVDEV_SUBDEV_MXM]	= NV_DEVICE_DISABLE_CORE,
91 	[NVDEV_SUBDEV_MC]	= NV_DEVICE_DISABLE_CORE,
92 	[NVDEV_SUBDEV_BUS]	= NV_DEVICE_DISABLE_CORE,
93 	[NVDEV_SUBDEV_TIMER]	= NV_DEVICE_DISABLE_CORE,
94 	[NVDEV_SUBDEV_FB]	= NV_DEVICE_DISABLE_CORE,
95 	[NVDEV_SUBDEV_LTCG]	= NV_DEVICE_DISABLE_CORE,
96 	[NVDEV_SUBDEV_IBUS]	= NV_DEVICE_DISABLE_CORE,
97 	[NVDEV_SUBDEV_INSTMEM]	= NV_DEVICE_DISABLE_CORE,
98 	[NVDEV_SUBDEV_VM]	= NV_DEVICE_DISABLE_CORE,
99 	[NVDEV_SUBDEV_BAR]	= NV_DEVICE_DISABLE_CORE,
100 	[NVDEV_SUBDEV_VOLT]	= NV_DEVICE_DISABLE_CORE,
101 	[NVDEV_SUBDEV_THERM]	= NV_DEVICE_DISABLE_CORE,
102 	[NVDEV_SUBDEV_PWR]	= NV_DEVICE_DISABLE_CORE,
103 	[NVDEV_ENGINE_DMAOBJ]	= NV_DEVICE_DISABLE_CORE,
104 	[NVDEV_ENGINE_PERFMON]  = NV_DEVICE_DISABLE_CORE,
105 	[NVDEV_ENGINE_FIFO]	= NV_DEVICE_DISABLE_FIFO,
106 	[NVDEV_ENGINE_SW]	= NV_DEVICE_DISABLE_FIFO,
107 	[NVDEV_ENGINE_GR]	= NV_DEVICE_DISABLE_GRAPH,
108 	[NVDEV_ENGINE_MPEG]	= NV_DEVICE_DISABLE_MPEG,
109 	[NVDEV_ENGINE_ME]	= NV_DEVICE_DISABLE_ME,
110 	[NVDEV_ENGINE_VP]	= NV_DEVICE_DISABLE_VP,
111 	[NVDEV_ENGINE_CRYPT]	= NV_DEVICE_DISABLE_CRYPT,
112 	[NVDEV_ENGINE_BSP]	= NV_DEVICE_DISABLE_BSP,
113 	[NVDEV_ENGINE_PPP]	= NV_DEVICE_DISABLE_PPP,
114 	[NVDEV_ENGINE_COPY0]	= NV_DEVICE_DISABLE_COPY0,
115 	[NVDEV_ENGINE_COPY1]	= NV_DEVICE_DISABLE_COPY1,
116 	[NVDEV_ENGINE_VIC]	= NV_DEVICE_DISABLE_VIC,
117 	[NVDEV_ENGINE_VENC]	= NV_DEVICE_DISABLE_VENC,
118 	[NVDEV_ENGINE_DISP]	= NV_DEVICE_DISABLE_DISP,
119 	[NVDEV_SUBDEV_NR]	= 0,
120 };
121 
122 static int
nouveau_devobj_ctor(struct nouveau_object * parent,struct nouveau_object * engine,struct nouveau_oclass * oclass,void * data,u32 size,struct nouveau_object ** pobject)123 nouveau_devobj_ctor(struct nouveau_object *parent,
124 		    struct nouveau_object *engine,
125 		    struct nouveau_oclass *oclass, void *data, u32 size,
126 		    struct nouveau_object **pobject)
127 {
128 	struct nouveau_client *client = nv_client(parent);
129 	struct nouveau_device *device;
130 	struct nouveau_devobj *devobj;
131 	struct nv_device_class *args = data;
132 	u32 boot0, strap;
133 	u64 disable, mmio_base, mmio_size;
134 #ifdef __NetBSD__
135 	bus_space_tag_t mmiot;
136 	bus_space_handle_t mmioh;
137 #else
138 	void __iomem *map;
139 #endif
140 	int ret, i, c;
141 
142 	if (size < sizeof(struct nv_device_class))
143 		return -EINVAL;
144 
145 	/* find the device subdev that matches what the client requested */
146 	device = nv_device(client->device);
147 	if (args->device != ~0) {
148 		device = nouveau_device_find(args->device);
149 		if (!device)
150 			return -ENODEV;
151 	}
152 
153 	ret = nouveau_parent_create(parent, nv_object(device), oclass, 0,
154 				    nouveau_control_oclass,
155 				    (1ULL << NVDEV_ENGINE_DMAOBJ) |
156 				    (1ULL << NVDEV_ENGINE_FIFO) |
157 				    (1ULL << NVDEV_ENGINE_DISP) |
158 				    (1ULL << NVDEV_ENGINE_PERFMON), &devobj);
159 	*pobject = nv_object(devobj);
160 	if (ret)
161 		return ret;
162 
163 #ifdef __NetBSD__
164 	mmiot = nv_device_resource_tag(device, 0);
165 #endif
166 	mmio_base = nv_device_resource_start(device, 0);
167 	mmio_size = nv_device_resource_len(device, 0);
168 
169 	/* translate api disable mask into internal mapping */
170 	disable = args->debug0;
171 	for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
172 		if (args->disable & disable_map[i])
173 			disable |= (1ULL << i);
174 	}
175 
176 	/* identify the chipset, and determine classes of subdev/engines */
177 	if (!(args->disable & NV_DEVICE_DISABLE_IDENTIFY) &&
178 	    !device->card_type) {
179 #ifdef __NetBSD__
180 		if (mmio_size < 0x102000)
181 			return -ENOMEM;
182 		/* XXX errno NetBSD->Linux */
183 		ret = -bus_space_map(mmiot, mmio_base, 0x102000, 0, &mmioh);
184 		if (ret)
185 			return ret;
186 
187 #ifndef __BIG_ENDIAN
188 		if (bus_space_read_4(mmiot, mmioh, 4) != 0)
189 #else
190 		if (bus_space_read_4(mmiot, mmioh, 4) == 0)
191 #endif
192 			bus_space_write_4(mmiot, mmioh, 4, 0x01000001);
193 
194 		boot0 = bus_space_read_4(mmiot, mmioh, 0x000000);
195 		strap = bus_space_read_4(mmiot, mmioh, 0x101000);
196 		bus_space_unmap(mmiot, mmioh, 0x102000);
197 #else
198 		map = ioremap(mmio_base, 0x102000);
199 		if (map == NULL)
200 			return -ENOMEM;
201 
202 		/* switch mmio to cpu's native endianness */
203 #ifndef __BIG_ENDIAN
204 		if (ioread32_native(map + 0x000004) != 0x00000000)
205 #else
206 		if (ioread32_native(map + 0x000004) == 0x00000000)
207 #endif
208 			iowrite32_native(0x01000001, map + 0x000004);
209 
210 		/* read boot0 and strapping information */
211 		boot0 = ioread32_native(map + 0x000000);
212 		strap = ioread32_native(map + 0x101000);
213 		iounmap(map);
214 #endif
215 
216 		/* determine chipset and derive architecture from it */
217 		if ((boot0 & 0x1f000000) > 0) {
218 			device->chipset = (boot0 & 0x1ff00000) >> 20;
219 			switch (device->chipset & 0x1f0) {
220 			case 0x010: {
221 				if (0x461 & (1 << (device->chipset & 0xf)))
222 					device->card_type = NV_10;
223 				else
224 					device->card_type = NV_11;
225 				break;
226 			}
227 			case 0x020: device->card_type = NV_20; break;
228 			case 0x030: device->card_type = NV_30; break;
229 			case 0x040:
230 			case 0x060: device->card_type = NV_40; break;
231 			case 0x050:
232 			case 0x080:
233 			case 0x090:
234 			case 0x0a0: device->card_type = NV_50; break;
235 			case 0x0c0: device->card_type = NV_C0; break;
236 			case 0x0d0: device->card_type = NV_D0; break;
237 			case 0x0e0:
238 			case 0x0f0:
239 			case 0x100: device->card_type = NV_E0; break;
240 			case 0x110: device->card_type = GM100; break;
241 			default:
242 				break;
243 			}
244 		} else
245 		if ((boot0 & 0xff00fff0) == 0x20004000) {
246 			if (boot0 & 0x00f00000)
247 				device->chipset = 0x05;
248 			else
249 				device->chipset = 0x04;
250 			device->card_type = NV_04;
251 		}
252 
253 		switch (device->card_type) {
254 		case NV_04: ret = nv04_identify(device); break;
255 		case NV_10:
256 		case NV_11: ret = nv10_identify(device); break;
257 		case NV_20: ret = nv20_identify(device); break;
258 		case NV_30: ret = nv30_identify(device); break;
259 		case NV_40: ret = nv40_identify(device); break;
260 		case NV_50: ret = nv50_identify(device); break;
261 		case NV_C0:
262 		case NV_D0: ret = nvc0_identify(device); break;
263 		case NV_E0: ret = nve0_identify(device); break;
264 		case GM100: ret = gm100_identify(device); break;
265 		default:
266 			ret = -EINVAL;
267 			break;
268 		}
269 
270 		if (ret) {
271 			nv_error(device, "unknown chipset, 0x%08x\n", boot0);
272 			return ret;
273 		}
274 
275 		nv_info(device, "BOOT0  : 0x%08x\n", boot0);
276 		nv_info(device, "Chipset: %s (NV%02X)\n",
277 			device->cname, device->chipset);
278 		nv_info(device, "Family : NV%02X\n", device->card_type);
279 
280 		/* determine frequency of timing crystal */
281 		if ( device->card_type <= NV_10 || device->chipset < 0x17 ||
282 		    (device->chipset >= 0x20 && device->chipset < 0x25))
283 			strap &= 0x00000040;
284 		else
285 			strap &= 0x00400040;
286 
287 		switch (strap) {
288 		case 0x00000000: device->crystal = 13500; break;
289 		case 0x00000040: device->crystal = 14318; break;
290 		case 0x00400000: device->crystal = 27000; break;
291 		case 0x00400040: device->crystal = 25000; break;
292 		}
293 
294 		nv_debug(device, "crystal freq: %dKHz\n", device->crystal);
295 	}
296 
297 #ifdef __NetBSD__
298 	if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
299 	    !nv_subdev(device)->mmiosz) {
300 		/* XXX errno NetBSD->Linux */
301 		ret = -bus_space_map(mmiot, mmio_base, mmio_size, 0, &mmioh);
302 		if (ret) {
303 			nv_error(device, "unable to map device registers\n");
304 			return ret;
305 		}
306 		nv_subdev(device)->mmiot = mmiot;
307 		nv_subdev(device)->mmioh = mmioh;
308 		nv_subdev(device)->mmiosz = mmio_size;
309 	}
310 #else
311 	if (!(args->disable & NV_DEVICE_DISABLE_MMIO) &&
312 	    !nv_subdev(device)->mmio) {
313 		nv_subdev(device)->mmio  = ioremap(mmio_base, mmio_size);
314 		if (!nv_subdev(device)->mmio) {
315 			nv_error(device, "unable to map device registers\n");
316 			return -ENOMEM;
317 		}
318 	}
319 #endif
320 
321 	/* ensure requested subsystems are available for use */
322 	for (i = 1, c = 1; i < NVDEV_SUBDEV_NR; i++) {
323 		if (!(oclass = device->oclass[i]) || (disable & (1ULL << i)))
324 			continue;
325 
326 		if (device->subdev[i]) {
327 			nouveau_object_ref(device->subdev[i],
328 					  &devobj->subdev[i]);
329 			continue;
330 		}
331 
332 		ret = nouveau_object_ctor(nv_object(device), NULL,
333 					  oclass, NULL, i,
334 					  &devobj->subdev[i]);
335 		if (ret == -ENODEV)
336 			continue;
337 		if (ret)
338 			return ret;
339 
340 		device->subdev[i] = devobj->subdev[i];
341 
342 		/* note: can't init *any* subdevs until devinit has been run
343 		 * due to not knowing exactly what the vbios init tables will
344 		 * mess with.  devinit also can't be run until all of its
345 		 * dependencies have been created.
346 		 *
347 		 * this code delays init of any subdev until all of devinit's
348 		 * dependencies have been created, and then initialises each
349 		 * subdev in turn as they're created.
350 		 */
351 		while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) {
352 			struct nouveau_object *subdev = devobj->subdev[c++];
353 			if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) {
354 				ret = nouveau_object_inc(subdev);
355 				if (ret)
356 					return ret;
357 				atomic_dec(&nv_object(device)->usecount);
358 			} else
359 			if (subdev) {
360 				nouveau_subdev_reset(subdev);
361 			}
362 		}
363 	}
364 
365 	return 0;
366 }
367 
368 static void
nouveau_devobj_dtor(struct nouveau_object * object)369 nouveau_devobj_dtor(struct nouveau_object *object)
370 {
371 	struct nouveau_devobj *devobj = (void *)object;
372 	int i;
373 
374 	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--)
375 		nouveau_object_ref(NULL, &devobj->subdev[i]);
376 
377 	nouveau_parent_destroy(&devobj->base);
378 }
379 
380 static u8
nouveau_devobj_rd08(struct nouveau_object * object,u64 addr)381 nouveau_devobj_rd08(struct nouveau_object *object, u64 addr)
382 {
383 	return nv_rd08(object->engine, addr);
384 }
385 
386 static u16
nouveau_devobj_rd16(struct nouveau_object * object,u64 addr)387 nouveau_devobj_rd16(struct nouveau_object *object, u64 addr)
388 {
389 	return nv_rd16(object->engine, addr);
390 }
391 
392 static u32
nouveau_devobj_rd32(struct nouveau_object * object,u64 addr)393 nouveau_devobj_rd32(struct nouveau_object *object, u64 addr)
394 {
395 	return nv_rd32(object->engine, addr);
396 }
397 
398 static void
nouveau_devobj_wr08(struct nouveau_object * object,u64 addr,u8 data)399 nouveau_devobj_wr08(struct nouveau_object *object, u64 addr, u8 data)
400 {
401 	nv_wr08(object->engine, addr, data);
402 }
403 
404 static void
nouveau_devobj_wr16(struct nouveau_object * object,u64 addr,u16 data)405 nouveau_devobj_wr16(struct nouveau_object *object, u64 addr, u16 data)
406 {
407 	nv_wr16(object->engine, addr, data);
408 }
409 
410 static void
nouveau_devobj_wr32(struct nouveau_object * object,u64 addr,u32 data)411 nouveau_devobj_wr32(struct nouveau_object *object, u64 addr, u32 data)
412 {
413 	nv_wr32(object->engine, addr, data);
414 }
415 
416 static struct nouveau_ofuncs
417 nouveau_devobj_ofuncs = {
418 	.ctor = nouveau_devobj_ctor,
419 	.dtor = nouveau_devobj_dtor,
420 	.init = _nouveau_parent_init,
421 	.fini = _nouveau_parent_fini,
422 	.rd08 = nouveau_devobj_rd08,
423 	.rd16 = nouveau_devobj_rd16,
424 	.rd32 = nouveau_devobj_rd32,
425 	.wr08 = nouveau_devobj_wr08,
426 	.wr16 = nouveau_devobj_wr16,
427 	.wr32 = nouveau_devobj_wr32,
428 };
429 
430 /******************************************************************************
431  * nouveau_device: engine functions
432  *****************************************************************************/
433 static struct nouveau_oclass
434 nouveau_device_sclass[] = {
435 	{ 0x0080, &nouveau_devobj_ofuncs },
436 	{}
437 };
438 
439 static int
nouveau_device_fini(struct nouveau_object * object,bool suspend)440 nouveau_device_fini(struct nouveau_object *object, bool suspend)
441 {
442 	struct nouveau_device *device = (void *)object;
443 	struct nouveau_object *subdev;
444 	int ret, i;
445 
446 	for (i = NVDEV_SUBDEV_NR - 1; i >= 0; i--) {
447 		if ((subdev = device->subdev[i])) {
448 			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
449 				ret = nouveau_object_dec(subdev, suspend);
450 				if (ret && suspend)
451 					goto fail;
452 			}
453 		}
454 	}
455 
456 	ret = 0;
457 fail:
458 	for (; ret && i < NVDEV_SUBDEV_NR; i++) {
459 		if ((subdev = device->subdev[i])) {
460 			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
461 				ret = nouveau_object_inc(subdev);
462 				if (ret) {
463 					/* XXX */
464 				}
465 			}
466 		}
467 	}
468 
469 	return ret;
470 }
471 
472 static int
nouveau_device_init(struct nouveau_object * object)473 nouveau_device_init(struct nouveau_object *object)
474 {
475 	struct nouveau_device *device = (void *)object;
476 	struct nouveau_object *subdev;
477 	int ret, i;
478 
479 	for (i = 0; i < NVDEV_SUBDEV_NR; i++) {
480 		if ((subdev = device->subdev[i])) {
481 			if (!nv_iclass(subdev, NV_ENGINE_CLASS)) {
482 				ret = nouveau_object_inc(subdev);
483 				if (ret)
484 					goto fail;
485 			} else {
486 				nouveau_subdev_reset(subdev);
487 			}
488 		}
489 	}
490 
491 	ret = 0;
492 fail:
493 	for (--i; ret && i >= 0; i--) {
494 		if ((subdev = device->subdev[i])) {
495 			if (!nv_iclass(subdev, NV_ENGINE_CLASS))
496 				nouveau_object_dec(subdev, false);
497 		}
498 	}
499 
500 	return ret;
501 }
502 
503 static void
nouveau_device_dtor(struct nouveau_object * object)504 nouveau_device_dtor(struct nouveau_object *object)
505 {
506 	struct nouveau_device *device = (void *)object;
507 
508 	mutex_lock(&nv_devices_mutex);
509 	list_del(&device->head);
510 	mutex_unlock(&nv_devices_mutex);
511 
512 #ifdef __NetBSD__
513 	if (nv_subdev(device)->mmiosz)
514 		bus_space_unmap(nv_subdev(device)->mmiot,
515 		    nv_subdev(device)->mmioh, nv_subdev(device)->mmiosz);
516 #else
517 	if (nv_subdev(device)->mmio)
518 		iounmap(nv_subdev(device)->mmio);
519 #endif
520 
521 	nouveau_engine_destroy(&device->base);
522 }
523 
524 #ifdef __NetBSD__
525 bus_space_tag_t
nv_device_resource_tag(struct nouveau_device * device,unsigned int bar)526 nv_device_resource_tag(struct nouveau_device *device, unsigned int bar)
527 {
528 	if (nv_device_is_pci(device)) {
529 		const struct pci_attach_args *const pa = &device->pdev->pd_pa;
530 		if (PCI_MAPREG_TYPE(pci_mapreg_type(pa->pa_pc, pa->pa_tag,
531 			    PCI_BAR(bar))) == PCI_MAPREG_TYPE_MEM)
532 			return pa->pa_memt;
533 		else
534 			return pa->pa_iot;
535 	} else {
536 		KASSERT(bar < device->platformdev->nresource);
537 		return device->platformdev->resource[bar].tag;
538 	}
539 }
540 #endif
541 
542 resource_size_t
nv_device_resource_start(struct nouveau_device * device,unsigned int bar)543 nv_device_resource_start(struct nouveau_device *device, unsigned int bar)
544 {
545 	if (nv_device_is_pci(device)) {
546 		return pci_resource_start(device->pdev, bar);
547 	} else {
548 #ifdef __NetBSD__
549 		if (bar >= device->platformdev->nresource)
550 			return 0;
551 		return device->platformdev->resource[bar].start;
552 #else
553 		struct resource *res;
554 		res = platform_get_resource(device->platformdev,
555 					    IORESOURCE_MEM, bar);
556 		if (!res)
557 			return 0;
558 		return res->start;
559 #endif
560 	}
561 }
562 
563 resource_size_t
nv_device_resource_len(struct nouveau_device * device,unsigned int bar)564 nv_device_resource_len(struct nouveau_device *device, unsigned int bar)
565 {
566 	if (nv_device_is_pci(device)) {
567 		return pci_resource_len(device->pdev, bar);
568 	} else {
569 #ifdef __NetBSD__
570 		if (bar >= device->platformdev->nresource)
571 			return 0;
572 		return device->platformdev->resource[bar].len;
573 #else
574 		struct resource *res;
575 		res = platform_get_resource(device->platformdev,
576 					    IORESOURCE_MEM, bar);
577 		if (!res)
578 			return 0;
579 		return resource_size(res);
580 #endif
581 	}
582 }
583 
584 #ifndef __NetBSD__
585 dma_addr_t
nv_device_map_page(struct nouveau_device * device,struct page * page)586 nv_device_map_page(struct nouveau_device *device, struct page *page)
587 {
588 	dma_addr_t ret;
589 
590 	if (nv_device_is_pci(device)) {
591 		ret = pci_map_page(device->pdev, page, 0, PAGE_SIZE,
592 				   PCI_DMA_BIDIRECTIONAL);
593 		if (pci_dma_mapping_error(device->pdev, ret))
594 			ret = 0;
595 	} else {
596 		ret = page_to_phys(page);
597 	}
598 
599 	return ret;
600 }
601 
602 void
nv_device_unmap_page(struct nouveau_device * device,dma_addr_t addr)603 nv_device_unmap_page(struct nouveau_device *device, dma_addr_t addr)
604 {
605 	if (nv_device_is_pci(device))
606 		pci_unmap_page(device->pdev, addr, PAGE_SIZE,
607 			       PCI_DMA_BIDIRECTIONAL);
608 }
609 
610 int
nv_device_get_irq(struct nouveau_device * device,bool stall)611 nv_device_get_irq(struct nouveau_device *device, bool stall)
612 {
613 	if (nv_device_is_pci(device)) {
614 		return device->pdev->irq;
615 	} else {
616 		return platform_get_irq_byname(device->platformdev,
617 					       stall ? "stall" : "nonstall");
618 	}
619 }
620 #endif
621 
622 static struct nouveau_oclass
623 nouveau_device_oclass = {
624 	.handle = NV_ENGINE(DEVICE, 0x00),
625 	.ofuncs = &(struct nouveau_ofuncs) {
626 		.dtor = nouveau_device_dtor,
627 		.init = nouveau_device_init,
628 		.fini = nouveau_device_fini,
629 	},
630 };
631 
632 int
nouveau_device_create_(void * dev,enum nv_bus_type type,u64 name,const char * sname,const char * cfg,const char * dbg,int length,void ** pobject)633 nouveau_device_create_(void *dev, enum nv_bus_type type, u64 name,
634 		       const char *sname, const char *cfg, const char *dbg,
635 		       int length, void **pobject)
636 {
637 	struct nouveau_device *device;
638 	int ret = -EEXIST;
639 
640 	mutex_lock(&nv_devices_mutex);
641 	list_for_each_entry(device, &nv_devices, head) {
642 		if (device->handle == name)
643 			goto done;
644 	}
645 
646 	ret = nouveau_engine_create_(NULL, NULL, &nouveau_device_oclass, true,
647 				     "DEVICE", "device", length, pobject);
648 	device = *pobject;
649 	if (ret)
650 		goto done;
651 
652 	switch (type) {
653 	case NOUVEAU_BUS_PCI:
654 		device->pdev = dev;
655 		break;
656 	case NOUVEAU_BUS_PLATFORM:
657 		device->platformdev = dev;
658 		break;
659 	}
660 	device->handle = name;
661 	device->cfgopt = cfg;
662 	device->dbgopt = dbg;
663 	device->name = sname;
664 
665 	nv_subdev(device)->debug = nouveau_dbgopt(device->dbgopt, "DEVICE");
666 	nv_engine(device)->sclass = nouveau_device_sclass;
667 	list_add(&device->head, &nv_devices);
668 done:
669 	mutex_unlock(&nv_devices_mutex);
670 	return ret;
671 }
672