powerpc/pseries/vas: Use QoS credits from the userspace
authorHaren Myneni <haren@linux.ibm.com>
Sat, 19 Mar 2022 09:28:09 +0000 (02:28 -0700)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 4 May 2022 12:00:47 +0000 (22:00 +1000)
The user can change the QoS credits dynamically with the
management console interface which notifies OS with sysfs. After
returning from the OS interface successfully, the management
console updates the hypervisor. Since the VAS capabilities in
the hypervisor is not updated when the OS gets the update,
the kernel is using the old total credits value from the
hypervisor. Fix this issue by using the new QoS credits
from the userspace instead of depending on VAS capabilities
from the hypervisor.

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/76d156f8af1e03cc09369d68e0bfad0c40031bcc.camel@linux.ibm.com
arch/powerpc/platforms/pseries/vas-sysfs.c
arch/powerpc/platforms/pseries/vas.c
arch/powerpc/platforms/pseries/vas.h

index 909535ca513a0a035f919d31a35dc99c470bd07d..ec65586cbeb39092886544d7c4213656f78d5dc3 100644 (file)
@@ -27,22 +27,31 @@ struct vas_caps_entry {
 
 /*
  * This function is used to get the notification from the drmgr when
- * QoS credits are changed. Though receiving the target total QoS
- * credits here, get the official QoS capabilities from the hypervisor.
+ * QoS credits are changed.
  */
-static ssize_t update_total_credits_trigger(struct vas_cop_feat_caps *caps,
+static ssize_t update_total_credits_store(struct vas_cop_feat_caps *caps,
                                                const char *buf, size_t count)
 {
        int err;
        u16 creds;
 
        err = kstrtou16(buf, 0, &creds);
+       /*
+        * The user space interface from the management console
+        * notifies OS with the new QoS credits and then the
+        * hypervisor. So OS has to use this new credits value
+        * and reconfigure VAS windows (close or reopen depends
+        * on the credits available) instead of depending on VAS
+        * QoS capabilities from the hypervisor.
+        */
        if (!err)
-               err = vas_reconfig_capabilties(caps->win_type);
+               err = vas_reconfig_capabilties(caps->win_type, creds);
 
        if (err)
                return -EINVAL;
 
+       pr_info("Set QoS total credits %u\n", creds);
+
        return count;
 }
 
@@ -92,7 +101,7 @@ VAS_ATTR_RO(nr_total_credits);
 VAS_ATTR_RO(nr_used_credits);
 
 static struct vas_sysfs_entry update_total_credits_attribute =
-       __ATTR(update_total_credits, 0200, NULL, update_total_credits_trigger);
+       __ATTR(update_total_credits, 0200, NULL, update_total_credits_store);
 
 static struct attribute *vas_def_capab_attrs[] = {
        &nr_total_credits_attribute.attr,
index 1f59d78c77a1fd690a978f619c6017c0c0f78de5..ec643bbdb67fcabf2428f34c1eeaee613a174859 100644 (file)
@@ -779,10 +779,10 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
  * changes. Reconfig window configurations based on the credits
  * availability from this new capabilities.
  */
-int vas_reconfig_capabilties(u8 type)
+int vas_reconfig_capabilties(u8 type, int new_nr_creds)
 {
        struct vas_cop_feat_caps *caps;
-       int old_nr_creds, new_nr_creds;
+       int old_nr_creds;
        struct vas_caps *vcaps;
        int rc = 0, nr_active_wins;
 
@@ -795,12 +795,6 @@ int vas_reconfig_capabilties(u8 type)
        caps = &vcaps->caps;
 
        mutex_lock(&vas_pseries_mutex);
-       rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, vcaps->feat,
-                                     (u64)virt_to_phys(&hv_cop_caps));
-       if (rc)
-               goto out;
-
-       new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds);
 
        old_nr_creds = atomic_read(&caps->nr_total_credits);
 
@@ -832,7 +826,6 @@ int vas_reconfig_capabilties(u8 type)
                                        false);
        }
 
-out:
        mutex_unlock(&vas_pseries_mutex);
        return rc;
 }
@@ -850,7 +843,7 @@ static int pseries_vas_notifier(struct notifier_block *nb,
        struct of_reconfig_data *rd = data;
        struct device_node *dn = rd->dn;
        const __be32 *intserv = NULL;
-       int len, rc = 0;
+       int new_nr_creds, len, rc = 0;
 
        if ((action == OF_RECONFIG_ATTACH_NODE) ||
                (action == OF_RECONFIG_DETACH_NODE))
@@ -862,7 +855,15 @@ static int pseries_vas_notifier(struct notifier_block *nb,
        if (!intserv)
                return NOTIFY_OK;
 
-       rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE);
+       rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES,
+                                       vascaps[VAS_GZIP_DEF_FEAT_TYPE].feat,
+                                       (u64)virt_to_phys(&hv_cop_caps));
+       if (!rc) {
+               new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds);
+               rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE,
+                                               new_nr_creds);
+       }
+
        if (rc)
                pr_err("Failed reconfig VAS capabilities with DLPAR\n");
 
index 34177881e998031daac8ac4d6b19c290717456d4..333ffa2f9f426758510481e3edde8812d81930f1 100644 (file)
@@ -135,7 +135,7 @@ struct pseries_vas_window {
 };
 
 int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps);
-int vas_reconfig_capabilties(u8 type);
+int vas_reconfig_capabilties(u8 type, int new_nr_creds);
 int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps);
 
 #ifdef CONFIG_PPC_VAS