On Thu, Dec 18, 2014 at 8:13 PM, Vince Hsu <vin...@nvidia.com> wrote: > Hello Ben, > > On 12/18/2014 05:34 PM, Ben Skeggs wrote: >> >> On Thu, Dec 18, 2014 at 4:28 PM, Vince Hsu <vin...@nvidia.com> wrote: >>> >>> This patch creates a subdev for DVFS (Dynamic Voltage and Frequency >>> Scaling) >>> support in Nouveau. This subdev refers to the status information provided >>> by >>> the NVIDIA hardware and tries to adjust the performance level based on >>> the >>> calculated target. Only the GK20A is supported right now. >> >> Hey Vince, >> >> I'd not make a new subdev, but implement this in the PMU (PWR >> currently) subdev. The ucode that's supposed to be running there can >> do the performance monitoring in a more complex implementation, and >> it's PMU counters you're touching to get the usage stats :) But the >> simpler on-host implementation is totally fine. > > Yeah, I know we have the counters defined in daemon.c. Martin reminded me > that Roy had a patch to remove that, sorry that I could not find the link > now. Another reason I did not use the nouveau_specsig is because I had to > create some nvif structures to access the counters and that's not > straightforward. I'm happy to hear you're fine with the on-host > implementation. :) > > I will move all to PWR subdev in the next version. >> >> >> The current base PMU implementation tries to do a lot of stuff that >> you don't need, just override the implementation entirely for GK20A >> for now if that's easier than reworking it. > > So currently there is no dGPU using the PMU? I just don't want to break any > dGPU functions. ;) We upload a custom firmware to it, which we (currently) only use as a script interpreter for memory clock changes. But for your needs right now, it'd be fine to ignore all the common code there for GK20A.
>> >> >> Aside from the subdev move, it looks good so far to me. Glad to see >> the CLK stuff isn't totally useless, despite it needing a *lot* of >> work. > > BTW, can we add some execution time information for pstate? I mean something > like "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state". I know we > don't want to change the user space ABI though. > > Thanks, > Vince > > >> >> Thanks, >> Ben. >> >>> Signed-off-by: Vince Hsu <vin...@nvidia.com> >>> --- >>> drm/Kbuild | 2 + >>> drm/core/include/subdev/dvfs.h | 1 + >>> drm/core/subdev/dvfs/base.c | 1 + >>> drm/core/subdev/dvfs/gk20a.c | 1 + >>> drm/core/subdev/dvfs/priv.h | 1 + >>> nvkm/engine/device/nve0.c | 2 + >>> nvkm/include/core/device.h | 1 + >>> nvkm/include/subdev/dvfs.h | 30 ++++++++ >>> nvkm/subdev/Makefile.am | 5 +- >>> nvkm/subdev/dvfs/Makefile.am | 6 ++ >>> nvkm/subdev/dvfs/base.c | 129 ++++++++++++++++++++++++++++++++++ >>> nvkm/subdev/dvfs/gk20a.c | 156 >>> +++++++++++++++++++++++++++++++++++++++++ >>> nvkm/subdev/dvfs/priv.h | 43 ++++++++++++ >>> 13 files changed, 376 insertions(+), 2 deletions(-) >>> create mode 120000 drm/core/include/subdev/dvfs.h >>> create mode 120000 drm/core/subdev/dvfs/base.c >>> create mode 120000 drm/core/subdev/dvfs/gk20a.c >>> create mode 120000 drm/core/subdev/dvfs/priv.h >>> create mode 100644 nvkm/include/subdev/dvfs.h >>> create mode 100644 nvkm/subdev/dvfs/Makefile.am >>> create mode 100644 nvkm/subdev/dvfs/base.c >>> create mode 100644 nvkm/subdev/dvfs/gk20a.c >>> create mode 100644 nvkm/subdev/dvfs/priv.h >>> >>> diff --git a/drm/Kbuild b/drm/Kbuild >>> index 061d9faef836..e7eb05e666a0 100644 >>> --- a/drm/Kbuild >>> +++ b/drm/Kbuild >>> @@ -227,6 +227,8 @@ nouveau-y += core/subdev/volt/base.o >>> nouveau-y += core/subdev/volt/gpio.o >>> nouveau-y += core/subdev/volt/nv40.o >>> nouveau-y += core/subdev/volt/gk20a.o >>> +nouveau-y += core/subdev/dvfs/base.o >>> +nouveau-y += core/subdev/dvfs/gk20a.o >>> >>> nouveau-y += core/engine/falcon.o >>> nouveau-y += core/engine/xtensa.o >>> diff --git a/drm/core/include/subdev/dvfs.h >>> b/drm/core/include/subdev/dvfs.h >>> new file mode 120000 >>> index 000000000000..553a6968350b >>> --- /dev/null >>> +++ b/drm/core/include/subdev/dvfs.h >>> @@ -0,0 +1 @@ >>> +../../../../nvkm/include/subdev/dvfs.h >>> \ No newline at end of file >>> diff --git a/drm/core/subdev/dvfs/base.c b/drm/core/subdev/dvfs/base.c >>> new file mode 120000 >>> index 000000000000..296334ee52d1 >>> --- /dev/null >>> +++ b/drm/core/subdev/dvfs/base.c >>> @@ -0,0 +1 @@ >>> +../../../../nvkm/subdev/dvfs/base.c >>> \ No newline at end of file >>> diff --git a/drm/core/subdev/dvfs/gk20a.c b/drm/core/subdev/dvfs/gk20a.c >>> new file mode 120000 >>> index 000000000000..d05d493e3fc9 >>> --- /dev/null >>> +++ b/drm/core/subdev/dvfs/gk20a.c >>> @@ -0,0 +1 @@ >>> +../../../../nvkm/subdev/dvfs/gk20a.c >>> \ No newline at end of file >>> diff --git a/drm/core/subdev/dvfs/priv.h b/drm/core/subdev/dvfs/priv.h >>> new file mode 120000 >>> index 000000000000..9b471dc44f48 >>> --- /dev/null >>> +++ b/drm/core/subdev/dvfs/priv.h >>> @@ -0,0 +1 @@ >>> +../../../../nvkm/subdev/dvfs/priv.h >>> \ No newline at end of file >>> diff --git a/nvkm/engine/device/nve0.c b/nvkm/engine/device/nve0.c >>> index ba7922d31351..5a830a37a15d 100644 >>> --- a/nvkm/engine/device/nve0.c >>> +++ b/nvkm/engine/device/nve0.c >>> @@ -41,6 +41,7 @@ >>> #include <subdev/bar.h> >>> #include <subdev/pwr.h> >>> #include <subdev/volt.h> >>> +#include <subdev/dvfs.h> >>> >>> #include <engine/device.h> >>> #include <engine/dmaobj.h> >>> @@ -180,6 +181,7 @@ nve0_identify(struct nouveau_device *device) >>> device->oclass[NVDEV_ENGINE_COPY2 ] = >>> &nve0_copy2_oclass; >>> device->oclass[NVDEV_ENGINE_PERFMON] = >>> &gk20a_perfmon_oclass; >>> device->oclass[NVDEV_SUBDEV_VOLT ] = >>> &gk20a_volt_oclass; >>> + device->oclass[NVDEV_SUBDEV_DVFS ] = gk20a_dvfs_oclass; >>> break; >>> case 0xf0: >>> device->cname = "GK110"; >>> diff --git a/nvkm/include/core/device.h b/nvkm/include/core/device.h >>> index 2ec2e50d3676..162fa6a3cfcc 100644 >>> --- a/nvkm/include/core/device.h >>> +++ b/nvkm/include/core/device.h >>> @@ -39,6 +39,7 @@ enum nv_subdev_type { >>> NVDEV_SUBDEV_VOLT, >>> NVDEV_SUBDEV_THERM, >>> NVDEV_SUBDEV_CLOCK, >>> + NVDEV_SUBDEV_DVFS, >>> >>> NVDEV_ENGINE_FIRST, >>> NVDEV_ENGINE_DMAOBJ = NVDEV_ENGINE_FIRST, >>> diff --git a/nvkm/include/subdev/dvfs.h b/nvkm/include/subdev/dvfs.h >>> new file mode 100644 >>> index 000000000000..3851629a0de4 >>> --- /dev/null >>> +++ b/nvkm/include/subdev/dvfs.h >>> @@ -0,0 +1,30 @@ >>> +#ifndef __NOUVEAU_DVFS_H__ >>> +#define __NOUVEAU_DVFS_H__ >>> + >>> +#include <core/subdev.h> >>> +#include <core/device.h> >>> + >>> +#include <subdev/timer.h> >>> + >>> +struct nouveau_dvfs_data { >>> + int p_load_target; >>> + int p_load_max; >>> + int p_smooth; >>> + unsigned int avg_load; >>> +}; >>> + >>> +struct nouveau_dvfs { >>> + struct nouveau_subdev base; >>> + struct nouveau_alarm alarm; >>> + struct nouveau_dvfs_data *data; >>> +}; >>> + >>> +static inline struct nouveau_dvfs * >>> +nouveau_dvfs(void *obj) >>> +{ >>> + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_DVFS]; >>> +} >>> + >>> +extern struct nouveau_oclass *gk20a_dvfs_oclass; >>> + >>> +#endif >>> diff --git a/nvkm/subdev/Makefile.am b/nvkm/subdev/Makefile.am >>> index 5a48ddb87981..3d11e0833032 100644 >>> --- a/nvkm/subdev/Makefile.am >>> +++ b/nvkm/subdev/Makefile.am >>> @@ -1,5 +1,5 @@ >>> SUBDIRS = bar bus bios clock devinit fb fuse gpio i2c ibus instmem \ >>> - ltc mc mxm pwr therm timer vm volt >>> + ltc mc mxm pwr therm timer vm volt dvfs >>> >>> noinst_LTLIBRARIES = libsubdev.la >>> >>> @@ -22,4 +22,5 @@ libsubdev_la_LIBADD = bar/libbar.la \ >>> therm/libtherm.la \ >>> timer/libtimer.la \ >>> vm/libvm.la \ >>> - volt/libvolt.la >>> + volt/libvolt.la \ >>> + dvfs/dvfs.la >>> diff --git a/nvkm/subdev/dvfs/Makefile.am b/nvkm/subdev/dvfs/Makefile.am >>> new file mode 100644 >>> index 000000000000..c09d4ec4124d >>> --- /dev/null >>> +++ b/nvkm/subdev/dvfs/Makefile.am >>> @@ -0,0 +1,6 @@ >>> +noinst_LTLIBRARIES = libdvfs.la >>> + >>> +libdvfs_la_SOURCES = base.c \ >>> + gk20a.c >>> + >>> +include $(srcdir)/../Makefile.subdev >>> diff --git a/nvkm/subdev/dvfs/base.c b/nvkm/subdev/dvfs/base.c >>> new file mode 100644 >>> index 000000000000..88ae201840a8 >>> --- /dev/null >>> +++ b/nvkm/subdev/dvfs/base.c >>> @@ -0,0 +1,129 @@ >>> +/* >>> + * Copyright (c) 2014, NVIDIA CORPORATION. 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 AUTHORS OR COPYRIGHT HOLDERS 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. >>> + */ >>> + >>> +#include <core/option.h> >>> + >>> +#include <subdev/clock.h> >>> +#include <subdev/dvfs.h> >>> +#include <subdev/volt.h> >>> + >>> +#include "priv.h" >>> + >>> +static void >>> +_nouveau_dvfs_work(struct nouveau_alarm *alarm) >>> +{ >>> + struct nouveau_dvfs *dvfs = container_of(alarm, struct >>> nouveau_dvfs, >>> + alarm); >>> + struct nouveau_dvfs_data *data = dvfs->data; >>> + struct nouveau_object *object = nv_object(dvfs); >>> + struct nouveau_dvfs_impl *impl = (void *)object->oclass; >>> + struct nouveau_dvfs_dev_status status; >>> + u32 utilization = 0; >>> + int state, ret; >>> + >>> + ret = impl->get_dev_status(dvfs, &status); >>> + if (ret) { >>> + nv_warn(dvfs, "failed to get device status\n"); >>> + goto resched; >>> + } >>> + >>> + if (status.total) >>> + utilization = div_u64((u64)status.busy * 100, >>> status.total); >>> + >>> + data->avg_load = (data->p_smooth * data->avg_load) + utilization; >>> + data->avg_load /= data->p_smooth + 1; >>> + nv_trace(dvfs, "utilization = %d %%, avg_load = %d %%\n", >>> + utilization, data->avg_load); >>> + >>> + ret = impl->get_cur_state(dvfs, &state); >>> + if (ret) { >>> + nv_warn(dvfs, "failed to get current state\n"); >>> + goto resched; >>> + } >>> + >>> + if (impl->get_target_state(dvfs, &state, data->avg_load)) { >>> + nv_trace(dvfs, "set new state to %d\n", state); >>> + impl->target(dvfs, &state); >>> + } >>> + >>> +resched: >>> + impl->reset_dev_status(dvfs); >>> + nouveau_timer_alarm(dvfs, 100000000, alarm); >>> +} >>> + >>> +int >>> +_nouveau_dvfs_fini(struct nouveau_object *object, bool suspend) >>> +{ >>> + struct nouveau_dvfs *dvfs = (void *)object; >>> + >>> + nouveau_timer_alarm_cancel(dvfs, &dvfs->alarm); >>> + >>> + return nouveau_subdev_fini(&dvfs->base, suspend); >>> +} >>> + >>> +int >>> +_nouveau_dvfs_init(struct nouveau_object *object) >>> +{ >>> + struct nouveau_dvfs *dvfs = (void *)object; >>> + struct nouveau_clock *clk = nouveau_clock(object); >>> + struct nouveau_volt *volt = nouveau_volt(object); >>> + int ret; >>> + >>> + ret = nouveau_subdev_init(&dvfs->base); >>> + if (ret) >>> + return ret; >>> + >>> + if (!clk || !volt) >>> + return -EINVAL; >>> + >>> + nouveau_timer_alarm(dvfs, 2000000000, &dvfs->alarm); >>> + >>> + return 0; >>> +} >>> + >>> +void >>> +_nouveau_dvfs_dtor(struct nouveau_object *object) >>> +{ >>> + struct nouveau_dvfs *dvfs = (void *)object; >>> + >>> + nouveau_subdev_destroy(&dvfs->base); >>> +} >>> + >>> +int >>> +nouveau_dvfs_create_(struct nouveau_object *parent, >>> + struct nouveau_object *engine, >>> + struct nouveau_oclass *oclass, >>> + int size, void **pobject) >>> +{ >>> + struct nouveau_dvfs *dvfs; >>> + int ret; >>> + >>> + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "DVFS", >>> + "dvfs", size, pobject); >>> + dvfs = *pobject; >>> + if (ret) >>> + return ret; >>> + >>> + nouveau_alarm_init(&dvfs->alarm, _nouveau_dvfs_work); >>> + >>> + return 0; >>> +} >>> diff --git a/nvkm/subdev/dvfs/gk20a.c b/nvkm/subdev/dvfs/gk20a.c >>> new file mode 100644 >>> index 000000000000..efebd2c10f99 >>> --- /dev/null >>> +++ b/nvkm/subdev/dvfs/gk20a.c >>> @@ -0,0 +1,156 @@ >>> +/* >>> + * Copyright (c) 2014, NVIDIA CORPORATION. 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 AUTHORS OR COPYRIGHT HOLDERS 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. >>> + */ >>> + >>> +#include <subdev/clock.h> >>> +#include <subdev/dvfs.h> >>> +#include <subdev/volt.h> >>> + >>> +#include "priv.h" >>> + >>> +#define BUSY_SLOT 0 >>> +#define CLK_SLOT 7 >>> + >>> +struct gk20a_dvfs_priv { >>> + struct nouveau_dvfs base; >>> +}; >>> + >>> +static int >>> +gk20a_dvfs_target(struct nouveau_dvfs *dvfs, int *state) >>> +{ >>> + struct nouveau_clock *clk = nouveau_clock(dvfs); >>> + >>> + return nouveau_clock_astate(clk, *state, 0, false); >>> +} >>> + >>> +static int >>> +gk20a_dvfs_get_cur_state(struct nouveau_dvfs *dvfs, int *state) >>> +{ >>> + struct nouveau_clock *clk = nouveau_clock(dvfs); >>> + >>> + *state = clk->pstate; >>> + return 0; >>> +} >>> + >>> +static int >>> +gk20a_dvfs_get_target_state(struct nouveau_dvfs *dvfs, int *state, int >>> load) >>> +{ >>> + struct nouveau_dvfs_data *data = dvfs->data; >>> + struct nouveau_clock *clk = nouveau_clock(dvfs); >>> + int cur_level, level; >>> + >>> + /* For GK20A, the performance level is directly mapped to pstate >>> */ >>> + level = cur_level = clk->pstate; >>> + >>> + if (load > data->p_load_max) { >>> + level = min(clk->state_nr - 1, level + (clk->state_nr / >>> 3)); >>> + } else { >>> + level += ((load - data->p_load_target) * 10 / >>> + data->p_load_target) / 2; >>> + level = max(0, level); >>> + level = min(clk->state_nr - 1, level); >>> + } >>> + >>> + nv_trace(dvfs, "cur level = %d, new level = %d\n", cur_level, >>> level); >>> + >>> + *state = level; >>> + >>> + if (level == cur_level) >>> + return 0; >>> + else >>> + return 1; >>> +} >>> + >>> +static int >>> +gk20a_dvfs_get_dev_status(struct nouveau_dvfs *dvfs, >>> + struct nouveau_dvfs_dev_status *status) >>> +{ >>> + status->busy = nv_rd32(dvfs, 0x10a508 + (BUSY_SLOT * 0x10)); >>> + status->total= nv_rd32(dvfs, 0x10a508 + (CLK_SLOT * 0x10)); >>> + return 0; >>> +} >>> + >>> +static void >>> +gk20a_dvfs_reset_dev_status(struct nouveau_dvfs *dvfs) >>> +{ >>> + nv_wr32(dvfs, 0x10a508 + (BUSY_SLOT * 0x10), 0x80000000); >>> + nv_wr32(dvfs, 0x10a508 + (CLK_SLOT * 0x10), 0x80000000); >>> +} >>> + >>> +static int >>> +gk20a_dvfs_init(struct nouveau_object *object) >>> +{ >>> + struct gk20a_dvfs_priv *priv = (void *)object; >>> + int ret; >>> + >>> + /* init pwr perf counter */ >>> + nv_wr32(priv, 0x10a504 + (BUSY_SLOT * 0x10), 0x00200001); >>> + nv_wr32(priv, 0x10a50c + (BUSY_SLOT * 0x10), 0x00000002); >>> + nv_wr32(priv, 0x10a50c + (CLK_SLOT * 0x10), 0x00000003); >>> + >>> + ret = nouveau_dvfs_init(&priv->base); >>> + if (ret) >>> + return ret; >>> + >>> + return 0; >>> +} >>> + >>> +struct nouveau_dvfs_data gk20a_dvfs_data = { >>> + .p_load_target = 70, >>> + .p_load_max = 90, >>> + .p_smooth = 1, >>> +}; >>> + >>> +static int >>> +gk20a_dvfs_ctor(struct nouveau_object *parent, struct nouveau_object >>> *engine, >>> + struct nouveau_oclass *oclass, void *data, u32 size, >>> + struct nouveau_object **pobject) >>> +{ >>> + struct gk20a_dvfs_priv *priv; >>> + struct nouveau_dvfs *dvfs; >>> + int ret; >>> + >>> + ret = nouveau_dvfs_create(parent, engine, oclass, &priv); >>> + *pobject = nv_object(priv); >>> + if (ret) >>> + return ret; >>> + >>> + dvfs = &priv->base; >>> + dvfs->data = &gk20a_dvfs_data; >>> + >>> + return 0; >>> +} >>> + >>> +struct nouveau_oclass * >>> +gk20a_dvfs_oclass = &(struct nouveau_dvfs_impl) { >>> + .base.handle = NV_SUBDEV(DVFS, 0xea), >>> + .base.ofuncs = &(struct nouveau_ofuncs) { >>> + .ctor = gk20a_dvfs_ctor, >>> + .dtor = _nouveau_dvfs_dtor, >>> + .init = gk20a_dvfs_init, >>> + .fini = _nouveau_dvfs_fini, >>> + }, >>> + .get_dev_status = gk20a_dvfs_get_dev_status, >>> + .reset_dev_status = gk20a_dvfs_reset_dev_status, >>> + .target = gk20a_dvfs_target, >>> + .get_cur_state = gk20a_dvfs_get_cur_state, >>> + .get_target_state = gk20a_dvfs_get_target_state, >>> +}.base; >>> diff --git a/nvkm/subdev/dvfs/priv.h b/nvkm/subdev/dvfs/priv.h >>> new file mode 100644 >>> index 000000000000..95c8a00a01c1 >>> --- /dev/null >>> +++ b/nvkm/subdev/dvfs/priv.h >>> @@ -0,0 +1,43 @@ >>> +#ifndef __NVKM_DVFS_PRIV_H__ >>> +#define __NVKM_DVFS_PRIV_H__ >>> + >>> +#include <subdev/dvfs.h> >>> + >>> +struct nouveau_dvfs_dev_status { >>> + unsigned long total; >>> + unsigned long busy; >>> + int cur_state; >>> +}; >>> + >>> +struct nouveau_dvfs_impl { >>> + struct nouveau_oclass base; >>> + int (*get_dev_status)(struct nouveau_dvfs *, >>> + struct nouveau_dvfs_dev_status *); >>> + void (*reset_dev_status)(struct nouveau_dvfs *); >>> + int (*target)(struct nouveau_dvfs *, int *state); >>> + int (*get_cur_state)(struct nouveau_dvfs *, int *state); >>> + int (*get_target_state)(struct nouveau_dvfs *, int *state, int >>> load); >>> +}; >>> + >>> +#define nouveau_dvfs_create(p,e,o,d) >>> \ >>> + nouveau_dvfs_create_((p), (e), (o), sizeof(**d), (void **)d) >>> +#define nouveau_dvfs_destroy(p) ({ >>> \ >>> + struct nouveau_dvfs *d = (p); >>> \ >>> + _nouveau_dvfs_dtor(nv_object(d)); >>> \ >>> +}) >>> +#define nouveau_dvfs_init(p) ({ >>> \ >>> + struct nouveau_dvfs *d = (p); >>> \ >>> + _nouveau_dvfs_init(nv_object(d)); >>> \ >>> +}) >>> +#define nouveau_dvfs_fini(p,s) ({ >>> \ >>> + struct nouveau_dvfs *d = (p); >>> \ >>> + _nouveau_dvfs_fini(nv_object(d), (s)); >>> \ >>> +}) >>> + >>> +int nouveau_dvfs_create_(struct nouveau_object *, struct nouveau_object >>> *, >>> + struct nouveau_oclass *, int, void **); >>> +void _nouveau_dvfs_dtor(struct nouveau_object *); >>> +int _nouveau_dvfs_init(struct nouveau_object *); >>> +int _nouveau_dvfs_fini(struct nouveau_object *, bool suspend); >>> + >>> +#endif >>> -- >>> 1.9.1 >>> >>> _______________________________________________ >>> Nouveau mailing list >>> Nouveau@lists.freedesktop.org >>> http://lists.freedesktop.org/mailman/listinfo/nouveau > > > > ----------------------------------------------------------------------------------- > This email message is for the sole use of the intended recipient(s) and may > contain > confidential information. Any unauthorized review, use, disclosure or > distribution > is prohibited. If you are not the intended recipient, please contact the > sender by > reply email and destroy all copies of the original message. > ----------------------------------------------------------------------------------- _______________________________________________ Nouveau mailing list Nouveau@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/nouveau