drm/nouveau/pm: extend profile interface for destroy/init/fini

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Martin Peres <martin.peres@labri.fr>
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 4fff09e..dcc1692 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -183,6 +183,12 @@
 	else
 		profile = pm->profile_dc;
 
+	if (profile != pm->profile) {
+		pm->profile->func->fini(pm->profile);
+		pm->profile = profile;
+		pm->profile->func->init(pm->profile);
+	}
+
 	/* select performance level based on profile */
 	perflvl = profile->func->select(profile);
 
@@ -251,6 +257,11 @@
 	return 0;
 }
 
+static void
+nouveau_pm_static_dummy(struct nouveau_pm_profile *profile)
+{
+}
+
 static struct nouveau_pm_level *
 nouveau_pm_static_select(struct nouveau_pm_profile *profile)
 {
@@ -258,6 +269,9 @@
 }
 
 const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = {
+	.destroy = nouveau_pm_static_dummy,
+	.init = nouveau_pm_static_dummy,
+	.fini = nouveau_pm_static_dummy,
 	.select = nouveau_pm_static_select,
 };
 
@@ -856,6 +870,7 @@
 
 	pm->profile_ac = &pm->boot.profile;
 	pm->profile_dc = &pm->boot.profile;
+	pm->profile = &pm->boot.profile;
 	pm->cur = &pm->boot;
 
 	/* add performance levels from vbios */
@@ -893,6 +908,12 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
+	struct nouveau_pm_profile *profile, *tmp;
+
+	list_for_each_entry_safe(profile, tmp, &pm->profiles, head) {
+		list_del(&profile->head);
+		profile->func->destroy(profile);
+	}
 
 	if (pm->cur != &pm->boot)
 		nouveau_pm_perflvl_set(dev, &pm->boot);