Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 's390-6.16-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Alexander Gordeev:

- Fix PCI error recovery and bring it in line with AER/EEH

* tag 's390-6.16-4' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/pci: Allow automatic recovery with minimal driver support
s390/pci: Do not try re-enabling load/store if device is disabled
s390/pci: Fix stale function handles in error handling

+44 -15
+44 -15
arch/s390/pci/pci_event.c
··· 54 54 case PCI_ERS_RESULT_CAN_RECOVER: 55 55 case PCI_ERS_RESULT_RECOVERED: 56 56 case PCI_ERS_RESULT_NEED_RESET: 57 + case PCI_ERS_RESULT_NONE: 57 58 return false; 58 59 default: 59 60 return true; ··· 78 77 if (!driver || !driver->err_handler) 79 78 return false; 80 79 if (!driver->err_handler->error_detected) 81 - return false; 82 - if (!driver->err_handler->slot_reset) 83 - return false; 84 - if (!driver->err_handler->resume) 85 80 return false; 86 81 return true; 87 82 } ··· 103 106 struct zpci_dev *zdev = to_zpci(pdev); 104 107 int rc; 105 108 109 + /* The underlying device may have been disabled by the event */ 110 + if (!zdev_enabled(zdev)) 111 + return PCI_ERS_RESULT_NEED_RESET; 112 + 106 113 pr_info("%s: Unblocking device access for examination\n", pci_name(pdev)); 107 114 rc = zpci_reset_load_store_blocked(zdev); 108 115 if (rc) { ··· 115 114 return PCI_ERS_RESULT_NEED_RESET; 116 115 } 117 116 118 - if (driver->err_handler->mmio_enabled) { 117 + if (driver->err_handler->mmio_enabled) 119 118 ers_res = driver->err_handler->mmio_enabled(pdev); 120 - if (ers_result_indicates_abort(ers_res)) { 121 - pr_info("%s: Automatic recovery failed after MMIO re-enable\n", 122 - pci_name(pdev)); 123 - return ers_res; 124 - } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { 125 - pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); 126 - return ers_res; 127 - } 119 + else 120 + ers_res = PCI_ERS_RESULT_NONE; 121 + 122 + if (ers_result_indicates_abort(ers_res)) { 123 + pr_info("%s: Automatic recovery failed after MMIO re-enable\n", 124 + pci_name(pdev)); 125 + return ers_res; 126 + } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { 127 + pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); 128 + return ers_res; 128 129 } 129 130 130 131 pr_debug("%s: Unblocking DMA\n", pci_name(pdev)); ··· 153 150 return ers_res; 154 151 } 155 152 pdev->error_state = pci_channel_io_normal; 156 - ers_res = driver->err_handler->slot_reset(pdev); 153 + 154 + if (driver->err_handler->slot_reset) 155 + ers_res = driver->err_handler->slot_reset(pdev); 156 + else 157 + ers_res = PCI_ERS_RESULT_NONE; 158 + 157 159 if (ers_result_indicates_abort(ers_res)) { 158 160 pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev)); 159 161 return ers_res; ··· 222 214 goto out_unlock; 223 215 } 224 216 225 - if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) { 217 + if (ers_res != PCI_ERS_RESULT_NEED_RESET) { 226 218 ers_res = zpci_event_do_error_state_clear(pdev, driver); 227 219 if (ers_result_indicates_abort(ers_res)) { 228 220 status_str = "failed (abort on MMIO enable)"; ··· 232 224 233 225 if (ers_res == PCI_ERS_RESULT_NEED_RESET) 234 226 ers_res = zpci_event_do_reset(pdev, driver); 227 + 228 + /* 229 + * ers_res can be PCI_ERS_RESULT_NONE either because the driver 230 + * decided to return it, indicating that it abstains from voting 231 + * on how to recover, or because it didn't implement the callback. 232 + * Both cases assume, that if there is nothing else causing a 233 + * disconnect, we recovered successfully. 234 + */ 235 + if (ers_res == PCI_ERS_RESULT_NONE) 236 + ers_res = PCI_ERS_RESULT_RECOVERED; 235 237 236 238 if (ers_res != PCI_ERS_RESULT_RECOVERED) { 237 239 pr_err("%s: Automatic recovery failed; operator intervention is required\n", ··· 291 273 struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); 292 274 struct pci_dev *pdev = NULL; 293 275 pci_ers_result_t ers_res; 276 + u32 fh = 0; 277 + int rc; 294 278 295 279 zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", 296 280 ccdf->fid, ccdf->fh, ccdf->pec); ··· 301 281 302 282 if (zdev) { 303 283 mutex_lock(&zdev->state_lock); 284 + rc = clp_refresh_fh(zdev->fid, &fh); 285 + if (rc) 286 + goto no_pdev; 287 + if (!fh || ccdf->fh != fh) { 288 + /* Ignore events with stale handles */ 289 + zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n", 290 + ccdf->fid, fh, ccdf->fh); 291 + goto no_pdev; 292 + } 304 293 zpci_update_fh(zdev, ccdf->fh); 305 294 if (zdev->zbus->bus) 306 295 pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);