cxl: Prevent adapter reset if an active context exists

This patch prevents resetting the cxl adapter via sysfs in presence of
one or more active cxl_context on it. This protects against an
unrecoverable error caused by PSL owning a dirty cache line even after
reset and host tries to touch the same cache line. In case a force reset
of the card is required irrespective of any active contexts, the int
value -1 can be stored in the 'reset' sysfs attribute of the card.

The patch introduces a new atomic_t member named contexts_num inside
struct cxl that holds the number of active context attached to the card
, which is checked against '0' before proceeding with the reset. To
prevent against a race condition where a context is activated just after
reset check is performed, the contexts_num is atomically set to '-1'
after reset-check to indicate that no more contexts can be activated on
the card anymore.

Before activating a context we atomically test if contexts_num is
non-negative and if so, increment its value by one. In case the value of
contexts_num is negative then it indicates that the card is about to be
reset and context activation is error-ed out at that point.

Fixes: 62fa19d4b4 ("cxl: Add ability to reset the card")
Cc: stable@vger.kernel.org # v4.0+
Acked-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Tento commit je obsažen v:
Vaibhav Jain
2016-10-14 15:08:36 +05:30
odevzdal Michael Ellerman
rodič 65bc3ece84
revize 70b565bbdb
9 změnil soubory, kde provedl 121 přidání a 7 odebrání

Zobrazit soubor

@@ -75,12 +75,31 @@ static ssize_t reset_adapter_store(struct device *device,
int val;
rc = sscanf(buf, "%i", &val);
if ((rc != 1) || (val != 1))
if ((rc != 1) || (val != 1 && val != -1))
return -EINVAL;
if ((rc = cxl_ops->adapter_reset(adapter)))
return rc;
return count;
/*
* See if we can lock the context mapping that's only allowed
* when there are no contexts attached to the adapter. Once
* taken this will also prevent any context from getting activated.
*/
if (val == 1) {
rc = cxl_adapter_context_lock(adapter);
if (rc)
goto out;
rc = cxl_ops->adapter_reset(adapter);
/* In case reset failed release context lock */
if (rc)
cxl_adapter_context_unlock(adapter);
} else if (val == -1) {
/* Perform a forced adapter reset */
rc = cxl_ops->adapter_reset(adapter);
}
out:
return rc ? rc : count;
}
static ssize_t load_image_on_perst_show(struct device *device,