blob: 3a88896b5ed8cbe134b14024e42d27271d44e242 [file] [log] [blame]
Xiaojie Yuan7e6bf882017-05-31 16:22:50 -04001/*
2 * Copyright © 2017 Advanced Micro Devices, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <ctype.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdint.h>
33#include <string.h>
34#include <unistd.h>
35#include <errno.h>
36
37#include "xf86drm.h"
38#include "amdgpu_drm.h"
39#include "amdgpu_internal.h"
40
41static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
42{
43 char *buf, *saveptr;
44 char *s_did;
45 char *s_rid;
46 char *s_name;
47 char *endptr;
48 int r = 0;
49
50 buf = strdup(line);
51 if (!buf)
52 return -ENOMEM;
53
54 /* ignore empty line and commented line */
55 if (strlen(line) == 0 || line[0] == '#') {
56 r = -EAGAIN;
57 goto out;
58 }
59
60 /* device id */
61 s_did = strtok_r(buf, ",", &saveptr);
62 if (!s_did) {
63 r = -EINVAL;
64 goto out;
65 }
66
67 id->did = strtol(s_did, &endptr, 16);
68 if (*endptr) {
69 r = -EINVAL;
70 goto out;
71 }
72
73 /* revision id */
74 s_rid = strtok_r(NULL, ",", &saveptr);
75 if (!s_rid) {
76 r = -EINVAL;
77 goto out;
78 }
79
80 id->rid = strtol(s_rid, &endptr, 16);
81 if (*endptr) {
82 r = -EINVAL;
83 goto out;
84 }
85
86 /* marketing name */
87 s_name = strtok_r(NULL, ",", &saveptr);
88 if (!s_name) {
89 r = -EINVAL;
90 goto out;
91 }
92 /* trim leading whitespaces or tabs */
93 while (isblank(*s_name))
94 s_name++;
95 if (strlen(s_name) == 0) {
96 r = -EINVAL;
97 goto out;
98 }
99
100 id->marketing_name = strdup(s_name);
101 if (id->marketing_name == NULL) {
102 r = -EINVAL;
103 goto out;
104 }
105
106out:
107 free(buf);
108
109 return r;
110}
111
112int amdgpu_parse_asic_ids(struct amdgpu_asic_id **p_asic_id_table)
113{
114 struct amdgpu_asic_id *asic_id_table;
115 struct amdgpu_asic_id *id;
116 FILE *fp;
117 char *line = NULL;
118 size_t len = 0;
119 ssize_t n;
120 int line_num = 1;
121 size_t table_size = 0;
122 size_t table_max_size = AMDGPU_ASIC_ID_TABLE_NUM_ENTRIES;
123 int r = 0;
124
125 fp = fopen(AMDGPU_ASIC_ID_TABLE, "r");
126 if (!fp) {
127 fprintf(stderr, "%s: %s\n", AMDGPU_ASIC_ID_TABLE,
128 strerror(errno));
129 return -EINVAL;
130 }
131
132 asic_id_table = calloc(table_max_size + 1,
133 sizeof(struct amdgpu_asic_id));
134 if (!asic_id_table) {
135 r = -ENOMEM;
136 goto close;
137 }
138
139 /* 1st valid line is file version */
140 while ((n = getline(&line, &len, fp)) != -1) {
141 /* trim trailing newline */
142 if (line[n - 1] == '\n')
143 line[n - 1] = '\0';
144
145 /* ignore empty line and commented line */
146 if (strlen(line) == 0 || line[0] == '#') {
147 line_num++;
148 continue;
149 }
150
151 drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line);
152 break;
153 }
154
155 while ((n = getline(&line, &len, fp)) != -1) {
156 if (table_size > table_max_size) {
157 /* double table size */
158 table_max_size *= 2;
159 id = realloc(asic_id_table, (table_max_size + 1) *
160 sizeof(struct amdgpu_asic_id));
161 if (!id) {
162 r = -ENOMEM;
163 goto free;
164 }
165 asic_id_table = id;
166 }
167
168 id = asic_id_table + table_size;
169
170 /* trim trailing newline */
171 if (line[n - 1] == '\n')
172 line[n - 1] = '\0';
173
174 r = parse_one_line(line, id);
175 if (r) {
176 if (r == -EAGAIN) {
177 line_num++;
178 continue;
179 }
180 fprintf(stderr, "Invalid format: %s: line %d: %s\n",
181 AMDGPU_ASIC_ID_TABLE, line_num, line);
182 goto free;
183 }
184
185 line_num++;
186 table_size++;
187 }
188
189 /* end of table */
190 id = asic_id_table + table_size;
191 memset(id, 0, sizeof(struct amdgpu_asic_id));
192
193 if (table_size != table_max_size) {
194 id = realloc(asic_id_table, (table_size + 1) *
195 sizeof(struct amdgpu_asic_id));
196 if (!id)
197 r = -ENOMEM;
198 else
199 asic_id_table = id;
200 }
201
202free:
203 free(line);
204
205 if (r && asic_id_table) {
206 while (table_size--) {
207 id = asic_id_table + table_size;
208 free(id->marketing_name);
209 }
210 free(asic_id_table);
211 asic_id_table = NULL;
212 }
213close:
214 fclose(fp);
215
216 *p_asic_id_table = asic_id_table;
217
218 return r;
219}