Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-07 Thread Michel Dänzer
On 07/06/17 08:12 PM, Emil Velikov wrote:
> On 7 June 2017 at 09:40, Michel Dänzer  wrote:
>> On 06/06/17 10:43 PM, Emil Velikov wrote:
>>> On 31 May 2017 at 21:22, Samuel Li  wrote:
>>>
 --- /dev/null
 +++ b/amdgpu/amdgpu_asic_id.c
>>>
 +static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
 +{
 +   char *buf, *saveptr;
 +   char *s_did;
 +   char *s_rid;
 +   char *s_name;
 +   char *endptr;
 +   int r = 0;
 +
 +   buf = strdup(line);
>>> You don't need the extra strdup here if you use strchr over strtok.
>>
>> Beware that without strdup here, amdgpu_parse_asic_ids must set line =
>> NULL after table_line++, so that getline allocates a new buffer for the
>> next line.
>>
> A simple "line = NULL" will lead to a memory leak, AFAICT.
>
> In either case, I'm a bit baffled how that is affected by the
> presence/lack of strdup?
> We don't alter or reuse the backing storage only
> strcmp/isblank/strtol/strdup it.

Oh, I missed that id->marketing_name is strdup'd again.

Anyway, it's probably better not to change the logic too much at this
point, other than anything needed to fix immediate bugs. It can always
be improved with follow-up patches.


-- 
Earthling Michel Dänzer   |   http://www.amd.com
Libre software enthusiast | Mesa and X developer
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-07 Thread Emil Velikov
On 7 June 2017 at 09:40, Michel Dänzer  wrote:
> On 06/06/17 10:43 PM, Emil Velikov wrote:
>> On 31 May 2017 at 21:22, Samuel Li  wrote:
>>
>>> --- /dev/null
>>> +++ b/amdgpu/amdgpu_asic_id.c
>>
>>> +static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
>>> +{
>>> +   char *buf, *saveptr;
>>> +   char *s_did;
>>> +   char *s_rid;
>>> +   char *s_name;
>>> +   char *endptr;
>>> +   int r = 0;
>>> +
>>> +   buf = strdup(line);
>> You don't need the extra strdup here if you use strchr over strtok.
>
> Beware that without strdup here, amdgpu_parse_asic_ids must set line =
> NULL after table_line++, so that getline allocates a new buffer for the
> next line.
>
A simple "line = NULL" will lead to a memory leak, AFAICT.

In either case, I'm a bit baffled how that is affected by the
presence/lack of strdup?
We don't alter or reuse the backing storage only
strcmp/isblank/strtol/strdup it.

>
>>> +int amdgpu_parse_asic_ids(struct amdgpu_asic_id **p_asic_id_table)
>>> +{
>>
>>> +   /* 1st valid line is file version */
>>> +   while ((n = getline(&line, &len, fp)) != -1) {
>>> +   /* trim trailing newline */
>>> +   if (line[n - 1] == '\n')
>>> +   line[n - 1] = '\0';
>> Why do we need this - afaict none of the parsing code cares if we have
>> \n or not?
>
> The \n has to be removed somehow, otherwise it ends up as part of the
> marketing name returned to the application.
>
Wouldn't be better to do that in parse_one_line() around the
marketing_name = strdup(...) call?
It's a matter of taste, so feel free to ignore me.

>
>>> +   /* end of table */
>>> +   id = asic_id_table + table_size;
>>> +   memset(id, 0, sizeof(struct amdgpu_asic_id));
>> Here one clears the sentinel, which is needed as we hit realloc above, 
>> correct?
>>
>>> +   asic_id_table = realloc(asic_id_table, (table_size+1) *
>>> +   sizeof(struct amdgpu_asic_id));
>> But why do we realloc again?
>
> I asked for that, in order not to waste memory for unused table entries.
>
D'oh, indeed. Thank you. Worth adding a note?

>
>>> +free:
>>> +   free(line);
>>> +
>>> +   if (r && asic_id_table) {
>>> +   while (table_size--) {
>>> +   id = asic_id_table + table_size;
>>> +   free(id->marketing_name);
>>> +   }
>>> +   free(asic_id_table);
>>> +   asic_id_table = NULL;
>>> +   }
>>> +close:
>>> +   fclose(fp);
>>> +
>>> +   *p_asic_id_table = asic_id_table;
>>> +
>> Please don't entwine the error path with the normal one.
>>
>> Setting *p_asic_id_table (or any user provided pointer) when the
>> function fails is bad design.
>
> I don't really see the issue with that; it's fine for the only caller of
> this function.
>
it's not obvious and might come to bite. Since *p_asic_id_table is
already NULL (we're using calloc) I'd opt for dropping it.
Not trying to force my opinion, just stating concerns.

Another crazy idea that just came to mind:
Since getline() can do multiple implicit realloc's one can allocate "a
sane" default and feed that instead of the current NULL.

Regards,
Emil
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-07 Thread Michel Dänzer
On 06/06/17 10:43 PM, Emil Velikov wrote:
> On 31 May 2017 at 21:22, Samuel Li  wrote:
> 
>> --- /dev/null
>> +++ b/amdgpu/amdgpu_asic_id.c
> 
>> +static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
>> +{
>> +   char *buf, *saveptr;
>> +   char *s_did;
>> +   char *s_rid;
>> +   char *s_name;
>> +   char *endptr;
>> +   int r = 0;
>> +
>> +   buf = strdup(line);
> You don't need the extra strdup here if you use strchr over strtok.

Beware that without strdup here, amdgpu_parse_asic_ids must set line =
NULL after table_line++, so that getline allocates a new buffer for the
next line.


>> +int amdgpu_parse_asic_ids(struct amdgpu_asic_id **p_asic_id_table)
>> +{
> 
>> +   /* 1st valid line is file version */
>> +   while ((n = getline(&line, &len, fp)) != -1) {
>> +   /* trim trailing newline */
>> +   if (line[n - 1] == '\n')
>> +   line[n - 1] = '\0';
> Why do we need this - afaict none of the parsing code cares if we have
> \n or not?

The \n has to be removed somehow, otherwise it ends up as part of the
marketing name returned to the application.


>> +   /* end of table */
>> +   id = asic_id_table + table_size;
>> +   memset(id, 0, sizeof(struct amdgpu_asic_id));
> Here one clears the sentinel, which is needed as we hit realloc above, 
> correct?
> 
>> +   asic_id_table = realloc(asic_id_table, (table_size+1) *
>> +   sizeof(struct amdgpu_asic_id));
> But why do we realloc again?

I asked for that, in order not to waste memory for unused table entries.


>> +free:
>> +   free(line);
>> +
>> +   if (r && asic_id_table) {
>> +   while (table_size--) {
>> +   id = asic_id_table + table_size;
>> +   free(id->marketing_name);
>> +   }
>> +   free(asic_id_table);
>> +   asic_id_table = NULL;
>> +   }
>> +close:
>> +   fclose(fp);
>> +
>> +   *p_asic_id_table = asic_id_table;
>> +
> Please don't entwine the error path with the normal one.
> 
> Setting *p_asic_id_table (or any user provided pointer) when the
> function fails is bad design.

I don't really see the issue with that; it's fine for the only caller of
this function.


-- 
Earthling Michel Dänzer   |   http://www.amd.com
Libre software enthusiast | Mesa and X developer
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-06 Thread Emil Velikov
Hi Samuel,

With all the other discussion aside here is some code specific input
which I'd hope you agree with.

On 31 May 2017 at 21:22, Samuel Li  wrote:

> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -45,6 +45,9 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
>
>  pkgconfigdir = @pkgconfigdir@
>  pkgconfig_DATA = libdrm.pc
> +libdrmdatadir = $(datadir)/libdrm
> +dist_libdrmdata_DATA = include/drm/amdgpu.ids
> +export libdrmdatadir
Don't place exports in the makefiles. See how pkgconfigdir is managed
in configure.ac and do do with libdrmdatadir.


> --- /dev/null
> +++ b/amdgpu/amdgpu_asic_id.c

> +static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
> +{
> +   char *buf, *saveptr;
> +   char *s_did;
> +   char *s_rid;
> +   char *s_name;
> +   char *endptr;
> +   int r = 0;
> +
> +   buf = strdup(line);
You don't need the extra strdup here if you use strchr over strtok.

> +   if (!buf)
> +   return -ENOMEM;
> +
> +   /* ignore empty line and commented line */
> +   if (strlen(line) == 0 || line[0] == '#') {
You might want to check/trim whitespace before #? Same question applies below.

> +   r = -EAGAIN;
> +   goto out;
With the strdup, hence free() gone, all the errors will be "return -EFOO;"


> +   /* trim leading whitespaces or tabs */
> +   while (*s_name == ' ' || *s_name == '\t')
> +   s_name++;
Use isblank/isspace - they should handle \r et al, which will creep as
someone on the team uses Windows ;-)



> +int amdgpu_parse_asic_ids(struct amdgpu_asic_id **p_asic_id_table)
> +{

> +   /* 1st valid line is file version */
> +   while ((n = getline(&line, &len, fp)) != -1) {
> +   /* trim trailing newline */
> +   if (line[n - 1] == '\n')
> +   line[n - 1] = '\0';
Why do we need this - afaict none of the parsing code cares if we have
\n or not?
Same question applies for the second loop, below.

> +
> +   /* ignore empty line and commented line */
> +   if (strlen(line) == 0 || line[0] == '#') {
> +   line_num++;
> +   continue;
> +   }
> +
> +   drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line);
> +   break;
> +   }
> +
Should the lack of a version line/tag be considered fatal or not? An
inline comment is welcome.

> +   while ((n = getline(&line, &len, fp)) != -1) {

> +
> +   if (table_size >= table_max_size) {
Move it at the top of the loop, since as-is it will end up reallocate
even when it doesn't need to.

> +   /* double table size */
> +   table_max_size *= 2;
> +   asic_id_table = realloc(asic_id_table, table_max_size 
> *
> +   sizeof(struct 
> amdgpu_asic_id));
> +   if (!asic_id_table) {
Memory originally pointed by asic_id_table is leaked.

> +   r = -ENOMEM;
> +   goto free;
> +   }
> +   }
> +   }
> +
> +   /* end of table */
> +   id = asic_id_table + table_size;
> +   memset(id, 0, sizeof(struct amdgpu_asic_id));
Here one clears the sentinel, which is needed as we hit realloc above, correct?

> +   asic_id_table = realloc(asic_id_table, (table_size+1) *
> +   sizeof(struct amdgpu_asic_id));
But why do we realloc again?

> +   if (!asic_id_table)
As above - we have a leak original asic_id_table.

> +   r = -ENOMEM;
> +
> +free:
> +   free(line);
> +
> +   if (r && asic_id_table) {
> +   while (table_size--) {
> +   id = asic_id_table + table_size;
> +   free(id->marketing_name);
> +   }
> +   free(asic_id_table);
> +   asic_id_table = NULL;
> +   }
> +close:
> +   fclose(fp);
> +
> +   *p_asic_id_table = asic_id_table;
> +
Please don't entwine the error path with the normal one.

Setting *p_asic_id_table (or any user provided pointer) when the
function fails is bad design.

Regards,
Emil
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


RE: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-05 Thread Li, Samuel
> what is the purpose of the file version
The initial purpose is to act like a version tag, not necessarily format 
related. 

Sam

-Original Message-
From: Michel Dänzer [mailto:mic...@daenzer.net] 
Sent: Sunday, June 04, 2017 10:10 PM
To: Li, Samuel 
Cc: amd-gfx@lists.freedesktop.org; Yuan, Xiaojie 
Subject: Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

On 01/06/17 05:22 AM, Samuel Li wrote:
> From: Xiaojie Yuan 
> 
> v2: fix an off by one error and leading white spaces
> v3: use thread safe strtok_r(); initialize len before calling getline();
> change printf() to drmMsg(); add initial amdgpu.ids
> v4: integrate some recent internal changes, including format changes
> v5: fix line number for empty/commented lines; realloc to save memory; 
> indentation changes
> v6: remove a line error
> 
> Change-Id: I12216da14910f5e2b0970bc1fafc2a20b0ef1ba9
> Reviewed-by: Junwei Zhang 
> Signed-off-by: Samuel Li 

[...]

> + /* 1st valid line is file version */
> + while ((n = getline(&line, &len, fp)) != -1) {
> + /* trim trailing newline */
> + if (line[n - 1] == '\n')
> + line[n - 1] = '\0';
> +
> + /* ignore empty line and commented line */
> + if (strlen(line) == 0 || line[0] == '#') {
> + line_num++;
> + continue;
> + }
> +
> + drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line);
> + break;
> + }

BTW, what is the purpose of the file version? If it's about the format of the 
file, we need to check here that the file has a format we can parse, something 
like

if ( != 1)
return -EINVAL;


Note that making backwards incompatible changes to the file format would pretty 
much kill the idea of updating the file with a script like update-pciids.


-- 
Earthling Michel Dänzer   |   http://www.amd.com
Libre software enthusiast | Mesa and X developer
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-06-04 Thread Michel Dänzer
On 01/06/17 05:22 AM, Samuel Li wrote:
> From: Xiaojie Yuan 
> 
> v2: fix an off by one error and leading white spaces
> v3: use thread safe strtok_r(); initialize len before calling getline();
> change printf() to drmMsg(); add initial amdgpu.ids
> v4: integrate some recent internal changes, including format changes
> v5: fix line number for empty/commented lines; realloc to save memory; 
> indentation changes
> v6: remove a line error
> 
> Change-Id: I12216da14910f5e2b0970bc1fafc2a20b0ef1ba9
> Reviewed-by: Junwei Zhang 
> Signed-off-by: Samuel Li 

[...]

> + /* 1st valid line is file version */
> + while ((n = getline(&line, &len, fp)) != -1) {
> + /* trim trailing newline */
> + if (line[n - 1] == '\n')
> + line[n - 1] = '\0';
> +
> + /* ignore empty line and commented line */
> + if (strlen(line) == 0 || line[0] == '#') {
> + line_num++;
> + continue;
> + }
> +
> + drmMsg("%s version: %s\n", AMDGPU_ASIC_ID_TABLE, line);
> + break;
> + }

BTW, what is the purpose of the file version? If it's about the format
of the file, we need to check here that the file has a format we can
parse, something like

if ( != 1)
return -EINVAL;


Note that making backwards incompatible changes to the file format would
pretty much kill the idea of updating the file with a script like
update-pciids.


-- 
Earthling Michel Dänzer   |   http://www.amd.com
Libre software enthusiast | Mesa and X developer
___
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx


Re: [PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-05-31 Thread Alex Deucher
On Wed, May 31, 2017 at 4:22 PM, Samuel Li  wrote:
> From: Xiaojie Yuan 
>
> v2: fix an off by one error and leading white spaces
> v3: use thread safe strtok_r(); initialize len before calling getline();
> change printf() to drmMsg(); add initial amdgpu.ids
> v4: integrate some recent internal changes, including format changes
> v5: fix line number for empty/commented lines; realloc to save memory; 
> indentation changes
> v6: remove a line error
>
> Change-Id: I12216da14910f5e2b0970bc1fafc2a20b0ef1ba9
> Reviewed-by: Junwei Zhang 
> Signed-off-by: Samuel Li 

Reviewed-by: Alex Deucher 

> ---
>  Makefile.am  |   3 +
>  amdgpu/Makefile.am   |   2 +
>  amdgpu/Makefile.sources  |   2 +-
>  amdgpu/amdgpu_asic_id.c  | 211 
> +++
>  amdgpu/amdgpu_asic_id.h  | 165 
>  amdgpu/amdgpu_device.c   |  28 +--
>  amdgpu/amdgpu_internal.h |  10 +++
>  include/drm/amdgpu.ids   | 170 ++
>  8 files changed, 418 insertions(+), 173 deletions(-)
>  create mode 100644 amdgpu/amdgpu_asic_id.c
>  delete mode 100644 amdgpu/amdgpu_asic_id.h
>  create mode 100644 include/drm/amdgpu.ids
>
> diff --git a/Makefile.am b/Makefile.am
> index dfb8fcd..8de8f6c 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -45,6 +45,9 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
>
>  pkgconfigdir = @pkgconfigdir@
>  pkgconfig_DATA = libdrm.pc
> +libdrmdatadir = $(datadir)/libdrm
> +dist_libdrmdata_DATA = include/drm/amdgpu.ids
> +export libdrmdatadir
>
>  if HAVE_LIBKMS
>  LIBKMS_SUBDIR = libkms
> diff --git a/amdgpu/Makefile.am b/amdgpu/Makefile.am
> index cf7bc1b..da71c1c 100644
> --- a/amdgpu/Makefile.am
> +++ b/amdgpu/Makefile.am
> @@ -30,6 +30,8 @@ AM_CFLAGS = \
> $(PTHREADSTUBS_CFLAGS) \
> -I$(top_srcdir)/include/drm
>
> +AM_CPPFLAGS = -DAMDGPU_ASIC_ID_TABLE=\"${libdrmdatadir}/amdgpu.ids\"
> +
>  libdrm_amdgpu_la_LTLIBRARIES = libdrm_amdgpu.la
>  libdrm_amdgpu_ladir = $(libdir)
>  libdrm_amdgpu_la_LDFLAGS = -version-number 1:0:0 -no-undefined
> diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources
> index 487b9e0..bc3abaa 100644
> --- a/amdgpu/Makefile.sources
> +++ b/amdgpu/Makefile.sources
> @@ -1,5 +1,5 @@
>  LIBDRM_AMDGPU_FILES := \
> -   amdgpu_asic_id.h \
> +   amdgpu_asic_id.c \
> amdgpu_bo.c \
> amdgpu_cs.c \
> amdgpu_device.c \
> diff --git a/amdgpu/amdgpu_asic_id.c b/amdgpu/amdgpu_asic_id.c
> new file mode 100644
> index 000..be39f4e
> --- /dev/null
> +++ b/amdgpu/amdgpu_asic_id.c
> @@ -0,0 +1,211 @@
> +/*
> + * Copyright © 2017 Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "xf86drm.h"
> +#include "amdgpu_drm.h"
> +#include "amdgpu_internal.h"
> +
> +static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
> +{
> +   char *buf, *saveptr;
> +   char *s_did;
> +   char *s_rid;
> +   char *s_name;
> +   char *endptr;
> +   int r = 0;
> +
> +   buf = strdup(line);
> +   if (!buf)
> +   return -ENOMEM;
> +
> +   /* ignore empty line and commented line */
> +   if (strlen(line) == 0 || line[0] == '#') {
> +   r = -EAGAIN;
> +   goto out;
> +   }
> +
> +   /* device id */
> +   s_did = strtok_r(buf, ",", &saveptr);
> +   if (!s_did) {
> +   r = -EINVAL;
> +   goto out;
> +   }
> +
> +   id->did = strtol(s_did, &endptr, 16);
> +   if (*endptr) {
> +   r = -EINVAL;
> +   goto out;
> +   }
> +
> +   /* revision id */
> +   s_rid = strtok_r(NULL, ",", &saveptr);
> +   if (!s_rid) {
> + 

[PATCH libdrm v6 1/1] amdgpu: move asic id table to a separate file

2017-05-31 Thread Samuel Li
From: Xiaojie Yuan 

v2: fix an off by one error and leading white spaces
v3: use thread safe strtok_r(); initialize len before calling getline();
change printf() to drmMsg(); add initial amdgpu.ids
v4: integrate some recent internal changes, including format changes
v5: fix line number for empty/commented lines; realloc to save memory; 
indentation changes
v6: remove a line error

Change-Id: I12216da14910f5e2b0970bc1fafc2a20b0ef1ba9
Reviewed-by: Junwei Zhang 
Signed-off-by: Samuel Li 
---
 Makefile.am  |   3 +
 amdgpu/Makefile.am   |   2 +
 amdgpu/Makefile.sources  |   2 +-
 amdgpu/amdgpu_asic_id.c  | 211 +++
 amdgpu/amdgpu_asic_id.h  | 165 
 amdgpu/amdgpu_device.c   |  28 +--
 amdgpu/amdgpu_internal.h |  10 +++
 include/drm/amdgpu.ids   | 170 ++
 8 files changed, 418 insertions(+), 173 deletions(-)
 create mode 100644 amdgpu/amdgpu_asic_id.c
 delete mode 100644 amdgpu/amdgpu_asic_id.h
 create mode 100644 include/drm/amdgpu.ids

diff --git a/Makefile.am b/Makefile.am
index dfb8fcd..8de8f6c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,6 +45,9 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm.pc
+libdrmdatadir = $(datadir)/libdrm
+dist_libdrmdata_DATA = include/drm/amdgpu.ids
+export libdrmdatadir
 
 if HAVE_LIBKMS
 LIBKMS_SUBDIR = libkms
diff --git a/amdgpu/Makefile.am b/amdgpu/Makefile.am
index cf7bc1b..da71c1c 100644
--- a/amdgpu/Makefile.am
+++ b/amdgpu/Makefile.am
@@ -30,6 +30,8 @@ AM_CFLAGS = \
$(PTHREADSTUBS_CFLAGS) \
-I$(top_srcdir)/include/drm
 
+AM_CPPFLAGS = -DAMDGPU_ASIC_ID_TABLE=\"${libdrmdatadir}/amdgpu.ids\"
+
 libdrm_amdgpu_la_LTLIBRARIES = libdrm_amdgpu.la
 libdrm_amdgpu_ladir = $(libdir)
 libdrm_amdgpu_la_LDFLAGS = -version-number 1:0:0 -no-undefined
diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources
index 487b9e0..bc3abaa 100644
--- a/amdgpu/Makefile.sources
+++ b/amdgpu/Makefile.sources
@@ -1,5 +1,5 @@
 LIBDRM_AMDGPU_FILES := \
-   amdgpu_asic_id.h \
+   amdgpu_asic_id.c \
amdgpu_bo.c \
amdgpu_cs.c \
amdgpu_device.c \
diff --git a/amdgpu/amdgpu_asic_id.c b/amdgpu/amdgpu_asic_id.c
new file mode 100644
index 000..be39f4e
--- /dev/null
+++ b/amdgpu/amdgpu_asic_id.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2017 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "xf86drm.h"
+#include "amdgpu_drm.h"
+#include "amdgpu_internal.h"
+
+static int parse_one_line(const char *line, struct amdgpu_asic_id *id)
+{
+   char *buf, *saveptr;
+   char *s_did;
+   char *s_rid;
+   char *s_name;
+   char *endptr;
+   int r = 0;
+
+   buf = strdup(line);
+   if (!buf)
+   return -ENOMEM;
+
+   /* ignore empty line and commented line */
+   if (strlen(line) == 0 || line[0] == '#') {
+   r = -EAGAIN;
+   goto out;
+   }
+
+   /* device id */
+   s_did = strtok_r(buf, ",", &saveptr);
+   if (!s_did) {
+   r = -EINVAL;
+   goto out;
+   }
+
+   id->did = strtol(s_did, &endptr, 16);
+   if (*endptr) {
+   r = -EINVAL;
+   goto out;
+   }
+
+   /* revision id */
+   s_rid = strtok_r(NULL, ",", &saveptr);
+   if (!s_rid) {
+   r = -EINVAL;
+   goto out;
+   }
+
+   id->rid = strtol(s_rid, &endptr, 16);
+   if (*endptr) {
+   r = -EINVAL;
+   goto out;
+   }
+
+   /* marketing name */
+   s_name = strtok_r(NULL, ",", &saveptr);
+   if (!s_name) {
+   r = -EINVAL;
+   goto out;
+   }
+