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

Merge tag 'powerpc-6.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Madhavan Srinivasan:

- Fixes for several issues in the powernv PCI hotplug path

- Fix htmldoc generation for htm.rst in toctree

- Add jit support for load_acquire and store_release in ppc64 bpf jit

Thanks to Bjorn Helgaas, Hari Bathini, Puranjay Mohan, Saket Kumar
Bhaskar, Shawn Anastasio, Timothy Pearson, and Vishal Parmar

* tag 'powerpc-6.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc64/bpf: Add jit support for load_acquire and store_release
docs: powerpc: add htm.rst to toctree
PCI: pnv_php: Enable third attention indicator state
PCI: pnv_php: Fix surprise plug detection and recovery
powerpc/eeh: Make EEH driver device hotplug safe
powerpc/eeh: Export eeh_unfreeze_pe()
PCI: pnv_php: Work around switches with broken presence detection
PCI: pnv_php: Clean up allocated IRQs on unplug

+353 -45
+1
arch/powerpc/include/asm/ppc-opcode.h
··· 425 425 #define PPC_RAW_SC() (0x44000002) 426 426 #define PPC_RAW_SYNC() (0x7c0004ac) 427 427 #define PPC_RAW_ISYNC() (0x4c00012c) 428 + #define PPC_RAW_LWSYNC() (0x7c2004ac) 428 429 429 430 /* 430 431 * Define what the VSX XX1 form instructions will look like, then add
+1
arch/powerpc/kernel/eeh.c
··· 1139 1139 1140 1140 return ret; 1141 1141 } 1142 + EXPORT_SYMBOL_GPL(eeh_unfreeze_pe); 1142 1143 1143 1144 1144 1145 static struct pci_device_id eeh_reset_ids[] = {
+32 -16
arch/powerpc/kernel/eeh_driver.c
··· 257 257 struct pci_driver *driver; 258 258 enum pci_ers_result new_result; 259 259 260 - pci_lock_rescan_remove(); 261 260 pdev = edev->pdev; 262 261 if (pdev) 263 262 get_device(&pdev->dev); 264 - pci_unlock_rescan_remove(); 265 263 if (!pdev) { 266 264 eeh_edev_info(edev, "no device"); 265 + *result = PCI_ERS_RESULT_DISCONNECT; 267 266 return; 268 267 } 269 268 device_lock(&pdev->dev); ··· 303 304 struct eeh_dev *edev, *tmp; 304 305 305 306 pr_info("EEH: Beginning: '%s'\n", name); 306 - eeh_for_each_pe(root, pe) eeh_pe_for_each_dev(pe, edev, tmp) 307 - eeh_pe_report_edev(edev, fn, result); 307 + eeh_for_each_pe(root, pe) 308 + eeh_pe_for_each_dev(pe, edev, tmp) 309 + eeh_pe_report_edev(edev, fn, result); 308 310 if (result) 309 311 pr_info("EEH: Finished:'%s' with aggregate recovery state:'%s'\n", 310 312 name, pci_ers_result_name(*result)); ··· 383 383 if (!edev) 384 384 return; 385 385 386 + pci_lock_rescan_remove(); 387 + 386 388 /* 387 389 * The content in the config space isn't saved because 388 390 * the blocked config space on some adapters. We have ··· 395 393 if (list_is_last(&edev->entry, &edev->pe->edevs)) 396 394 eeh_pe_restore_bars(edev->pe); 397 395 396 + pci_unlock_rescan_remove(); 398 397 return; 399 398 } 400 399 401 400 pdev = eeh_dev_to_pci_dev(edev); 402 - if (!pdev) 401 + if (!pdev) { 402 + pci_unlock_rescan_remove(); 403 403 return; 404 + } 404 405 405 406 pci_restore_state(pdev); 407 + 408 + pci_unlock_rescan_remove(); 406 409 } 407 410 408 411 /** ··· 654 647 if (any_passed || driver_eeh_aware || (pe->type & EEH_PE_VF)) { 655 648 eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data); 656 649 } else { 657 - pci_lock_rescan_remove(); 658 650 pci_hp_remove_devices(bus); 659 - pci_unlock_rescan_remove(); 660 651 } 661 652 662 653 /* ··· 670 665 if (rc) 671 666 return rc; 672 667 673 - pci_lock_rescan_remove(); 674 - 675 668 /* Restore PE */ 676 669 eeh_ops->configure_bridge(pe); 677 670 eeh_pe_restore_bars(pe); ··· 677 674 /* Clear frozen state */ 678 675 rc = eeh_clear_pe_frozen_state(pe, false); 679 676 if (rc) { 680 - pci_unlock_rescan_remove(); 681 677 return rc; 682 678 } 683 679 ··· 711 709 pe->tstamp = tstamp; 712 710 pe->freeze_count = cnt; 713 711 714 - pci_unlock_rescan_remove(); 715 712 return 0; 716 713 } 717 714 ··· 844 843 {LIST_HEAD_INIT(rmv_data.removed_vf_list), 0}; 845 844 int devices = 0; 846 845 846 + pci_lock_rescan_remove(); 847 + 847 848 bus = eeh_pe_bus_get(pe); 848 849 if (!bus) { 849 850 pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n", 850 851 __func__, pe->phb->global_number, pe->addr); 852 + pci_unlock_rescan_remove(); 851 853 return; 852 854 } 853 855 ··· 1098 1094 eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true); 1099 1095 eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); 1100 1096 1101 - pci_lock_rescan_remove(); 1102 - pci_hp_remove_devices(bus); 1103 - pci_unlock_rescan_remove(); 1097 + bus = eeh_pe_bus_get(pe); 1098 + if (bus) 1099 + pci_hp_remove_devices(bus); 1100 + else 1101 + pr_err("%s: PCI bus for PHB#%x-PE#%x disappeared\n", 1102 + __func__, pe->phb->global_number, pe->addr); 1103 + 1104 1104 /* The passed PE should no longer be used */ 1105 + pci_unlock_rescan_remove(); 1105 1106 return; 1106 1107 } 1107 1108 ··· 1123 1114 eeh_clear_slot_attention(edev->pdev); 1124 1115 1125 1116 eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true); 1117 + 1118 + pci_unlock_rescan_remove(); 1126 1119 } 1127 1120 1128 1121 /** ··· 1143 1132 unsigned long flags; 1144 1133 int rc; 1145 1134 1135 + pci_lock_rescan_remove(); 1146 1136 1147 1137 do { 1148 1138 rc = eeh_ops->next_error(&pe); ··· 1183 1171 1184 1172 break; 1185 1173 case EEH_NEXT_ERR_NONE: 1174 + pci_unlock_rescan_remove(); 1186 1175 return; 1187 1176 default: 1188 1177 pr_warn("%s: Invalid value %d from next_error()\n", 1189 1178 __func__, rc); 1179 + pci_unlock_rescan_remove(); 1190 1180 return; 1191 1181 } 1192 1182 ··· 1200 1186 if (rc == EEH_NEXT_ERR_FROZEN_PE || 1201 1187 rc == EEH_NEXT_ERR_FENCED_PHB) { 1202 1188 eeh_pe_state_mark(pe, EEH_PE_RECOVERING); 1189 + pci_unlock_rescan_remove(); 1203 1190 eeh_handle_normal_event(pe); 1191 + pci_lock_rescan_remove(); 1204 1192 } else { 1205 1193 eeh_for_each_pe(pe, tmp_pe) 1206 1194 eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev) ··· 1215 1199 eeh_report_failure, NULL); 1216 1200 eeh_set_channel_state(pe, pci_channel_io_perm_failure); 1217 1201 1218 - pci_lock_rescan_remove(); 1219 1202 list_for_each_entry(hose, &hose_list, list_node) { 1220 1203 phb_pe = eeh_phb_pe_get(hose); 1221 1204 if (!phb_pe || ··· 1233 1218 } 1234 1219 pci_hp_remove_devices(bus); 1235 1220 } 1236 - pci_unlock_rescan_remove(); 1237 1221 } 1238 1222 1239 1223 /* ··· 1242 1228 if (rc == EEH_NEXT_ERR_DEAD_IOC) 1243 1229 break; 1244 1230 } while (rc != EEH_NEXT_ERR_NONE); 1231 + 1232 + pci_unlock_rescan_remove(); 1245 1233 }
+6 -4
arch/powerpc/kernel/eeh_pe.c
··· 671 671 eeh_ops->write_config(edev, cap + PCI_EXP_LNKCTL, 2, val); 672 672 673 673 /* Check link */ 674 - if (!edev->pdev->link_active_reporting) { 675 - eeh_edev_dbg(edev, "No link reporting capability\n"); 676 - msleep(1000); 677 - return; 674 + if (edev->pdev) { 675 + if (!edev->pdev->link_active_reporting) { 676 + eeh_edev_dbg(edev, "No link reporting capability\n"); 677 + msleep(1000); 678 + return; 679 + } 678 680 } 679 681 680 682 /* Wait the link is up until timeout (5s) */
+3
arch/powerpc/kernel/pci-hotplug.c
··· 141 141 struct pci_controller *phb; 142 142 struct device_node *dn = pci_bus_to_OF_node(bus); 143 143 144 + if (!dn) 145 + return; 146 + 144 147 phb = pci_bus_to_host(bus); 145 148 146 149 mode = PCI_PROBE_NORMAL;
+82
arch/powerpc/net/bpf_jit_comp64.c
··· 409 409 " blr ;" 410 410 ); 411 411 412 + static int emit_atomic_ld_st(const struct bpf_insn insn, struct codegen_context *ctx, u32 *image) 413 + { 414 + u32 code = insn.code; 415 + u32 dst_reg = bpf_to_ppc(insn.dst_reg); 416 + u32 src_reg = bpf_to_ppc(insn.src_reg); 417 + u32 size = BPF_SIZE(code); 418 + u32 tmp1_reg = bpf_to_ppc(TMP_REG_1); 419 + u32 tmp2_reg = bpf_to_ppc(TMP_REG_2); 420 + s16 off = insn.off; 421 + s32 imm = insn.imm; 422 + 423 + switch (imm) { 424 + case BPF_LOAD_ACQ: 425 + switch (size) { 426 + case BPF_B: 427 + EMIT(PPC_RAW_LBZ(dst_reg, src_reg, off)); 428 + break; 429 + case BPF_H: 430 + EMIT(PPC_RAW_LHZ(dst_reg, src_reg, off)); 431 + break; 432 + case BPF_W: 433 + EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); 434 + break; 435 + case BPF_DW: 436 + if (off % 4) { 437 + EMIT(PPC_RAW_LI(tmp1_reg, off)); 438 + EMIT(PPC_RAW_LDX(dst_reg, src_reg, tmp1_reg)); 439 + } else { 440 + EMIT(PPC_RAW_LD(dst_reg, src_reg, off)); 441 + } 442 + break; 443 + } 444 + EMIT(PPC_RAW_LWSYNC()); 445 + break; 446 + case BPF_STORE_REL: 447 + EMIT(PPC_RAW_LWSYNC()); 448 + switch (size) { 449 + case BPF_B: 450 + EMIT(PPC_RAW_STB(src_reg, dst_reg, off)); 451 + break; 452 + case BPF_H: 453 + EMIT(PPC_RAW_STH(src_reg, dst_reg, off)); 454 + break; 455 + case BPF_W: 456 + EMIT(PPC_RAW_STW(src_reg, dst_reg, off)); 457 + break; 458 + case BPF_DW: 459 + if (off % 4) { 460 + EMIT(PPC_RAW_LI(tmp2_reg, off)); 461 + EMIT(PPC_RAW_STDX(src_reg, dst_reg, tmp2_reg)); 462 + } else { 463 + EMIT(PPC_RAW_STD(src_reg, dst_reg, off)); 464 + } 465 + break; 466 + } 467 + break; 468 + default: 469 + pr_err_ratelimited("unexpected atomic load/store op code %02x\n", 470 + imm); 471 + return -EINVAL; 472 + } 473 + 474 + return 0; 475 + } 476 + 412 477 /* Assemble the body code between the prologue & epilogue */ 413 478 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, 414 479 u32 *addrs, int pass, bool extra_pass) ··· 963 898 /* 964 899 * BPF_STX ATOMIC (atomic ops) 965 900 */ 901 + case BPF_STX | BPF_ATOMIC | BPF_B: 902 + case BPF_STX | BPF_ATOMIC | BPF_H: 966 903 case BPF_STX | BPF_ATOMIC | BPF_W: 967 904 case BPF_STX | BPF_ATOMIC | BPF_DW: 905 + if (bpf_atomic_is_load_store(&insn[i])) { 906 + ret = emit_atomic_ld_st(insn[i], ctx, image); 907 + if (ret) 908 + return ret; 909 + 910 + if (size != BPF_DW && insn_is_zext(&insn[i + 1])) 911 + addrs[++i] = ctx->idx * 4; 912 + break; 913 + } else if (size == BPF_B || size == BPF_H) { 914 + pr_err_ratelimited( 915 + "eBPF filter atomic op code %02x (@%d) unsupported\n", 916 + code, i); 917 + return -EOPNOTSUPP; 918 + } 919 + 968 920 save_reg = tmp2_reg; 969 921 ret_reg = src_reg; 970 922
+226 -24
drivers/pci/hotplug/pnv_php.c
··· 3 3 * PCI Hotplug Driver for PowerPC PowerNV platform. 4 4 * 5 5 * Copyright Gavin Shan, IBM Corporation 2016. 6 + * Copyright (C) 2025 Raptor Engineering, LLC 7 + * Copyright (C) 2025 Raptor Computing Systems, LLC 6 8 */ 7 9 8 10 #include <linux/bitfield.h> 9 11 #include <linux/libfdt.h> 10 12 #include <linux/module.h> 11 13 #include <linux/pci.h> 14 + #include <linux/delay.h> 12 15 #include <linux/pci_hotplug.h> 13 16 #include <linux/of_fdt.h> 14 17 ··· 39 36 static void pnv_php_unregister_one(struct device_node *dn); 40 37 static void pnv_php_unregister(struct device_node *dn); 41 38 39 + static void pnv_php_enable_irq(struct pnv_php_slot *php_slot); 40 + 42 41 static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, 43 - bool disable_device) 42 + bool disable_device, bool disable_msi) 44 43 { 45 44 struct pci_dev *pdev = php_slot->pdev; 46 45 u16 ctrl; ··· 58 53 php_slot->irq = 0; 59 54 } 60 55 61 - if (php_slot->wq) { 62 - destroy_workqueue(php_slot->wq); 63 - php_slot->wq = NULL; 64 - } 65 - 66 - if (disable_device) { 56 + if (disable_device || disable_msi) { 67 57 if (pdev->msix_enabled) 68 58 pci_disable_msix(pdev); 69 59 else if (pdev->msi_enabled) 70 60 pci_disable_msi(pdev); 71 - 72 - pci_disable_device(pdev); 73 61 } 62 + 63 + if (disable_device) 64 + pci_disable_device(pdev); 74 65 } 75 66 76 67 static void pnv_php_free_slot(struct kref *kref) ··· 75 74 struct pnv_php_slot, kref); 76 75 77 76 WARN_ON(!list_empty(&php_slot->children)); 78 - pnv_php_disable_irq(php_slot, false); 77 + pnv_php_disable_irq(php_slot, false, false); 78 + destroy_workqueue(php_slot->wq); 79 79 kfree(php_slot->name); 80 80 kfree(php_slot); 81 81 } ··· 393 391 return 0; 394 392 } 395 393 394 + static int pcie_check_link_active(struct pci_dev *pdev) 395 + { 396 + u16 lnk_status; 397 + int ret; 398 + 399 + ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); 400 + if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) 401 + return -ENODEV; 402 + 403 + ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); 404 + 405 + return ret; 406 + } 407 + 396 408 static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state) 397 409 { 398 410 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); ··· 419 403 */ 420 404 ret = pnv_pci_get_presence_state(php_slot->id, &presence); 421 405 if (ret >= 0) { 406 + if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM && 407 + presence == OPAL_PCI_SLOT_EMPTY) { 408 + /* 409 + * Similar to pciehp_hpc, check whether the Link Active 410 + * bit is set to account for broken downstream bridges 411 + * that don't properly assert Presence Detect State, as 412 + * was observed on the Microsemi Switchtec PM8533 PFX 413 + * [11f8:8533]. 414 + */ 415 + if (pcie_check_link_active(php_slot->pdev) > 0) 416 + presence = OPAL_PCI_SLOT_PRESENT; 417 + } 418 + 422 419 *state = presence; 423 420 ret = 0; 424 421 } else { ··· 441 412 return ret; 442 413 } 443 414 415 + static int pnv_php_get_raw_indicator_status(struct hotplug_slot *slot, u8 *state) 416 + { 417 + struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); 418 + struct pci_dev *bridge = php_slot->pdev; 419 + u16 status; 420 + 421 + pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status); 422 + *state = (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; 423 + return 0; 424 + } 425 + 426 + 444 427 static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *state) 445 428 { 446 429 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); 447 430 431 + pnv_php_get_raw_indicator_status(slot, &php_slot->attention_state); 448 432 *state = php_slot->attention_state; 449 433 return 0; 450 434 } ··· 475 433 mask = PCI_EXP_SLTCTL_AIC; 476 434 477 435 if (state) 478 - new = PCI_EXP_SLTCTL_ATTN_IND_ON; 436 + new = FIELD_PREP(PCI_EXP_SLTCTL_AIC, state); 479 437 else 480 438 new = PCI_EXP_SLTCTL_ATTN_IND_OFF; 481 439 482 440 pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new); 483 441 484 442 return 0; 443 + } 444 + 445 + static int pnv_php_activate_slot(struct pnv_php_slot *php_slot, 446 + struct hotplug_slot *slot) 447 + { 448 + int ret, i; 449 + 450 + /* 451 + * Issue initial slot activation command to firmware 452 + * 453 + * Firmware will power slot on, attempt to train the link, and 454 + * discover any downstream devices. If this process fails, firmware 455 + * will return an error code and an invalid device tree. Failure 456 + * can be caused for multiple reasons, including a faulty 457 + * downstream device, poor connection to the downstream device, or 458 + * a previously latched PHB fence. On failure, issue fundamental 459 + * reset up to three times before aborting. 460 + */ 461 + ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON); 462 + if (ret) { 463 + SLOT_WARN( 464 + php_slot, 465 + "PCI slot activation failed with error code %d, possible frozen PHB", 466 + ret); 467 + SLOT_WARN( 468 + php_slot, 469 + "Attempting complete PHB reset before retrying slot activation\n"); 470 + for (i = 0; i < 3; i++) { 471 + /* 472 + * Slot activation failed, PHB may be fenced from a 473 + * prior device failure. 474 + * 475 + * Use the OPAL fundamental reset call to both try a 476 + * device reset and clear any potentially active PHB 477 + * fence / freeze. 478 + */ 479 + SLOT_WARN(php_slot, "Try %d...\n", i + 1); 480 + pci_set_pcie_reset_state(php_slot->pdev, 481 + pcie_warm_reset); 482 + msleep(250); 483 + pci_set_pcie_reset_state(php_slot->pdev, 484 + pcie_deassert_reset); 485 + 486 + ret = pnv_php_set_slot_power_state( 487 + slot, OPAL_PCI_SLOT_POWER_ON); 488 + if (!ret) 489 + break; 490 + } 491 + 492 + if (i >= 3) 493 + SLOT_WARN(php_slot, 494 + "Failed to bring slot online, aborting!\n"); 495 + } 496 + 497 + return ret; 485 498 } 486 499 487 500 static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan) ··· 601 504 goto scan; 602 505 603 506 /* Power is off, turn it on and then scan the slot */ 604 - ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON); 507 + ret = pnv_php_activate_slot(php_slot, slot); 605 508 if (ret) 606 509 return ret; 607 510 ··· 658 561 static int pnv_php_enable_slot(struct hotplug_slot *slot) 659 562 { 660 563 struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); 564 + u32 prop32; 565 + int ret; 661 566 662 - return pnv_php_enable(php_slot, true); 567 + ret = pnv_php_enable(php_slot, true); 568 + if (ret) 569 + return ret; 570 + 571 + /* (Re-)enable interrupt if the slot supports surprise hotplug */ 572 + ret = of_property_read_u32(php_slot->dn, "ibm,slot-surprise-pluggable", 573 + &prop32); 574 + if (!ret && prop32) 575 + pnv_php_enable_irq(php_slot); 576 + 577 + return 0; 578 + } 579 + 580 + /* 581 + * Disable any hotplug interrupts for all slots on the provided bus, as well as 582 + * all downstream slots in preparation for a hot unplug. 583 + */ 584 + static int pnv_php_disable_all_irqs(struct pci_bus *bus) 585 + { 586 + struct pci_bus *child_bus; 587 + struct pci_slot *slot; 588 + 589 + /* First go down child buses */ 590 + list_for_each_entry(child_bus, &bus->children, node) 591 + pnv_php_disable_all_irqs(child_bus); 592 + 593 + /* Disable IRQs for all pnv_php slots on this bus */ 594 + list_for_each_entry(slot, &bus->slots, list) { 595 + struct pnv_php_slot *php_slot = to_pnv_php_slot(slot->hotplug); 596 + 597 + pnv_php_disable_irq(php_slot, false, true); 598 + } 599 + 600 + return 0; 601 + } 602 + 603 + /* 604 + * Disable any hotplug interrupts for all downstream slots on the provided 605 + * bus in preparation for a hot unplug. 606 + */ 607 + static int pnv_php_disable_all_downstream_irqs(struct pci_bus *bus) 608 + { 609 + struct pci_bus *child_bus; 610 + 611 + /* Go down child buses, recursively deactivating their IRQs */ 612 + list_for_each_entry(child_bus, &bus->children, node) 613 + pnv_php_disable_all_irqs(child_bus); 614 + 615 + return 0; 663 616 } 664 617 665 618 static int pnv_php_disable_slot(struct hotplug_slot *slot) ··· 725 578 if (php_slot->state != PNV_PHP_STATE_POPULATED && 726 579 php_slot->state != PNV_PHP_STATE_REGISTERED) 727 580 return 0; 581 + 582 + /* 583 + * Free all IRQ resources from all child slots before remove. 584 + * Note that we do not disable the root slot IRQ here as that 585 + * would also deactivate the slot hot (re)plug interrupt! 586 + */ 587 + pnv_php_disable_all_downstream_irqs(php_slot->bus); 728 588 729 589 /* Remove all devices behind the slot */ 730 590 pci_lock_rescan_remove(); ··· 797 643 798 644 php_slot->name = kstrdup(label, GFP_KERNEL); 799 645 if (!php_slot->name) { 646 + kfree(php_slot); 647 + return NULL; 648 + } 649 + 650 + /* Allocate workqueue for this slot's interrupt handling */ 651 + php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name); 652 + if (!php_slot->wq) { 653 + SLOT_WARN(php_slot, "Cannot alloc workqueue\n"); 654 + kfree(php_slot->name); 800 655 kfree(php_slot); 801 656 return NULL; 802 657 } ··· 908 745 return entry.vector; 909 746 } 910 747 748 + static void 749 + pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot) 750 + { 751 + struct pci_dev *pdev = php_slot->pdev; 752 + struct eeh_dev *edev; 753 + struct eeh_pe *pe; 754 + int i, rc; 755 + 756 + /* 757 + * When a device is surprise removed from a downstream bridge slot, 758 + * the upstream bridge port can still end up frozen due to related EEH 759 + * events, which will in turn block the MSI interrupts for slot hotplug 760 + * detection. 761 + * 762 + * Detect and thaw any frozen upstream PE after slot deactivation. 763 + */ 764 + edev = pci_dev_to_eeh_dev(pdev); 765 + pe = edev ? edev->pe : NULL; 766 + rc = eeh_pe_get_state(pe); 767 + if ((rc == -ENODEV) || (rc == -ENOENT)) { 768 + SLOT_WARN( 769 + php_slot, 770 + "Upstream bridge PE state unknown, hotplug detect may fail\n"); 771 + } else { 772 + if (pe->state & EEH_PE_ISOLATED) { 773 + SLOT_WARN( 774 + php_slot, 775 + "Upstream bridge PE %02x frozen, thawing...\n", 776 + pe->addr); 777 + for (i = 0; i < 3; i++) 778 + if (!eeh_unfreeze_pe(pe)) 779 + break; 780 + if (i >= 3) 781 + SLOT_WARN( 782 + php_slot, 783 + "Unable to thaw PE %02x, hotplug detect will fail!\n", 784 + pe->addr); 785 + else 786 + SLOT_WARN(php_slot, 787 + "PE %02x thawed successfully\n", 788 + pe->addr); 789 + } 790 + } 791 + } 792 + 911 793 static void pnv_php_event_handler(struct work_struct *work) 912 794 { 913 795 struct pnv_php_event *event = 914 796 container_of(work, struct pnv_php_event, work); 915 797 struct pnv_php_slot *php_slot = event->php_slot; 916 798 917 - if (event->added) 799 + if (event->added) { 918 800 pnv_php_enable_slot(&php_slot->slot); 919 - else 801 + } else { 920 802 pnv_php_disable_slot(&php_slot->slot); 803 + pnv_php_detect_clear_suprise_removal_freeze(php_slot); 804 + } 921 805 922 806 kfree(event); 923 807 } ··· 1053 843 u16 sts, ctrl; 1054 844 int ret; 1055 845 1056 - /* Allocate workqueue */ 1057 - php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name); 1058 - if (!php_slot->wq) { 1059 - SLOT_WARN(php_slot, "Cannot alloc workqueue\n"); 1060 - pnv_php_disable_irq(php_slot, true); 1061 - return; 1062 - } 1063 - 1064 846 /* Check PDC (Presence Detection Change) is broken or not */ 1065 847 ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc", 1066 848 &broken_pdc); ··· 1071 869 ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED, 1072 870 php_slot->name, php_slot); 1073 871 if (ret) { 1074 - pnv_php_disable_irq(php_slot, true); 872 + pnv_php_disable_irq(php_slot, true, true); 1075 873 SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq); 1076 874 return; 1077 875 }
+2 -1
tools/testing/selftests/bpf/progs/bpf_misc.h
··· 229 229 230 230 #if __clang_major__ >= 18 && defined(ENABLE_ATOMICS_TESTS) && \ 231 231 (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 232 - (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) 232 + (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) || \ 233 + (defined(__TARGET_ARCH_powerpc)) 233 234 #define CAN_USE_LOAD_ACQ_STORE_REL 234 235 #endif 235 236