Skip to content

Commit 4553792

Browse files
niklas88Alexander Gordeev
authored andcommitted
s390/pci: Fix stale function handles in error handling
The error event information for PCI error events contains a function handle for the respective function. This handle is generally captured at the time the error event was recorded. Due to delays in processing or cascading issues, it may happen that during firmware recovery multiple events are generated. When processing these events in order Linux may already have recovered an affected function making the event information stale. Fix this by doing an unconditional CLP List PCI function retrieving the current function handle with the zdev->state_lock held and ignoring the event if its function handle is stale. Cc: [email protected] Fixes: 4cdf2f4 ("s390/pci: implement minimal PCI error recovery") Reviewed-by: Julian Ruess <[email protected]> Reviewed-by: Gerd Bayer <[email protected]> Reviewed-by: Farhan Ali <[email protected]> Signed-off-by: Niklas Schnelle <[email protected]> Signed-off-by: Alexander Gordeev <[email protected]>
1 parent 7f8073c commit 4553792

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

arch/s390/pci/pci_event.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
273273
struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
274274
struct pci_dev *pdev = NULL;
275275
pci_ers_result_t ers_res;
276+
u32 fh = 0;
277+
int rc;
276278

277279
zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n",
278280
ccdf->fid, ccdf->fh, ccdf->pec);
@@ -281,6 +283,15 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
281283

282284
if (zdev) {
283285
mutex_lock(&zdev->state_lock);
286+
rc = clp_refresh_fh(zdev->fid, &fh);
287+
if (rc)
288+
goto no_pdev;
289+
if (!fh || ccdf->fh != fh) {
290+
/* Ignore events with stale handles */
291+
zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n",
292+
ccdf->fid, fh, ccdf->fh);
293+
goto no_pdev;
294+
}
284295
zpci_update_fh(zdev, ccdf->fh);
285296
if (zdev->zbus->bus)
286297
pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);

0 commit comments

Comments
 (0)