diff options
author | Ananth N Mavinakayanahalli <ananth@in.ibm.com> | 2014-10-16 14:16:40 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2014-10-22 18:19:37 +1100 |
commit | bed82938878cff16c539c1c6b3887b2cf65b4f57 (patch) | |
tree | 5dd0647e2da6b854c188be93180db5bed542c9da | |
parent | 465b156e61f027a10ca3a7de97b857de4bd48bb6 (diff) | |
download | talos-skiboot-bed82938878cff16c539c1c6b3887b2cf65b4f57.tar.gz talos-skiboot-bed82938878cff16c539c1c6b3887b2cf65b4f57.zip |
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.c | 65 |
1 files changed, 34 insertions, 31 deletions
@@ -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); |