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