summaryrefslogtreecommitdiffstats
path: root/core/pci-opal.c
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2015-04-09 13:47:12 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-05-07 17:51:29 +1000
commit9e5747525d909fbf71a68d3593bba06d2bc4e86c (patch)
tree2df9cfe91dcd91c25bdbc4457fbb0ebdf9a8270a /core/pci-opal.c
parentc04f054808ce744526494253d3fa03330d53dcfb (diff)
downloadblackbird-skiboot-9e5747525d909fbf71a68d3593bba06d2bc4e86c.tar.gz
blackbird-skiboot-9e5747525d909fbf71a68d3593bba06d2bc4e86c.zip
eeh: Fix eeh event handling
The opal eeh interrupt handlers raise an opal event (OPAL_EVENT_PCI_ERROR) whenever there is some processing required from the OS. The OS then needs to call opal_pci_next_error(...) in a loop passing each phb in turn to clear the event. However opal_pci_next_error(...) clears the event unconditionally meaning it would be possible for eeh events to be cleared without processing them leading to missed events. This patch fixes the problem by keeping track of eeh events on a per-phb basis and only clearing the opal event once all phb eeh events have been cleared. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/pci-opal.c')
-rw-r--r--core/pci-opal.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/core/pci-opal.c b/core/pci-opal.c
index a1c6e7a8..75c689e6 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -53,6 +53,26 @@ opal_call(OPAL_PCI_CONFIG_WRITE_BYTE, opal_pci_config_write_byte, 4);
opal_call(OPAL_PCI_CONFIG_WRITE_HALF_WORD, opal_pci_config_write_half_word, 4);
opal_call(OPAL_PCI_CONFIG_WRITE_WORD, opal_pci_config_write_word, 4);
+static struct lock opal_eeh_evt_lock = LOCK_UNLOCKED;
+static uint64_t opal_eeh_evt = 0;
+
+void opal_pci_eeh_set_evt(uint64_t phb_id)
+{
+ lock(&opal_eeh_evt_lock);
+ opal_eeh_evt |= 1ULL << phb_id;
+ opal_update_pending_evt(OPAL_EVENT_PCI_ERROR, OPAL_EVENT_PCI_ERROR);
+ unlock(&opal_eeh_evt_lock);
+}
+
+void opal_pci_eeh_clear_evt(uint64_t phb_id)
+{
+ lock(&opal_eeh_evt_lock);
+ opal_eeh_evt &= ~(1ULL << phb_id);
+ if (!opal_eeh_evt)
+ opal_update_pending_evt(OPAL_EVENT_PCI_ERROR, 0);
+ unlock(&opal_eeh_evt_lock);
+}
+
static int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number,
uint8_t *freeze_state,
uint16_t *pci_error_type,
@@ -660,8 +680,7 @@ static int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe,
return OPAL_UNSUPPORTED;
phb->ops->lock(phb);
- /* Any call to this function clears the error event */
- opal_update_pending_evt(OPAL_EVENT_PCI_ERROR, 0);
+ opal_pci_eeh_clear_evt(phb_id);
rc = phb->ops->next_error(phb, first_frozen_pe, pci_error_type,
severity);
phb->ops->unlock(phb);
OpenPOWER on IntegriCloud