diff options
author | Keith Busch <keith.busch@intel.com> | 2018-07-16 18:05:02 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2018-07-19 17:21:01 -0400 |
commit | 0c27e28f77179548aa3d25a8f7a3dda22fd3e080 (patch) | |
tree | 5a4e4361328fb220d8910d6d6283f967025df083 | |
parent | f8d46c89c86fa11c60c05e101a3a4c7458623103 (diff) |
PCI/DPC: Defer event handling to work queue
Move all event handling to the existing work queue, which will
make it simpler to pass event information to the handler.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Sinan Kaya <okaya@kernel.org>
Reviewed-by: Oza Pawandeep <poza@codeaurora.org>
-rw-r--r-- | drivers/pci/pcie/dpc.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 972aac892846..5f5fac279c75 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c | |||
@@ -108,14 +108,6 @@ static pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) | |||
108 | return PCI_ERS_RESULT_RECOVERED; | 108 | return PCI_ERS_RESULT_RECOVERED; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void dpc_work(struct work_struct *work) | ||
112 | { | ||
113 | struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); | ||
114 | struct pci_dev *pdev = dpc->dev->port; | ||
115 | |||
116 | /* We configure DPC so it only triggers on ERR_FATAL */ | ||
117 | pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); | ||
118 | } | ||
119 | 111 | ||
120 | static void dpc_process_rp_pio_error(struct dpc_dev *dpc) | 112 | static void dpc_process_rp_pio_error(struct dpc_dev *dpc) |
121 | { | 113 | { |
@@ -174,33 +166,21 @@ static void dpc_process_rp_pio_error(struct dpc_dev *dpc) | |||
174 | } | 166 | } |
175 | } | 167 | } |
176 | 168 | ||
177 | static irqreturn_t dpc_irq(int irq, void *context) | 169 | static void dpc_work(struct work_struct *work) |
178 | { | 170 | { |
179 | struct dpc_dev *dpc = (struct dpc_dev *)context; | 171 | struct dpc_dev *dpc = container_of(work, struct dpc_dev, work); |
180 | struct pci_dev *pdev = dpc->dev->port; | 172 | struct pci_dev *pdev = dpc->dev->port; |
181 | struct device *dev = &dpc->dev->device; | 173 | struct device *dev = &dpc->dev->device; |
182 | u16 cap = dpc->cap_pos, status, source, reason, ext_reason; | 174 | u16 cap = dpc->cap_pos, status, source, reason, ext_reason; |
183 | 175 | ||
184 | pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); | 176 | pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); |
185 | 177 | pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source); | |
186 | if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0)) | ||
187 | return IRQ_NONE; | ||
188 | |||
189 | if (!(status & PCI_EXP_DPC_STATUS_TRIGGER)) { | ||
190 | pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, | ||
191 | PCI_EXP_DPC_STATUS_INTERRUPT); | ||
192 | return IRQ_HANDLED; | ||
193 | } | ||
194 | |||
195 | pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, | ||
196 | &source); | ||
197 | 178 | ||
198 | dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n", | 179 | dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n", |
199 | status, source); | 180 | status, source); |
200 | 181 | ||
201 | reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; | 182 | reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; |
202 | ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; | 183 | ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; |
203 | |||
204 | dev_warn(dev, "DPC %s detected, remove downstream devices\n", | 184 | dev_warn(dev, "DPC %s detected, remove downstream devices\n", |
205 | (reason == 0) ? "unmasked uncorrectable error" : | 185 | (reason == 0) ? "unmasked uncorrectable error" : |
206 | (reason == 1) ? "ERR_NONFATAL" : | 186 | (reason == 1) ? "ERR_NONFATAL" : |
@@ -208,10 +188,26 @@ static irqreturn_t dpc_irq(int irq, void *context) | |||
208 | (ext_reason == 0) ? "RP PIO error" : | 188 | (ext_reason == 0) ? "RP PIO error" : |
209 | (ext_reason == 1) ? "software trigger" : | 189 | (ext_reason == 1) ? "software trigger" : |
210 | "reserved error"); | 190 | "reserved error"); |
191 | |||
211 | /* show RP PIO error detail information */ | 192 | /* show RP PIO error detail information */ |
212 | if (dpc->rp_extensions && reason == 3 && ext_reason == 0) | 193 | if (dpc->rp_extensions && reason == 3 && ext_reason == 0) |
213 | dpc_process_rp_pio_error(dpc); | 194 | dpc_process_rp_pio_error(dpc); |
214 | 195 | ||
196 | /* We configure DPC so it only triggers on ERR_FATAL */ | ||
197 | pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_DPC); | ||
198 | } | ||
199 | |||
200 | static irqreturn_t dpc_irq(int irq, void *context) | ||
201 | { | ||
202 | struct dpc_dev *dpc = (struct dpc_dev *)context; | ||
203 | struct pci_dev *pdev = dpc->dev->port; | ||
204 | u16 cap = dpc->cap_pos, status; | ||
205 | |||
206 | pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); | ||
207 | |||
208 | if (!(status & PCI_EXP_DPC_STATUS_INTERRUPT) || status == (u16)(~0)) | ||
209 | return IRQ_NONE; | ||
210 | |||
215 | pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, | 211 | pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, |
216 | PCI_EXP_DPC_STATUS_INTERRUPT); | 212 | PCI_EXP_DPC_STATUS_INTERRUPT); |
217 | if (status & PCI_EXP_DPC_STATUS_TRIGGER) | 213 | if (status & PCI_EXP_DPC_STATUS_TRIGGER) |