VAS windows can be closed in the hypervisor due to lost credits
when the core is removed and the kernel gets fault for NX
requests on these inactive windows. If the NX requests are
issued on these inactive windows, OS gets page faults and the
paste failure will be returned to the user space. If the lost
credits are available later with core add, reopen these windows
and set them active. Later when the OS sees page faults on these
active windows, it creates mapping on the new paste address.
Then the user space can continue to use these windows and send
HW compression requests to NX successfully.

Signed-off-by: Haren Myneni <ha...@linux.ibm.com>
---
 arch/powerpc/platforms/pseries/vas.c | 91 +++++++++++++++++++++++++++-
 1 file changed, 90 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/vas.c 
b/arch/powerpc/platforms/pseries/vas.c
index a297720bcdae..96178dd58adf 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -565,6 +565,88 @@ static int __init get_vas_capabilities(u8 feat, enum 
vas_cop_feat_type type,
        return 0;
 }
 
+/*
+ * VAS windows can be closed due to lost credits when the core is
+ * removed. So reopen them if credits are available due to DLPAR
+ * core add and set the window active status. When NX sees the page
+ * fault on the unmapped paste address, the kernel handles the fault
+ * by setting the remapping to new paste address if the window is
+ * active.
+ */
+static int reconfig_open_windows(struct vas_caps *vcaps, int creds)
+{
+       long domain[PLPAR_HCALL9_BUFSIZE] = {VAS_DEFAULT_DOMAIN_ID};
+       struct vas_cop_feat_caps *caps = &vcaps->caps;
+       struct pseries_vas_window *win = NULL, *tmp;
+       int rc, mv_ents = 0;
+
+       /*
+        * Nothing to do if there are no closed windows.
+        */
+       if (!vcaps->nr_close_wins)
+               return 0;
+
+       /*
+        * For the core removal, the hypervisor reduces the credits
+        * assigned to the LPAR and the kernel closes VAS windows
+        * in the hypervisor depends on reduced credits. The kernel
+        * uses LIFO (the last windows that are opened will be closed
+        * first) and expects to open in the same order when credits
+        * are available.
+        * For example, 40 windows are closed when the LPAR lost 2 cores
+        * (dedicated). If 1 core is added, this LPAR can have 20 more
+        * credits. It means the kernel can reopen 20 windows. So move
+        * 20 entries in the VAS windows lost and reopen next 20 windows.
+        */
+       if (vcaps->nr_close_wins > creds)
+               mv_ents = vcaps->nr_close_wins - creds;
+
+       list_for_each_entry_safe(win, tmp, &vcaps->list, win_list) {
+               if (!mv_ents)
+                       break;
+
+               mv_ents--;
+       }
+
+       list_for_each_entry_safe_from(win, tmp, &vcaps->list, win_list) {
+               /*
+                * Nothing to do on this window if it is not closed
+                * with VAS_WIN_NO_CRED_CLOSE
+                */
+               if (!(win->vas_win.status & VAS_WIN_NO_CRED_CLOSE))
+                       continue;
+
+               rc = allocate_setup_window(win, (u64 *)&domain[0],
+                                          caps->win_type);
+               if (rc)
+                       return rc;
+
+               rc = h_modify_vas_window(win);
+               if (rc)
+                       goto out;
+
+               mutex_lock(&win->vas_win.task_ref.mmap_mutex);
+               /*
+                * Set window status to active
+                */
+               win->vas_win.status &= ~VAS_WIN_NO_CRED_CLOSE;
+               mutex_unlock(&win->vas_win.task_ref.mmap_mutex);
+               win->win_type = caps->win_type;
+               if (!--vcaps->nr_close_wins)
+                       break;
+       }
+
+       return 0;
+out:
+       /*
+        * Window modify HCALL failed. So close the window to the
+        * hypervisor and return.
+        */
+       free_irq_setup(win);
+       h_deallocate_vas_window(win->vas_win.winid);
+       return rc;
+}
+
 /*
  * The hypervisor reduces the available credits if the LPAR lost core. It
  * means the excessive windows should not be active and the user space
@@ -673,7 +755,14 @@ static int vas_reconfig_capabilties(u8 type)
         * closed / reopened. Hold the vas_pseries_mutex so that the
         * the user space can not open new windows.
         */
-       if (old_nr_creds >  new_nr_creds) {
+       if (old_nr_creds <  new_nr_creds) {
+               /*
+                * If the existing target credits is less than the new
+                * target, reopen windows if they are closed due to
+                * the previous DLPAR (core removal).
+                */
+               rc = reconfig_open_windows(vcaps, new_nr_creds - old_nr_creds);
+       } else {
                /*
                 * # active windows is more than new LPAR available
                 * credits. So close the excessive windows.
-- 
2.27.0


Reply via email to