mutex_lock(&vas_pseries_mutex);
/*
* VAS window is already closed in the hypervisor when
- * lost the credit. So just remove the entry from
- * the list, remove task references and free vas_window
+ * lost the credit or with migration. So just remove the entry
+ * from the list, remove task references and free vas_window
* struct.
*/
- if (win->vas_win.status & VAS_WIN_NO_CRED_CLOSE) {
+ if (!(win->vas_win.status & VAS_WIN_NO_CRED_CLOSE) &&
+ !(win->vas_win.status & VAS_WIN_MIGRATE_CLOSE)) {
rc = deallocate_free_window(win);
if (rc) {
mutex_unlock(&vas_pseries_mutex);
* by setting the remapping to new paste address if the window is
* active.
*/
-static int reconfig_open_windows(struct vas_caps *vcaps, int creds)
+static int reconfig_open_windows(struct vas_caps *vcaps, int creds,
+ bool migrate)
{
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;
+ int flag;
/*
* Nothing to do if there are no closed windows.
* (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.
+ * For partition migration, reopen all windows that are closed
+ * during resume.
*/
- if (vcaps->nr_close_wins > creds)
+ if ((vcaps->nr_close_wins > creds) && !migrate)
mv_ents = vcaps->nr_close_wins - creds;
list_for_each_entry_safe(win, tmp, &vcaps->list, win_list) {
mv_ents--;
}
+ /*
+ * Open windows if they are closed only with migration or
+ * DLPAR (lost credit) before.
+ */
+ if (migrate)
+ flag = VAS_WIN_MIGRATE_CLOSE;
+ else
+ flag = VAS_WIN_NO_CRED_CLOSE;
+
list_for_each_entry_safe_from(win, tmp, &vcaps->list, win_list) {
/*
+ * This window is closed with DLPAR and migration events.
+ * So reopen the window with the last event.
+ * The user space is not suspended with the current
+ * migration notifier. So the user space can issue DLPAR
+ * CPU hotplug while migration in progress. In this case
+ * this window will be opened with the last event.
+ */
+ if ((win->vas_win.status & VAS_WIN_NO_CRED_CLOSE) &&
+ (win->vas_win.status & VAS_WIN_MIGRATE_CLOSE)) {
+ win->vas_win.status &= ~flag;
+ continue;
+ }
+
+ /*
* Nothing to do on this window if it is not closed
- * with VAS_WIN_NO_CRED_CLOSE
+ * with this flag
*/
- if (!(win->vas_win.status & VAS_WIN_NO_CRED_CLOSE))
+ if (!(win->vas_win.status & flag))
continue;
rc = allocate_setup_window(win, (u64 *)&domain[0],
/*
* Set window status to active
*/
- win->vas_win.status &= ~VAS_WIN_NO_CRED_CLOSE;
+ win->vas_win.status &= ~flag;
mutex_unlock(&win->vas_win.task_ref.mmap_mutex);
win->win_type = caps->win_type;
if (!--vcaps->nr_close_wins)
* the user space to fall back to SW compression and manage with the
* existing windows.
*/
-static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds)
+static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
+ bool migrate)
{
struct pseries_vas_window *win, *tmp;
struct vas_user_win_ref *task_ref;
struct vm_area_struct *vma;
- int rc = 0;
+ int rc = 0, flag;
+
+ if (migrate)
+ flag = VAS_WIN_MIGRATE_CLOSE;
+ else
+ flag = VAS_WIN_NO_CRED_CLOSE;
list_for_each_entry_safe(win, tmp, &vcap->list, win_list) {
/*
* This window is already closed due to lost credit
- * before. Go for next window.
+ * or for migration before. Go for next window.
+ * For migration, nothing to do since this window
+ * closed for DLPAR and will be reopened even on
+ * the destination system with other DLPAR operation.
*/
- if (win->vas_win.status & VAS_WIN_NO_CRED_CLOSE)
+ if ((win->vas_win.status & VAS_WIN_MIGRATE_CLOSE) ||
+ (win->vas_win.status & VAS_WIN_NO_CRED_CLOSE)) {
+ win->vas_win.status |= flag;
continue;
+ }
task_ref = &win->vas_win.task_ref;
mutex_lock(&task_ref->mmap_mutex);
* Number of available credits are reduced, So select
* and close windows.
*/
- win->vas_win.status |= VAS_WIN_NO_CRED_CLOSE;
+ win->vas_win.status |= flag;
mmap_write_lock(task_ref->mm);
/*
* later when the process issued with close(FD).
*/
rc = deallocate_free_window(win);
- if (rc)
+ /*
+ * This failure is from the hypervisor.
+ * No way to stop migration for these failures.
+ * So ignore error and continue closing other windows.
+ */
+ if (rc && !migrate)
return rc;
vcap->nr_close_wins++;
- if (!--excess_creds)
+ /*
+ * For migration, do not depend on lpar_creds in case if
+ * mismatch with the hypervisor value (should not happen).
+ * So close all active windows in the list and will be
+ * reopened windows based on the new lpar_creds on the
+ * destination system during resume.
+ */
+ if (!migrate && !--excess_creds)
break;
}
* 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);
+ rc = reconfig_open_windows(vcaps, new_nr_creds - old_nr_creds,
+ false);
} else {
/*
* # active windows is more than new LPAR available
nr_active_wins = vcaps->nr_open_windows - vcaps->nr_close_wins;
if (nr_active_wins > new_nr_creds)
rc = reconfig_close_windows(vcaps,
- nr_active_wins - new_nr_creds);
+ nr_active_wins - new_nr_creds,
+ false);
}
out: