Message ID | 20161109180850.6012-1-emil.l.velikov@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 10/11/16 03:08 AM, Emil Velikov wrote: > From: Emil Velikov <emil.velikov@collabora.com> > > Parsing config sysfs file wakes up the device. The latter of which may > be slow and isn't required to begin with. > > Reading through config is/was required since the revision is not > available by other means, although with a kernel patch in the way that > is about to change. > > Since returning 0 when one might expect a valid value is a no-go add a > workaround drmDeviceUseRevisionFile() which one can use to say "I don't > care if the revision file returns 0." > > v2: Complete rework - add new API to control the method, instead of > changing it underneat the users' feet. > > Cc: Michel Dänzer <michel.daenzer@amd.com> > Cc: Mauro Santos <registo.mailling@gmail.com> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502 > Signed-off-by: Emil Velikov <emil.velikov@collabora.com> > --- > I don't have a strong preference for/against this or v1. > > With this Mesa will require a 2 line patch. With v1 things will get > fixed magically, when rebuilt against newer libdrm. "drmDeviceUseRevisionFile" seems slightly misleading — the intent is "I don't care about the revision", not "I want you to use the revision file". > +static int drmParsePciDeviceInfo(const char *d_name, > + drmPciDeviceInfoPtr device) > +{ > +#ifdef __linux__ > + if (use_revision_file) > + return parse_separate_sysfs_files(d_name, device); > + > + return parse_config_sysfs_file(d_name, device); I might be better to always try parse_separate_sysfs_files first, but bail from there if the revision files don't exist and the new API wasn't called.
On 09.11.2016 19:08, Emil Velikov wrote: > From: Emil Velikov <emil.velikov@collabora.com> > > Parsing config sysfs file wakes up the device. The latter of which may > be slow and isn't required to begin with. > > Reading through config is/was required since the revision is not > available by other means, although with a kernel patch in the way that > is about to change. > > Since returning 0 when one might expect a valid value is a no-go add a > workaround drmDeviceUseRevisionFile() which one can use to say "I don't > care if the revision file returns 0." > > v2: Complete rework - add new API to control the method, instead of > changing it underneat the users' feet. > > Cc: Michel Dänzer <michel.daenzer@amd.com> > Cc: Mauro Santos <registo.mailling@gmail.com> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502 > Signed-off-by: Emil Velikov <emil.velikov@collabora.com> > --- > I don't have a strong preference for/against this or v1. > > With this Mesa will require a 2 line patch. With v1 things will get > fixed magically, when rebuilt against newer libdrm. > > Mauro I'll send the mesa patch in a second. Feel free to give it a spin. > > Thanks > --- > xf86drm.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- > xf86drm.h | 11 ++++++++++ > 2 files changed, 78 insertions(+), 3 deletions(-) > > diff --git a/xf86drm.c b/xf86drm.c > index 52add5e..676effc 100644 > --- a/xf86drm.c > +++ b/xf86drm.c > @@ -113,6 +113,13 @@ void drmSetServerInfo(drmServerInfoPtr info) > drm_server_info = info; > } > > +static bool use_revision_file; > + > +void drmDeviceUseRevisionFile(void) > +{ > + use_revision_file = true; > +} I think this API of setting a magic hidden global variable is really nasty. Can we add new drmGetDevice[s] entry points with a flags parameter and a flag (per Michel's suggestion) which says "I don't care about the revision ID"? It kind of sucks because they'll have to get a silly name like drmGetDevice[s]2, but I think that's still better than magic global state. Cheers, Nicolai > + > /** > * Output a message to stderr. > * > @@ -2946,10 +2953,56 @@ static int drmGetMaxNodeName(void) > 3 /* length of the node number */; > } > > -static int drmParsePciDeviceInfo(const char *d_name, > - drmPciDeviceInfoPtr device) > -{ > #ifdef __linux__ > +static int parse_separate_sysfs_files(const char *d_name, > + drmPciDeviceInfoPtr device) > +{ > +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) > + static const char *attrs[] = { > + "revision", /* XXX: make sure it's always first, see note below */ > + "vendor", > + "device", > + "subsystem_vendor", > + "subsystem_device", > + }; > + char path[PATH_MAX + 1]; > + unsigned int data[ARRAY_SIZE(attrs)]; > + FILE *fp; > + int ret; > + > + for (unsigned i = 0; i < ARRAY_SIZE(attrs); i++) { > + snprintf(path, PATH_MAX, "/sys/class/drm/%s/device/%s", > + d_name, attrs[i]); > + fp = fopen(path, "r"); > + if (!fp) { > + /* Note: First we check the revision, since older kernels > + * may not have it. Default to zero in such cases. */ > + if (i == 0) { > + data[i] = 0; > + continue; > + } > + return -errno; > + } > + > + ret = fscanf(fp, "%x", &data[i]); > + fclose(fp); > + if (ret != 1) > + return -errno; > + > + } > + > + device->revision_id = data[0] & 0xff; > + device->vendor_id = data[1] & 0xffff; > + device->device_id = data[2] & 0xffff; > + device->subvendor_id = data[3] & 0xffff; > + device->subdevice_id = data[4] & 0xffff; > + > + return 0; > +} > + > +static int parse_config_sysfs_file(const char *d_name, > + drmPciDeviceInfoPtr device) > +{ > char path[PATH_MAX + 1]; > unsigned char config[64]; > int fd, ret; > @@ -2971,6 +3024,17 @@ static int drmParsePciDeviceInfo(const char *d_name, > device->subdevice_id = config[46] | (config[47] << 8); > > return 0; > +} > +#endif > + > +static int drmParsePciDeviceInfo(const char *d_name, > + drmPciDeviceInfoPtr device) > +{ > +#ifdef __linux__ > + if (use_revision_file) > + return parse_separate_sysfs_files(d_name, device); > + > + return parse_config_sysfs_file(d_name, device); > #else > #warning "Missing implementation of drmParsePciDeviceInfo" > return -EINVAL; > diff --git a/xf86drm.h b/xf86drm.h > index 481d882..d1ebc32 100644 > --- a/xf86drm.h > +++ b/xf86drm.h > @@ -796,6 +796,17 @@ extern void drmFreeDevice(drmDevicePtr *device); > extern int drmGetDevices(drmDevicePtr devices[], int max_devices); > extern void drmFreeDevices(drmDevicePtr devices[], int count); > > + > +/** > + * Force any sequential calls to drmGetDevice/drmGetDevices to use the > + * revision sysfs file instead of config one. The latter wakes up the device > + * if powered off. > + * > + * A value of 0 will be returned for the revision_id field if the sysfs file > + * is missing. DO NOT USE THIS if you depend on a correct revision_id. > + */ > +extern void drmDeviceUseRevisionFile(void); > + > #if defined(__cplusplus) > } > #endif >
On 10 November 2016 at 12:40, Nicolai Hähnle <nhaehnle@gmail.com> wrote: > On 09.11.2016 19:08, Emil Velikov wrote: >> >> From: Emil Velikov <emil.velikov@collabora.com> >> >> Parsing config sysfs file wakes up the device. The latter of which may >> be slow and isn't required to begin with. >> >> Reading through config is/was required since the revision is not >> available by other means, although with a kernel patch in the way that >> is about to change. >> >> Since returning 0 when one might expect a valid value is a no-go add a >> workaround drmDeviceUseRevisionFile() which one can use to say "I don't >> care if the revision file returns 0." >> >> v2: Complete rework - add new API to control the method, instead of >> changing it underneat the users' feet. >> >> Cc: Michel Dänzer <michel.daenzer@amd.com> >> Cc: Mauro Santos <registo.mailling@gmail.com> >> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502 >> Signed-off-by: Emil Velikov <emil.velikov@collabora.com> >> --- >> I don't have a strong preference for/against this or v1. >> >> With this Mesa will require a 2 line patch. With v1 things will get >> fixed magically, when rebuilt against newer libdrm. >> >> Mauro I'll send the mesa patch in a second. Feel free to give it a spin. >> >> Thanks >> --- >> xf86drm.c | 70 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- >> xf86drm.h | 11 ++++++++++ >> 2 files changed, 78 insertions(+), 3 deletions(-) >> >> diff --git a/xf86drm.c b/xf86drm.c >> index 52add5e..676effc 100644 >> --- a/xf86drm.c >> +++ b/xf86drm.c >> @@ -113,6 +113,13 @@ void drmSetServerInfo(drmServerInfoPtr info) >> drm_server_info = info; >> } >> >> +static bool use_revision_file; >> + >> +void drmDeviceUseRevisionFile(void) >> +{ >> + use_revision_file = true; >> +} > > > I think this API of setting a magic hidden global variable is really nasty. > > Can we add new drmGetDevice[s] entry points with a flags parameter and a > flag (per Michel's suggestion) which says "I don't care about the revision > ID"? It kind of sucks because they'll have to get a silly name like > drmGetDevice[s]2, but I think that's still better than magic global state. > AFACS Michel suggested (in his latest reply) to have parse_separate_sysfs_files always and make the lack of revision file fatal - falling back to ./config. Not a separate API [+ flags] ? I can do that, as long as he's OK with the idea/approach. Thanks Emil P.S. /me is dreaming of the day when [wh]e'll get to drop 90% of libdrm and it's hacks - viva la libdrm3 !
On 10/11/16 10:38 PM, Emil Velikov wrote: > On 10 November 2016 at 12:40, Nicolai Hähnle <nhaehnle@gmail.com> wrote: >> On 09.11.2016 19:08, Emil Velikov wrote: >>> >>> From: Emil Velikov <emil.velikov@collabora.com> >>> >>> Parsing config sysfs file wakes up the device. The latter of which may >>> be slow and isn't required to begin with. >>> >>> Reading through config is/was required since the revision is not >>> available by other means, although with a kernel patch in the way that >>> is about to change. >>> >>> Since returning 0 when one might expect a valid value is a no-go add a >>> workaround drmDeviceUseRevisionFile() which one can use to say "I don't >>> care if the revision file returns 0." >>> >>> v2: Complete rework - add new API to control the method, instead of >>> changing it underneat the users' feet. >>> >>> Cc: Michel Dänzer <michel.daenzer@amd.com> >>> Cc: Mauro Santos <registo.mailling@gmail.com> >>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502 >>> Signed-off-by: Emil Velikov <emil.velikov@collabora.com> >>> --- >>> I don't have a strong preference for/against this or v1. >>> >>> With this Mesa will require a 2 line patch. With v1 things will get >>> fixed magically, when rebuilt against newer libdrm. >>> >>> Mauro I'll send the mesa patch in a second. Feel free to give it a spin. >>> >>> Thanks >>> --- >>> xf86drm.c | 70 >>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- >>> xf86drm.h | 11 ++++++++++ >>> 2 files changed, 78 insertions(+), 3 deletions(-) >>> >>> diff --git a/xf86drm.c b/xf86drm.c >>> index 52add5e..676effc 100644 >>> --- a/xf86drm.c >>> +++ b/xf86drm.c >>> @@ -113,6 +113,13 @@ void drmSetServerInfo(drmServerInfoPtr info) >>> drm_server_info = info; >>> } >>> >>> +static bool use_revision_file; >>> + >>> +void drmDeviceUseRevisionFile(void) >>> +{ >>> + use_revision_file = true; >>> +} >> >> >> I think this API of setting a magic hidden global variable is really nasty. >> >> Can we add new drmGetDevice[s] entry points with a flags parameter and a >> flag (per Michel's suggestion) which says "I don't care about the revision >> ID"? It kind of sucks because they'll have to get a silly name like >> drmGetDevice[s]2, but I think that's still better than magic global state. >> > AFACS Michel suggested (in his latest reply) to have > parse_separate_sysfs_files always and make the lack of revision file > fatal - falling back to ./config. Not a separate API [+ flags] ? You're mixing up two separate issues. Sorry if I was unclear before, let me try again: My first comment was about the "drmDeviceUseRevisionFile" name being misleading and not reflecting the intent. For this issue, I think Nicolai's suggestion is even better than just fixing the name. My other comment was that parse_separate_sysfs_files should be tried first even if the revision information is needed, and should only bail in that case if the separate revision sysfs files are missing, in which case parse_config_sysfs_file can be used as a fallback. > P.S. /me is dreaming of the day when [wh]e'll get to drop 90% of > libdrm and it's hacks - viva la libdrm3 ! Given the issues with bumping SONAME, I'm afraid you'll have to continue dreaming for a long time. :)
On 14 November 2016 at 09:56, Michel Dänzer <michel@daenzer.net> wrote: > On 10/11/16 10:38 PM, Emil Velikov wrote: >> On 10 November 2016 at 12:40, Nicolai Hähnle <nhaehnle@gmail.com> wrote: >>> On 09.11.2016 19:08, Emil Velikov wrote: >>>> >>>> From: Emil Velikov <emil.velikov@collabora.com> >>>> >>>> Parsing config sysfs file wakes up the device. The latter of which may >>>> be slow and isn't required to begin with. >>>> >>>> Reading through config is/was required since the revision is not >>>> available by other means, although with a kernel patch in the way that >>>> is about to change. >>>> >>>> Since returning 0 when one might expect a valid value is a no-go add a >>>> workaround drmDeviceUseRevisionFile() which one can use to say "I don't >>>> care if the revision file returns 0." >>>> >>>> v2: Complete rework - add new API to control the method, instead of >>>> changing it underneat the users' feet. >>>> >>>> Cc: Michel Dänzer <michel.daenzer@amd.com> >>>> Cc: Mauro Santos <registo.mailling@gmail.com> >>>> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=98502 >>>> Signed-off-by: Emil Velikov <emil.velikov@collabora.com> >>>> --- >>>> I don't have a strong preference for/against this or v1. >>>> >>>> With this Mesa will require a 2 line patch. With v1 things will get >>>> fixed magically, when rebuilt against newer libdrm. >>>> >>>> Mauro I'll send the mesa patch in a second. Feel free to give it a spin. >>>> >>>> Thanks >>>> --- >>>> xf86drm.c | 70 >>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- >>>> xf86drm.h | 11 ++++++++++ >>>> 2 files changed, 78 insertions(+), 3 deletions(-) >>>> >>>> diff --git a/xf86drm.c b/xf86drm.c >>>> index 52add5e..676effc 100644 >>>> --- a/xf86drm.c >>>> +++ b/xf86drm.c >>>> @@ -113,6 +113,13 @@ void drmSetServerInfo(drmServerInfoPtr info) >>>> drm_server_info = info; >>>> } >>>> >>>> +static bool use_revision_file; >>>> + >>>> +void drmDeviceUseRevisionFile(void) >>>> +{ >>>> + use_revision_file = true; >>>> +} >>> >>> >>> I think this API of setting a magic hidden global variable is really nasty. >>> >>> Can we add new drmGetDevice[s] entry points with a flags parameter and a >>> flag (per Michel's suggestion) which says "I don't care about the revision >>> ID"? It kind of sucks because they'll have to get a silly name like >>> drmGetDevice[s]2, but I think that's still better than magic global state. >>> >> AFACS Michel suggested (in his latest reply) to have >> parse_separate_sysfs_files always and make the lack of revision file >> fatal - falling back to ./config. Not a separate API [+ flags] ? > > You're mixing up two separate issues. Sorry if I was unclear before, let > me try again: > > My first comment was about the "drmDeviceUseRevisionFile" name being > misleading and not reflecting the intent. For this issue, I think > Nicolai's suggestion is even better than just fixing the name. > > My other comment was that parse_separate_sysfs_files should be tried > first even if the revision information is needed, and should only bail > in that case if the separate revision sysfs files are missing, in which > case parse_config_sysfs_file can be used as a fallback. > > Makes perfect sense, tyvm ! >> P.S. /me is dreaming of the day when [wh]e'll get to drop 90% of >> libdrm and it's hacks - viva la libdrm3 ! > > Given the issues with bumping SONAME, I'm afraid you'll have to continue > dreaming for a long time. :) > Sticking with libdrm3.so.X + libdrm3.pc should sort that, right ? That plus a simple sed job to make the symbols different/unique. Regardless, anything libdrm3 is unrelated to the topic in question. Emil
diff --git a/xf86drm.c b/xf86drm.c index 52add5e..676effc 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -113,6 +113,13 @@ void drmSetServerInfo(drmServerInfoPtr info) drm_server_info = info; } +static bool use_revision_file; + +void drmDeviceUseRevisionFile(void) +{ + use_revision_file = true; +} + /** * Output a message to stderr. * @@ -2946,10 +2953,56 @@ static int drmGetMaxNodeName(void) 3 /* length of the node number */; } -static int drmParsePciDeviceInfo(const char *d_name, - drmPciDeviceInfoPtr device) -{ #ifdef __linux__ +static int parse_separate_sysfs_files(const char *d_name, + drmPciDeviceInfoPtr device) +{ +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + static const char *attrs[] = { + "revision", /* XXX: make sure it's always first, see note below */ + "vendor", + "device", + "subsystem_vendor", + "subsystem_device", + }; + char path[PATH_MAX + 1]; + unsigned int data[ARRAY_SIZE(attrs)]; + FILE *fp; + int ret; + + for (unsigned i = 0; i < ARRAY_SIZE(attrs); i++) { + snprintf(path, PATH_MAX, "/sys/class/drm/%s/device/%s", + d_name, attrs[i]); + fp = fopen(path, "r"); + if (!fp) { + /* Note: First we check the revision, since older kernels + * may not have it. Default to zero in such cases. */ + if (i == 0) { + data[i] = 0; + continue; + } + return -errno; + } + + ret = fscanf(fp, "%x", &data[i]); + fclose(fp); + if (ret != 1) + return -errno; + + } + + device->revision_id = data[0] & 0xff; + device->vendor_id = data[1] & 0xffff; + device->device_id = data[2] & 0xffff; + device->subvendor_id = data[3] & 0xffff; + device->subdevice_id = data[4] & 0xffff; + + return 0; +} + +static int parse_config_sysfs_file(const char *d_name, + drmPciDeviceInfoPtr device) +{ char path[PATH_MAX + 1]; unsigned char config[64]; int fd, ret; @@ -2971,6 +3024,17 @@ static int drmParsePciDeviceInfo(const char *d_name, device->subdevice_id = config[46] | (config[47] << 8); return 0; +} +#endif + +static int drmParsePciDeviceInfo(const char *d_name, + drmPciDeviceInfoPtr device) +{ +#ifdef __linux__ + if (use_revision_file) + return parse_separate_sysfs_files(d_name, device); + + return parse_config_sysfs_file(d_name, device); #else #warning "Missing implementation of drmParsePciDeviceInfo" return -EINVAL; diff --git a/xf86drm.h b/xf86drm.h index 481d882..d1ebc32 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -796,6 +796,17 @@ extern void drmFreeDevice(drmDevicePtr *device); extern int drmGetDevices(drmDevicePtr devices[], int max_devices); extern void drmFreeDevices(drmDevicePtr devices[], int count); + +/** + * Force any sequential calls to drmGetDevice/drmGetDevices to use the + * revision sysfs file instead of config one. The latter wakes up the device + * if powered off. + * + * A value of 0 will be returned for the revision_id field if the sysfs file + * is missing. DO NOT USE THIS if you depend on a correct revision_id. + */ +extern void drmDeviceUseRevisionFile(void); + #if defined(__cplusplus) } #endif