aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnanth N Mavinakayanahalli <ananth@in.ibm.com>2014-10-16 14:16:40 +0530
committerStewart Smith <stewart@linux.vnet.ibm.com>2014-12-03 16:44:03 +1100
commit3484a186e5542813fc0c356d28c17e6afe0e81c6 (patch)
tree01e44a0f7e1ef7d416b552283540951a71c8605d
parentf469cb35866a1499ad3855e6753718bd077a816a (diff)
downloadskiboot-3484a186e5542813fc0c356d28c17e6afe0e81c6.zip
skiboot-3484a186e5542813fc0c356d28c17e6afe0e81c6.tar.gz
skiboot-3484a186e5542813fc0c356d28c17e6afe0e81c6.tar.bz2
PSI: Drive link down on HIR
After sending the FSP reset sequence via PSIHBCR, drive the PSI link down without actually waiting for the PSI interrupt indicating the 'Link Inactive Transition'. There have been cases where this interrupt doesn't arrive and we are left high and dry waiting for it, while the FSP comes back up and thinks Sapphire is not initializing the new link (bz 117526 for instance). Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hw/psi.c65
1 files changed, 34 insertions, 31 deletions
diff --git a/hw/psi.c b/hw/psi.c
index 42eac39..bde0446 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -52,37 +52,6 @@ void psi_set_link_polling(bool active)
psi_link_poll_active = active;
}
-/*
- * Resetting the FSP is a multi step sequence:
- * 1. Read the PSIHBCR
- * 2. Set the PSIHBCR[6] -- write register back.
- * 3. Read PSIHBCR again
- * 4. Reset PSIHBCR[6] -- write register back.
- */
-void psi_reset_fsp(struct psi *psi)
-{
- lock(&psi_lock);
-
- if (psi->active) {
- u64 reg;
-
- printf("PSI: Driving FSP reset via PSI\n");
- reg = in_be64(psi->regs + PSIHB_CR);
- reg &= ~(0xfffull << 20); /* Reset error bits */
- reg |= PSIHB_CR_FSP_RESET; /* FSP reset trigger start */
- out_be64(psi->regs + PSIHB_CR, reg);
- printf("PSI[0x%03x]: FSP reset start PSIHBCR set to %llx\n",
- psi->chip_id, in_be64(psi->regs + PSIHB_CR));
-
- reg = in_be64(psi->regs + PSIHB_CR);
- reg &= ~PSIHB_CR_FSP_RESET; /* Clear FSP reset bit */
- out_be64(psi->regs + PSIHB_CR, reg); /* Complete reset */
- printf("PSI[0x%03x]: FSP reset complete. PSIHBCR set to %llx\n",
- psi->chip_id, in_be64(psi->regs + PSIHB_CR));
- }
- unlock(&psi_lock);
-}
-
void psi_disable_link(struct psi *psi)
{
lock(&psi_lock);
@@ -127,6 +96,40 @@ void psi_disable_link(struct psi *psi)
unlock(&psi_lock);
}
+/*
+ * Resetting the FSP is a multi step sequence:
+ * 1. Read the PSIHBCR
+ * 2. Set the PSIHBCR[6] -- write register back.
+ * 3. Read PSIHBCR again
+ * 4. Reset PSIHBCR[6] -- write register back.
+ */
+void psi_reset_fsp(struct psi *psi)
+{
+ lock(&psi_lock);
+
+ if (psi->active) {
+ u64 reg;
+
+ printf("PSI: Driving FSP reset via PSI\n");
+ reg = in_be64(psi->regs + PSIHB_CR);
+ reg &= ~(0xfffull << 20); /* Reset error bits */
+ reg |= PSIHB_CR_FSP_RESET; /* FSP reset trigger start */
+ out_be64(psi->regs + PSIHB_CR, reg);
+ printf("PSI[0x%03x]: FSP reset start PSIHBCR set to %llx\n",
+ psi->chip_id, in_be64(psi->regs + PSIHB_CR));
+
+ reg = in_be64(psi->regs + PSIHB_CR);
+ reg &= ~PSIHB_CR_FSP_RESET; /* Clear FSP reset bit */
+ out_be64(psi->regs + PSIHB_CR, reg); /* Complete reset */
+ printf("PSI[0x%03x]: FSP reset complete. PSIHBCR set to %llx\n",
+ psi->chip_id, in_be64(psi->regs + PSIHB_CR));
+ }
+ unlock(&psi_lock);
+
+ /* Now bring down the PSI link too... */
+ psi_disable_link(psi);
+}
+
bool psi_check_link_active(struct psi *psi)
{
u64 val = in_be64(psi->regs + PSIHB_CR);