diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2014-07-21 14:35:27 +1000 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-07-21 14:48:45 +1000 |
commit | a4202bc19821a024e460592159507a059f993d3b (patch) | |
tree | 9385e51a6fe4e3ef4b5bf905e2a0188b91935aa6 | |
parent | 1b5220b4b7a337463cfe77e36d8988039f6facca (diff) | |
download | skiboot-a4202bc19821a024e460592159507a059f993d3b.zip skiboot-a4202bc19821a024e460592159507a059f993d3b.tar.gz skiboot-a4202bc19821a024e460592159507a059f993d3b.tar.bz2 |
PCI: Allow to set frozen state
The patch introduces a new OPAL API opal_pci_eeh_freeze_set(),
which allows to set frozen state for the specified PE, so that
we can support "compound" PE in kernel.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | core/pci-opal.c | 19 | ||||
-rw-r--r-- | hw/p7ioc-phb.c | 33 | ||||
-rw-r--r-- | hw/phb3.c | 35 | ||||
-rw-r--r-- | include/opal.h | 9 | ||||
-rw-r--r-- | include/pci.h | 2 |
5 files changed, 96 insertions, 2 deletions
diff --git a/core/pci-opal.c b/core/pci-opal.c index 59f4d5c..2048d7f 100644 --- a/core/pci-opal.c +++ b/core/pci-opal.c @@ -93,6 +93,25 @@ static int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, } opal_call(OPAL_PCI_EEH_FREEZE_CLEAR, opal_pci_eeh_freeze_clear, 3); +static int64_t opal_pci_eeh_freeze_set(uint64_t phb_id, uint64_t pe_number, + uint64_t eeh_action_token) +{ + struct phb *phb = pci_get_phb(phb_id); + int64_t rc; + + if (!phb) + return OPAL_PARAMETER; + if (!phb->ops->eeh_freeze_set) + return OPAL_UNSUPPORTED; + phb->ops->lock(phb); + rc = phb->ops->eeh_freeze_set(phb, pe_number, eeh_action_token); + phb->ops->unlock(phb); + pci_put_phb(phb); + + return rc; +} +opal_call(OPAL_PCI_EEH_FREEZE_SET, opal_pci_eeh_freeze_set, 3); + static int64_t opal_pci_err_injct(uint64_t phb_id, uint32_t pe_no, uint32_t type, uint32_t function, uint64_t addr, uint64_t mask) diff --git a/hw/p7ioc-phb.c b/hw/p7ioc-phb.c index 64dbfed..834a794 100644 --- a/hw/p7ioc-phb.c +++ b/hw/p7ioc-phb.c @@ -1301,6 +1301,38 @@ static int64_t p7ioc_eeh_freeze_clear(struct phb *phb, uint64_t pe_number, return OPAL_SUCCESS; } +static int64_t p7ioc_eeh_freeze_set(struct phb *phb, uint64_t pe_number, + uint64_t eeh_action_token) +{ + struct p7ioc_phb *p = phb_to_p7ioc_phb(phb); + uint64_t data; + + if (pe_number > 127) + return OPAL_PARAMETER; + + if (eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_MMIO && + eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_DMA && + eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_ALL) + return OPAL_PARAMETER; + + if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_MMIO) { + p7ioc_phb_ioda_sel(p, IODA_TBL_PESTA, pe_number, false); + data = in_be64(p->regs + PHB_IODA_DATA0); + data |= IODA_PESTA_MMIO_FROZEN; + out_be64(p->regs + PHB_IODA_DATA0, data); + } + + if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_DMA) { + p7ioc_phb_ioda_sel(p, IODA_TBL_PESTB, pe_number, false); + data = in_be64(p->regs + PHB_IODA_DATA0); + data |= IODA_PESTB_DMA_STOPPED; + out_be64(p->regs + PHB_IODA_DATA0, data); + } + + return OPAL_SUCCESS; +} + + static int64_t p7ioc_err_injct(struct phb *phb, uint32_t pe_no, uint32_t type, uint32_t function, uint64_t address, uint64_t mask) @@ -2526,6 +2558,7 @@ static const struct phb_ops p7ioc_phb_ops = { .pci_reinit = p7ioc_pci_reinit, .eeh_freeze_status = p7ioc_eeh_freeze_status, .eeh_freeze_clear = p7ioc_eeh_freeze_clear, + .eeh_freeze_set = p7ioc_eeh_freeze_set, .err_injct = p7ioc_err_injct, .get_diag_data = NULL, .get_diag_data2 = p7ioc_get_diag_data, @@ -2431,6 +2431,40 @@ static int64_t phb3_eeh_freeze_clear(struct phb *phb, uint64_t pe_number, return OPAL_SUCCESS; } +static int64_t phb3_eeh_freeze_set(struct phb *phb, uint64_t pe_number, + uint64_t eeh_action_token) +{ + struct phb3 *p = phb_to_phb3(phb); + uint64_t data; + + if (p->state == PHB3_STATE_BROKEN) + return OPAL_HARDWARE; + + if (pe_number >= PHB3_MAX_PE_NUM) + return OPAL_PARAMETER; + + if (eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_MMIO && + eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_DMA && + eeh_action_token != OPAL_EEH_ACTION_SET_FREEZE_ALL) + return OPAL_PARAMETER; + + if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_MMIO) { + phb3_ioda_sel(p, IODA2_TBL_PESTA, pe_number, false); + data = in_be64(p->regs + PHB_IODA_DATA0); + data |= IODA2_PESTA_MMIO_FROZEN; + out_be64(p->regs + PHB_IODA_DATA0, data); + } + + if (eeh_action_token & OPAL_EEH_ACTION_SET_FREEZE_DMA) { + phb3_ioda_sel(p, IODA2_TBL_PESTB, pe_number, false); + data = in_be64(p->regs + PHB_IODA_DATA0); + data |= IODA2_PESTB_DMA_STOPPED; + out_be64(p->regs + PHB_IODA_DATA0, data); + } + + return OPAL_SUCCESS; +} + static int64_t phb3_eeh_next_error(struct phb *phb, uint64_t *first_frozen_pe, uint16_t *pci_error_type, @@ -3009,6 +3043,7 @@ static const struct phb_ops phb3_ops = { .poll = phb3_poll, .eeh_freeze_status = phb3_eeh_freeze_status, .eeh_freeze_clear = phb3_eeh_freeze_clear, + .eeh_freeze_set = phb3_eeh_freeze_set, .next_error = phb3_eeh_next_error, .err_injct = phb3_err_injct, .get_diag_data = NULL, diff --git a/include/opal.h b/include/opal.h index 592f139..43b7c80 100644 --- a/include/opal.h +++ b/include/opal.h @@ -132,7 +132,8 @@ #define OPAL_DUMP_INFO2 94 #define OPAL_WRITE_OPPANEL_ASYNC 95 #define OPAL_PCI_ERR_INJCT 96 -#define OPAL_LAST 96 +#define OPAL_PCI_EEH_FREEZE_SET 97 +#define OPAL_LAST 97 #ifndef __ASSEMBLY__ @@ -157,7 +158,11 @@ enum OpalFreezeState { enum OpalEehFreezeActionToken { OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, - OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3 + OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3, + + OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1, + OPAL_EEH_ACTION_SET_FREEZE_DMA = 2, + OPAL_EEH_ACTION_SET_FREEZE_ALL = 3 }; enum OpalPciStatusToken { diff --git a/include/pci.h b/include/pci.h index 9acc068..aff70b3 100644 --- a/include/pci.h +++ b/include/pci.h @@ -252,6 +252,8 @@ struct phb_ops { uint64_t *phb_status); int64_t (*eeh_freeze_clear)(struct phb *phb, uint64_t pe_number, uint64_t eeh_action_token); + int64_t (*eeh_freeze_set)(struct phb *phb, uint64_t pe_number, + uint64_t eeh_action_token); int64_t (*err_injct)(struct phb *phb, uint32_t pe_no, uint32_t type, uint32_t function, uint64_t addr, uint64_t mask); int64_t (*get_diag_data)(struct phb *phb, void *diag_buffer, |