blob: b9860c27c1e1895ce3cef08eedb7632b182ee772 [file] [log] [blame]
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -06001/*
2 * XGL 3-D graphics library
3 *
4 * Copyright (C) 2014 LunarG, 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
14 * in 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
Chia-I Wu44e42362014-09-02 08:32:09 +080025 * Courtney Goeltzenleuchter <courtney@lunarg.com>
26 * Chia-I Wu <olv@lunarg.com>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060027 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
Chia-I Wua6e33492014-08-05 13:35:08 +080033#include <stdio.h>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060034#include <sys/types.h>
35#include <sys/stat.h>
36#include <assert.h>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060037#include <fcntl.h>
Chia-I Wua6e33492014-08-05 13:35:08 +080038#include <unistd.h>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060039#include <fnmatch.h>
40
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060041#include <libudev.h>
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060042
Chia-I Wua6e33492014-08-05 13:35:08 +080043#include "gpu.h"
44#include "intel.h"
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060045
Chia-I Wu73019ad2014-08-29 12:01:13 +080046static int intel_devid_override;
Chia-I Wu1c527012014-08-23 14:57:35 +080047int intel_debug = -1;
48
49static void intel_debug_init(void)
50{
51 const char *env;
52
53 if (intel_debug >= 0)
54 return;
55
56 intel_debug = 0;
57
58 /* parse comma-separated debug options */
59 env = getenv("INTEL_DEBUG");
60 while (env) {
61 const char *p = strchr(env, ',');
62 size_t len;
63
64 if (p)
65 len = p - env;
66 else
67 len = strlen(env);
68
Chia-I Wu73019ad2014-08-29 12:01:13 +080069 if (strncmp(env, "batch", len) == 0) {
Chia-I Wu1c527012014-08-23 14:57:35 +080070 intel_debug |= INTEL_DEBUG_BATCH;
Chia-I Wu73019ad2014-08-29 12:01:13 +080071 } else if (strncmp(env, "nohw", len) == 0) {
Chia-I Wu93ada312014-08-23 15:02:25 +080072 intel_debug |= INTEL_DEBUG_NOHW;
Chia-I Wu73019ad2014-08-29 12:01:13 +080073 } else if (strncmp(env, "0x", 2) == 0) {
74 intel_debug |= INTEL_DEBUG_NOHW;
75 intel_devid_override = strtol(env, NULL, 16);
76 }
Chia-I Wu1c527012014-08-23 14:57:35 +080077
78 if (!p)
79 break;
80
81 env = p + 1;
82 }
83}
84
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060085static int is_render_node(int fd, struct stat *st)
86{
87 if (fstat(fd, st))
88 return 0;
89
90 if (!S_ISCHR(st->st_mode))
91 return 0;
92
93 return st->st_rdev & 0x80;
94}
95
Chia-I Wu468e3c32014-08-04 08:03:57 +080096ICD_EXPORT XGL_RESULT XGLAPI xglInitAndEnumerateGpus(const XGL_APPLICATION_INFO *
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -060097 pAppInfo,
98 const XGL_ALLOC_CALLBACKS *
99 pAllocCb, XGL_UINT maxGpus,
100 XGL_UINT * pGpuCount,
101 XGL_PHYSICAL_GPU * pGpus)
102{
103 struct udev *udev;
104 struct udev_enumerate *e;
105 struct udev_device *device, *parent;
106 struct udev_list_entry *entry;
107 const char *pci_id, *path;
108 const char *usub, *dnode;
109 int fd;
110 struct stat st;
111 char *pci_glob = "*:*";
Chia-I Wu3065c9c2014-08-04 06:28:31 +0800112 XGL_RESULT ret;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600113 XGL_UINT count = 0;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600114
Chia-I Wu1c527012014-08-23 14:57:35 +0800115 intel_debug_init();
116
Chia-I Wuc217f802014-08-05 10:17:50 +0800117 ret = icd_set_allocator(pAllocCb);
Chia-I Wu3065c9c2014-08-04 06:28:31 +0800118 if (ret != XGL_SUCCESS)
119 return ret;
120
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600121 /*
122 * xglInitAndEnumerateGpus() can be called multiple times. Calling it more than once
123 * forces driver reinitialization.
124 */
Chia-I Wua6e33492014-08-05 13:35:08 +0800125 intel_gpu_remove_all();
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600126
Chia-I Wuc7bff532014-08-06 12:14:54 +0800127 if (!maxGpus) {
128 *pGpuCount = 0;
Chia-I Wua6e33492014-08-05 13:35:08 +0800129 return XGL_SUCCESS;
Chia-I Wuc7bff532014-08-06 12:14:54 +0800130 }
Chia-I Wua6e33492014-08-05 13:35:08 +0800131
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600132 // TODO: Do we need any other validation for incoming pointers?
133
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600134 udev = udev_new();
135 if (udev == NULL) {
Chia-I Wua6e33492014-08-05 13:35:08 +0800136 icd_log(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0,
137 XGL_NULL_HANDLE, 0, 0, "failed to initialize udev context");
138 return XGL_ERROR_OUT_OF_MEMORY;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600139 }
140
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600141 fd = -1;
142 e = udev_enumerate_new(udev);
143 udev_enumerate_add_match_subsystem(e, "drm");
144 udev_enumerate_scan_devices(e);
145 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
Chia-I Wua6e33492014-08-05 13:35:08 +0800146 unsigned int ven_id, dev_id;
147 struct intel_gpu *gpu;
148
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600149 path = udev_list_entry_get_name(entry);
150 device = udev_device_new_from_syspath(udev, path);
151 parent = udev_device_get_parent(device);
152 usub = udev_device_get_subsystem(parent);
153 /* Filter out KMS output devices. */
Chia-I Wu78462db2014-08-06 12:23:55 +0800154 if (!usub || (strcmp(usub, "pci") != 0)) {
155 udev_device_unref(device);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600156 continue;
Chia-I Wu78462db2014-08-06 12:23:55 +0800157 }
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600158 pci_id = udev_device_get_property_value(parent, "PCI_ID");
Chia-I Wu78462db2014-08-06 12:23:55 +0800159 if (fnmatch(pci_glob, pci_id, 0) != 0) {
160 udev_device_unref(device);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600161 continue;
Chia-I Wu78462db2014-08-06 12:23:55 +0800162 }
Chia-I Wua6e33492014-08-05 13:35:08 +0800163 sscanf(pci_id, "%x:%x", &ven_id, &dev_id);
Chia-I Wu78462db2014-08-06 12:23:55 +0800164 if (ven_id != 0x8086) {
165 udev_device_unref(device);
Chia-I Wua6e33492014-08-05 13:35:08 +0800166 continue;
Chia-I Wu78462db2014-08-06 12:23:55 +0800167 }
Chia-I Wua6e33492014-08-05 13:35:08 +0800168
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600169 dnode = udev_device_get_devnode(device);
Chia-I Wua6e33492014-08-05 13:35:08 +0800170 /* TODO do not open the device at this point */
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600171 fd = open(dnode, O_RDWR);
Chia-I Wu78462db2014-08-06 12:23:55 +0800172 if (fd < 0) {
173 udev_device_unref(device);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600174 continue;
Chia-I Wu78462db2014-08-06 12:23:55 +0800175 }
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600176 if (!is_render_node(fd, &st)) {
177 close(fd);
178 fd = -1;
Chia-I Wu78462db2014-08-06 12:23:55 +0800179 udev_device_unref(device);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600180 continue;
181 }
Chia-I Wua6e33492014-08-05 13:35:08 +0800182 close(fd);
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600183
Chia-I Wu73019ad2014-08-29 12:01:13 +0800184 if (intel_devid_override)
185 dev_id = intel_devid_override;
Chia-I Wua6e33492014-08-05 13:35:08 +0800186 ret = intel_gpu_add(dev_id, dnode, &gpu);
Chia-I Wu78462db2014-08-06 12:23:55 +0800187
188 udev_device_unref(device);
189
Chia-I Wua6e33492014-08-05 13:35:08 +0800190 if (ret == XGL_SUCCESS) {
191 pGpus[count++] = (XGL_PHYSICAL_GPU) gpu;
192 if (count >= maxGpus)
193 break;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600194 }
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600195 }
Chia-I Wua6e33492014-08-05 13:35:08 +0800196
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600197 udev_enumerate_unref(e);
198 udev_unref(udev);
199
Chia-I Wua6e33492014-08-05 13:35:08 +0800200 *pGpuCount = count;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600201
Chia-I Wua6e33492014-08-05 13:35:08 +0800202 return (count > 0) ? XGL_SUCCESS : XGL_ERROR_UNAVAILABLE;
Courtney Goeltzenleuchtere06e72d2014-08-01 12:44:23 -0600203}