_PSD(P-State Dependency) provides performance control, no matter legacy
P-state or CPPC, logical processor dependency information.

In order to re-use it for CPPC, this commit extracts the delivery of _PSD
info from push_pxx_to_hypervisor() and wrap it with a new sub-hypercall
XEN_PM_PSD.

Signed-off-by: Penny Zheng <penny.zh...@amd.com>
---
v2 -> v3:
- new commit
---
 drivers/xen/xen-acpi-processor.c | 82 ++++++++++++++++++++------------
 include/xen/interface/platform.h |  8 ++--
 2 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index e9f38f171240..8db8631a4b9d 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -157,18 +157,40 @@ xen_copy_pss_data(struct acpi_processor *_pr,
        }
        return dst_states;
 }
-static int xen_copy_psd_data(struct acpi_processor *_pr,
-                            struct xen_processor_performance *dst)
+static int xen_copy_pct_data(struct acpi_pct_register *pct,
+                            struct xen_pct_register *dst_pct)
+{
+       /* It would be nice if you could just do 'memcpy(pct, dst_pct') but
+        * sadly the Xen structure did not have the proper padding so the
+        * descriptor field takes two (dst_pct) bytes instead of one (pct).
+        */
+       dst_pct->descriptor = pct->descriptor;
+       dst_pct->length = pct->length;
+       dst_pct->space_id = pct->space_id;
+       dst_pct->bit_width = pct->bit_width;
+       dst_pct->bit_offset = pct->bit_offset;
+       dst_pct->reserved = pct->reserved;
+       dst_pct->address = pct->address;
+       return 0;
+}
+static int push_psd_to_hypervisor(struct acpi_processor *_pr)
 {
+       struct xen_platform_op op = {
+               .cmd                    = XENPF_set_processor_pminfo,
+               .interface_version      = XENPF_INTERFACE_VERSION,
+               .u.set_pminfo.id        = _pr->acpi_id,
+               .u.set_pminfo.type      = XEN_PM_PSD,
+       };
        struct acpi_psd_package *pdomain;
+       int ret = 0;
 
        BUILD_BUG_ON(sizeof(struct xen_psd_package) !=
                     sizeof(struct acpi_psd_package));
 
-       /* This information is enumerated only if 
acpi_processor_preregister_performance
-        * has been called.
+       /* This information is enumerated only if
+        * acpi_processor_preregister_performance has been called.
         */
-       dst->shared_type = _pr->performance->shared_type;
+       op.u.set_pminfo.shared_type = _pr->performance->shared_type;
 
        pdomain = &(_pr->performance->domain_info);
 
@@ -180,32 +202,30 @@ static int xen_copy_psd_data(struct acpi_processor *_pr,
         * running as a PVH dom0.
         */
        if (pdomain->num_processors <= 1 ||
-           dst->shared_type == CPUFREQ_SHARED_TYPE_NONE) {
+           op.u.set_pminfo.shared_type == CPUFREQ_SHARED_TYPE_NONE) {
                if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
-                       dst->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+                       op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_ALL;
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
-                       dst->shared_type = CPUFREQ_SHARED_TYPE_HW;
+                       op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_HW;
                else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
-                       dst->shared_type = CPUFREQ_SHARED_TYPE_ANY;
-
+                       op.u.set_pminfo.shared_type = CPUFREQ_SHARED_TYPE_ANY;
        }
-       memcpy(&(dst->domain_info), pdomain, sizeof(struct acpi_psd_package));
-       return 0;
-}
-static int xen_copy_pct_data(struct acpi_pct_register *pct,
-                            struct xen_pct_register *dst_pct)
-{
-       /* It would be nice if you could just do 'memcpy(pct, dst_pct') but
-        * sadly the Xen structure did not have the proper padding so the
-        * descriptor field takes two (dst_pct) bytes instead of one (pct).
-        */
-       dst_pct->descriptor = pct->descriptor;
-       dst_pct->length = pct->length;
-       dst_pct->space_id = pct->space_id;
-       dst_pct->bit_width = pct->bit_width;
-       dst_pct->bit_offset = pct->bit_offset;
-       dst_pct->reserved = pct->reserved;
-       dst_pct->address = pct->address;
+
+       memcpy(&(op.u.set_pminfo.domain_info), pdomain,
+              sizeof(struct acpi_psd_package));
+
+       if (!no_hypercall)
+               ret = HYPERVISOR_platform_op(&op);
+
+       if (!ret) {
+               pr_debug("ACPI CPU%u - _PSD uploaded.\n", _pr->acpi_id);
+       } else if ((ret != -EINVAL) && (ret != -ENOSYS))
+               /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
+                * table is referencing a non-existing CPU - which can happen
+                * with broken ACPI tables. */
+               pr_warn("(_PSD): Hypervisor error (%d) for ACPI CPU%u\n",
+                       ret, _pr->acpi_id);
+
        return 0;
 }
 static int push_pxx_to_hypervisor(struct acpi_processor *_pr)
@@ -234,10 +254,8 @@ static int push_pxx_to_hypervisor(struct acpi_processor 
*_pr)
                set_xen_guest_handle(dst_perf->states, dst_states);
                dst_perf->flags |= XEN_PX_PSS;
        }
