LoongArch: Parse MADT to get multi-processor information
[linux-2.6-microblaze.git] / drivers / thermal / thermal_netlink.c
index 73e68cc..32fea51 100644 (file)
@@ -43,6 +43,11 @@ static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] =
        [THERMAL_GENL_ATTR_CDEV_MAX_STATE]      = { .type = NLA_U32 },
        [THERMAL_GENL_ATTR_CDEV_NAME]           = { .type = NLA_STRING,
                                                    .len = THERMAL_NAME_LENGTH },
+       /* CPU capabilities */
+       [THERMAL_GENL_ATTR_CPU_CAPABILITY]              = { .type = NLA_NESTED },
+       [THERMAL_GENL_ATTR_CPU_CAPABILITY_ID]           = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE]  = { .type = NLA_U32 },
+       [THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY]   = { .type = NLA_U32 },
 };
 
 struct param {
@@ -58,6 +63,8 @@ struct param {
        int temp;
        int cdev_state;
        int cdev_max_state;
+       struct thermal_genl_cpu_caps *cpu_capabilities;
+       int cpu_capabilities_count;
 };
 
 typedef int (*cb_t)(struct param *);
@@ -190,6 +197,42 @@ static int thermal_genl_event_gov_change(struct param *p)
        return 0;
 }
 
+static int thermal_genl_event_cpu_capability_change(struct param *p)
+{
+       struct thermal_genl_cpu_caps *cpu_cap = p->cpu_capabilities;
+       struct sk_buff *msg = p->msg;
+       struct nlattr *start_cap;
+       int i;
+
+       start_cap = nla_nest_start(msg, THERMAL_GENL_ATTR_CPU_CAPABILITY);
+       if (!start_cap)
+               return -EMSGSIZE;
+
+       for (i = 0; i < p->cpu_capabilities_count; ++i) {
+               if (nla_put_u32(msg, THERMAL_GENL_ATTR_CPU_CAPABILITY_ID,
+                               cpu_cap->cpu))
+                       goto out_cancel_nest;
+
+               if (nla_put_u32(msg, THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE,
+                               cpu_cap->performance))
+                       goto out_cancel_nest;
+
+               if (nla_put_u32(msg, THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY,
+                               cpu_cap->efficiency))
+                       goto out_cancel_nest;
+
+               ++cpu_cap;
+       }
+
+       nla_nest_end(msg, start_cap);
+
+       return 0;
+out_cancel_nest:
+       nla_nest_cancel(msg, start_cap);
+
+       return -EMSGSIZE;
+}
+
 int thermal_genl_event_tz_delete(struct param *p)
        __attribute__((alias("thermal_genl_event_tz")));
 
@@ -219,6 +262,7 @@ static cb_t event_cb[] = {
        [THERMAL_GENL_EVENT_CDEV_DELETE]        = thermal_genl_event_cdev_delete,
        [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE]  = thermal_genl_event_cdev_state_update,
        [THERMAL_GENL_EVENT_TZ_GOV_CHANGE]      = thermal_genl_event_gov_change,
+       [THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE] = thermal_genl_event_cpu_capability_change,
 };
 
 /*
@@ -356,6 +400,15 @@ int thermal_notify_tz_gov_change(int tz_id, const char *name)
        return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_GOV_CHANGE, &p);
 }
 
+int thermal_genl_cpu_capability_event(int count,
+                                     struct thermal_genl_cpu_caps *caps)
+{
+       struct param p = { .cpu_capabilities_count = count, .cpu_capabilities = caps };
+
+       return thermal_genl_send_event(THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE, &p);
+}
+EXPORT_SYMBOL_GPL(thermal_genl_cpu_capability_event);
+
 /*************************** Command encoding ********************************/
 
 static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz,