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 branch 'pds_core-pci-reset'

Shannon Nelson says:

====================
pds_core: add PCI reset handling

Make sure pds_core can handle and recover from PCI function resets and
similar PCI bus issues: add detection and handlers for PCI problems.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+101 -11
+34 -9
drivers/net/ethernet/amd/pds_core/core.c
··· 445 445 goto err_out_teardown; 446 446 447 447 /* Set up the VIFs */ 448 - err = pdsc_viftypes_init(pdsc); 449 - if (err) 450 - goto err_out_teardown; 448 + if (init) { 449 + err = pdsc_viftypes_init(pdsc); 450 + if (err) 451 + goto err_out_teardown; 451 452 452 - if (init) 453 453 pdsc_debugfs_add_viftype(pdsc); 454 + } 454 455 455 456 clear_bit(PDSC_S_FW_DEAD, &pdsc->state); 456 457 return 0; ··· 470 469 pdsc_qcq_free(pdsc, &pdsc->notifyqcq); 471 470 pdsc_qcq_free(pdsc, &pdsc->adminqcq); 472 471 473 - kfree(pdsc->viftype_status); 474 - pdsc->viftype_status = NULL; 472 + if (removing) { 473 + kfree(pdsc->viftype_status); 474 + pdsc->viftype_status = NULL; 475 + } 475 476 476 477 if (pdsc->intr_info) { 477 478 for (i = 0; i < pdsc->nintrs; i++) ··· 515 512 PDS_CORE_INTR_MASK_SET); 516 513 } 517 514 518 - static void pdsc_fw_down(struct pdsc *pdsc) 515 + void pdsc_fw_down(struct pdsc *pdsc) 519 516 { 520 517 union pds_core_notifyq_comp reset_event = { 521 518 .reset.ecode = cpu_to_le16(PDS_EVENT_RESET), ··· 523 520 }; 524 521 525 522 if (test_and_set_bit(PDSC_S_FW_DEAD, &pdsc->state)) { 526 - dev_err(pdsc->dev, "%s: already happening\n", __func__); 523 + dev_warn(pdsc->dev, "%s: already happening\n", __func__); 527 524 return; 528 525 } 526 + 527 + if (pdsc->pdev->is_virtfn) 528 + return; 529 529 530 530 /* Notify clients of fw_down */ 531 531 if (pdsc->fw_reporter) ··· 539 533 pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY); 540 534 } 541 535 542 - static void pdsc_fw_up(struct pdsc *pdsc) 536 + void pdsc_fw_up(struct pdsc *pdsc) 543 537 { 544 538 union pds_core_notifyq_comp reset_event = { 545 539 .reset.ecode = cpu_to_le16(PDS_EVENT_RESET), ··· 549 543 550 544 if (!test_bit(PDSC_S_FW_DEAD, &pdsc->state)) { 551 545 dev_err(pdsc->dev, "%s: fw not dead\n", __func__); 546 + return; 547 + } 548 + 549 + if (pdsc->pdev->is_virtfn) { 550 + clear_bit(PDSC_S_FW_DEAD, &pdsc->state); 552 551 return; 553 552 } 554 553 ··· 576 565 577 566 err_out: 578 567 pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY); 568 + } 569 + 570 + static void pdsc_check_pci_health(struct pdsc *pdsc) 571 + { 572 + u8 fw_status = ioread8(&pdsc->info_regs->fw_status); 573 + 574 + /* is PCI broken? */ 575 + if (fw_status != PDS_RC_BAD_PCI) 576 + return; 577 + 578 + pdsc_reset_prepare(pdsc->pdev); 579 + pdsc_reset_done(pdsc->pdev); 579 580 } 580 581 581 582 void pdsc_health_thread(struct work_struct *work) ··· 615 592 if (!healthy) 616 593 pdsc_fw_down(pdsc); 617 594 } 595 + 596 + pdsc_check_pci_health(pdsc); 618 597 619 598 pdsc->fw_generation = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION; 620 599
+7
drivers/net/ethernet/amd/pds_core/core.h
··· 283 283 int pdsc_dev_reinit(struct pdsc *pdsc); 284 284 int pdsc_dev_init(struct pdsc *pdsc); 285 285 286 + void pdsc_reset_prepare(struct pci_dev *pdev); 287 + void pdsc_reset_done(struct pci_dev *pdev); 288 + 286 289 int pdsc_intr_alloc(struct pdsc *pdsc, char *name, 287 290 irq_handler_t handler, void *data); 288 291 void pdsc_intr_free(struct pdsc *pdsc, int index); ··· 312 309 313 310 int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw, 314 311 struct netlink_ext_ack *extack); 312 + 313 + void pdsc_fw_down(struct pdsc *pdsc); 314 + void pdsc_fw_up(struct pdsc *pdsc); 315 + 315 316 #endif /* _PDSC_H_ */
+9 -2
drivers/net/ethernet/amd/pds_core/dev.c
··· 42 42 return -ERANGE; 43 43 case PDS_RC_BAD_ADDR: 44 44 return -EFAULT; 45 + case PDS_RC_BAD_PCI: 46 + return -ENXIO; 45 47 case PDS_RC_EOPCODE: 46 48 case PDS_RC_EINTR: 47 49 case PDS_RC_DEV_CMD: ··· 64 62 /* Firmware is useful only if the running bit is set and 65 63 * fw_status != 0xff (bad PCI read) 66 64 */ 67 - return (pdsc->fw_status != 0xff) && 65 + return (pdsc->fw_status != PDS_RC_BAD_PCI) && 68 66 (pdsc->fw_status & PDS_CORE_FW_STS_F_RUNNING); 69 67 } 70 68 ··· 130 128 unsigned long max_wait; 131 129 unsigned long duration; 132 130 int timeout = 0; 131 + bool running; 133 132 int done = 0; 134 133 int err = 0; 135 134 int status; ··· 139 136 max_wait = start_time + (max_seconds * HZ); 140 137 141 138 while (!done && !timeout) { 139 + running = pdsc_is_fw_running(pdsc); 140 + if (!running) 141 + break; 142 + 142 143 done = pdsc_devcmd_done(pdsc); 143 144 if (done) 144 145 break; ··· 159 152 dev_dbg(dev, "DEVCMD %d %s after %ld secs\n", 160 153 opcode, pdsc_devcmd_str(opcode), duration / HZ); 161 154 162 - if (!done || timeout) { 155 + if ((!done || timeout) && running) { 163 156 dev_err(dev, "DEVCMD %d %s timeout, done %d timeout %d max_seconds=%d\n", 164 157 opcode, pdsc_devcmd_str(opcode), done, timeout, 165 158 max_seconds);
+50
drivers/net/ethernet/amd/pds_core/main.c
··· 445 445 devlink_free(dl); 446 446 } 447 447 448 + void pdsc_reset_prepare(struct pci_dev *pdev) 449 + { 450 + struct pdsc *pdsc = pci_get_drvdata(pdev); 451 + 452 + pdsc_fw_down(pdsc); 453 + 454 + pci_free_irq_vectors(pdev); 455 + pdsc_unmap_bars(pdsc); 456 + pci_release_regions(pdev); 457 + pci_disable_device(pdev); 458 + } 459 + 460 + void pdsc_reset_done(struct pci_dev *pdev) 461 + { 462 + struct pdsc *pdsc = pci_get_drvdata(pdev); 463 + struct device *dev = pdsc->dev; 464 + int err; 465 + 466 + err = pci_enable_device(pdev); 467 + if (err) { 468 + dev_err(dev, "Cannot enable PCI device: %pe\n", ERR_PTR(err)); 469 + return; 470 + } 471 + pci_set_master(pdev); 472 + 473 + if (!pdev->is_virtfn) { 474 + pcie_print_link_status(pdsc->pdev); 475 + 476 + err = pci_request_regions(pdsc->pdev, PDS_CORE_DRV_NAME); 477 + if (err) { 478 + dev_err(pdsc->dev, "Cannot request PCI regions: %pe\n", 479 + ERR_PTR(err)); 480 + return; 481 + } 482 + 483 + err = pdsc_map_bars(pdsc); 484 + if (err) 485 + return; 486 + } 487 + 488 + pdsc_fw_up(pdsc); 489 + } 490 + 491 + static const struct pci_error_handlers pdsc_err_handler = { 492 + /* FLR handling */ 493 + .reset_prepare = pdsc_reset_prepare, 494 + .reset_done = pdsc_reset_done, 495 + }; 496 + 448 497 static struct pci_driver pdsc_driver = { 449 498 .name = PDS_CORE_DRV_NAME, 450 499 .id_table = pdsc_id_table, 451 500 .probe = pdsc_probe, 452 501 .remove = pdsc_remove, 453 502 .sriov_configure = pdsc_sriov_configure, 503 + .err_handler = &pdsc_err_handler, 454 504 }; 455 505 456 506 void *pdsc_get_pf_struct(struct pci_dev *vf_pdev)
+1
include/linux/pds/pds_core_if.h
··· 79 79 PDS_RC_EVFID = 31, /* VF ID does not exist */ 80 80 PDS_RC_BAD_FW = 32, /* FW file is invalid or corrupted */ 81 81 PDS_RC_ECLIENT = 33, /* No such client id */ 82 + PDS_RC_BAD_PCI = 255, /* Broken PCI when reading status */ 82 83 }; 83 84 84 85 /**