-       if (!xen_copy_psd_data(_pr, dst_perf))
-               dst_perf->flags |= XEN_PX_PSD;
 
-       if (dst_perf->flags != (XEN_PX_PSD | XEN_PX_PSS | XEN_PX_PCT | 
XEN_PX_PPC)) {
+       if (dst_perf->flags != (XEN_PX_PSS | XEN_PX_PCT | XEN_PX_PPC)) {
                pr_warn("ACPI CPU%u missing some P-state data (%x), skipping\n",
                        _pr->acpi_id, dst_perf->flags);
                ret = -ENODEV;
@@ -281,6 +299,10 @@ static int upload_pm_data(struct acpi_processor *_pr)
                mutex_unlock(&acpi_ids_mutex);
                return -EBUSY;
        }
+
+       if (_pr->performance && _pr->performance->states)
+               err |= push_psd_to_hypervisor(_pr);
+
        if (_pr->flags.power)
                err = push_cxx_to_hypervisor(_pr);
 
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index 79a443c65ea9..a35e1eb958f3 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -319,11 +319,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_getidletime_t);
 #define XEN_PM_PX   1
 #define XEN_PM_TX   2
 #define XEN_PM_PDC  3
+#define XEN_PM_PSD  4
 /* Px sub info type */
 #define XEN_PX_PCT   1
 #define XEN_PX_PSS   2
 #define XEN_PX_PPC   4
-#define XEN_PX_PSD   8
 
 struct xen_power_register {
        uint32_t     space_id;
@@ -399,8 +399,6 @@ struct xen_processor_performance {
        struct xen_pct_register status_register;
        uint32_t state_count;     /* total available performance states */
        GUEST_HANDLE(xen_processor_px) states;
-       struct xen_psd_package domain_info;
-       uint32_t shared_type;     /* coordination type of this processor */
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_processor_performance);
 
@@ -410,9 +408,11 @@ struct xenpf_set_processor_pminfo {
        uint32_t type;  /* {XEN_PM_CX, XEN_PM_PX} */
        union {
                struct xen_processor_power          power;/* Cx: _CST/_CSD */
-               struct xen_processor_performance    perf; /* Px: 
_PPC/_PCT/_PSS/_PSD */
+               struct xen_psd_package              domain_info; /* _PSD */
+               struct xen_processor_performance    perf; /* Px: _PPC/_PCT/_PSS 
*/
                GUEST_HANDLE(uint32_t)              pdc;
        };
+       uint32_t shared_type;     /* coordination type of this processor */
 };
 DEFINE_GUEST_HANDLE_STRUCT(xenpf_set_processor_pminfo);
 
-- 
2.34.1


Reply via email to