summaryrefslogtreecommitdiffstats
path: root/hw/phb3.c
diff options
context:
space:
mode:
authorAndrew Donnellan <andrew.donnellan@au1.ibm.com>2017-01-27 18:33:16 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-03-20 11:23:33 +1100
commit9fdd5e830b322097d415dc31499b2dd61eebbdfc (patch)
tree9dfad2ab7032a232025043fa2029c5493ebd7d7c /hw/phb3.c
parente9ede1c48b3bd5af3a68e2277146f3b6b1c7ca3c (diff)
downloadblackbird-skiboot-9fdd5e830b322097d415dc31499b2dd61eebbdfc.tar.gz
blackbird-skiboot-9fdd5e830b322097d415dc31499b2dd61eebbdfc.zip
hw/phb3: add host sync notifier to trigger creset/CAPP disable on kexec
To support kexec in Linux, we need to trigger a creset to disable CAPP mode on each PHB that has been attached to a CAPP. Add a host sync notifier, phb3_host_sync_reset(), that will be triggered by the opal_sync_host_reboot() call that Linux makes when "shutting down" a powernv system (this includes bringing the system down to prepare it for kexec). This notifier will trigger a creset only on PHBs that need it, and will poll regularly until the creset completes. This approach is somewhat hacky, as it's somewhat of an abuse of the host sync notifier system (IMHO), but it seems the most obvious way to ensure that the reset/CAPP disable occurs that will work with old kernel versions and not require additional support on the kernel side. Suggested-by: Stewart Smith <stewart@linux.vnet.ibm.com> Signed-off-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/phb3.c')
-rw-r--r--hw/phb3.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/hw/phb3.c b/hw/phb3.c
index f64e49e8..89d66f3c 100644
--- a/hw/phb3.c
+++ b/hw/phb3.c
@@ -4610,6 +4610,44 @@ static bool phb3_calculate_windows(struct phb3 *p)
return true;
}
+/*
+ * Trigger a creset to disable CAPI mode on kernel shutdown.
+ *
+ * This helper is called repeatedly by the host sync notifier mechanism, which
+ * relies on the kernel to regularly poll the OPAL_SYNC_HOST_REBOOT call as it
+ * shuts down.
+ *
+ * This is a somewhat hacky abuse of the host sync notifier mechanism, but the
+ * alternatives require a new API call which won't work for older kernels.
+ */
+static bool phb3_host_sync_reset(void *data)
+{
+ struct phb3 *p = (struct phb3 *)data;
+ struct pci_slot *slot = p->phb.slot;
+ struct proc_chip *chip = get_chip(p->chip_id);
+ int64_t rc;
+
+ switch (slot->state) {
+ case PHB3_SLOT_NORMAL:
+ lock(&capi_lock);
+ rc = (chip->capp_phb3_attached_mask & (1 << p->index)) ?
+ OPAL_PHB_CAPI_MODE_CAPI :
+ OPAL_PHB_CAPI_MODE_PCIE;
+ unlock(&capi_lock);
+
+ if (rc == OPAL_PHB_CAPI_MODE_PCIE)
+ return true;
+
+ PHBINF(p, "PHB in CAPI mode, resetting\n");
+ p->flags &= ~PHB3_CAPP_RECOVERY;
+ phb3_creset(slot);
+ return false;
+ default:
+ rc = slot->ops.poll(slot);
+ return rc <= OPAL_SUCCESS;
+ }
+}
+
static void phb3_create(struct dt_node *np)
{
const struct dt_property *prop;
@@ -4743,6 +4781,8 @@ static void phb3_create(struct dt_node *np)
/* Load capp microcode into capp unit */
capp_load_ucode(p);
+ opal_add_host_sync_notifier(phb3_host_sync_reset, p);
+
/* Platform additional setup */
if (platform.pci_setup_phb)
platform.pci_setup_phb(&p->phb, p->index);
OpenPOWER on IntegriCloud