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-10-22 18:19:37 +1100
commitbed82938878cff16c539c1c6b3887b2cf65b4f57 (patch)
tree5dd0647e2da6b854c188be93180db5bed542c9da
parent465b156e61f027a10ca3a7de97b857de4bd48bb6 (diff)
downloadskiboot-bed82938878cff16c539c1c6b3887b2cf65b4f57.zip
skiboot-bed82938878cff16c539c1c6b3887b2cf65b4f57.tar.gz
skiboot-bed82938878cff16c539c1c6b3887b2cf65b4f57.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 ffd50bf..6752bf4 100644
--- a/hw/psi.c
+++ b/hw/psi.c
@@ -48,37 +48,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);
@@ -123,6 +92,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);