From nobody Mon Jun 8 17:46:39 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E30113DD87E; Wed, 27 May 2026 18:09:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905342; cv=none; b=u1ACKzzDRYE7IYxmRvBfiAfpmymlgNP6px7KfirfvMHGS2vg2kVAtMebqjyY9/7NK89KWJEFr1Lpjyyig/PMycBxVIIh5gJ5BZ1/6OuTSXLruM1kL7RAe2FeCTgUUoMXIvZEy0yCn0PH/FInXJKKWQslNGzSpNmFVYNX2DvOYag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905342; c=relaxed/simple; bh=ZnbLwe6TDSjpyLo8ALWeffVq0Ut2VkuT9uRi3fjDBf4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WOFlQBAFkeZOsJbPBhTvz3yE6GztFaic4wJCoBa3NqeAkaqNWwBvobV4dFAKqcCpHonXEFXsyIPUGgRYnIxjkyOgrAxVUOH4PzDLvgt1G/7efujXH4p09lhwJdU/phJQ5zhVwP4d3uItYoM96y/s6pVhKKYgbpw6FusKaq/BwUs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=hcMNQfAH; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="hcMNQfAH" Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 64RCr7HX346650; Wed, 27 May 2026 18:08:51 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=TrOA5GJrGr69PnMdD gtk8L85vkg2hNUjDeGZFpXPS04=; b=hcMNQfAHbkqYYoWDgdjGsN8/v3B8Fz7/C iqc4qsBrfsEWCj0QuW1F/njY401kN8jyHvJ9viCM7oNLBReAiHBfG1wd9CU3BtXl +ZTMos0/X8RvYklZrOLY8m2lUVTg77lPW9Q5YL1Ayru618n2Hwrvc4DyNpHOj49q pEfk/3dKIy6F9ZuQIo2VSZhqdByiSWtuM3MaTR+TDjcHgrymdEG6e1EfjousiWQZ MbdtmB0HOhsO020JCnngO47oDBmQLrCYJsAoSVssppIdIRZslU5BRImkzwNvEUlv nAdLjol5RmRaWcJnDTs40Y+pRwe3xr43QGTabOjExXFbHBzF8/3vA== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4eb4nutwhh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:08:51 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 64RHs52f022906; Wed, 27 May 2026 18:08:50 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4edjrbvasb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:08:50 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 64RI8kmu45482318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 27 May 2026 18:08:46 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 541DD20043; Wed, 27 May 2026 18:08:46 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E536320040; Wed, 27 May 2026 18:08:41 +0000 (GMT) Received: from li-3c92a0cc-27cf-11b2-a85c-b804d9ca68fa.ibm.com (unknown [9.124.220.41]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 27 May 2026 18:08:41 +0000 (GMT) From: Aditya Gupta To: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Timothy Pearson , Bjorn Helgaas , Shawn Anastasio Cc: sashiko-bot@kernel.org, linux-pci@vger.kernel.org, Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , stable@vger.kernel.org Subject: [PATCH v2 1/3] ppc/pnv: Add null checks for OpenCapi PHBs Date: Wed, 27 May 2026 23:38:14 +0530 Message-ID: <20260527180816.2749186-2-adityag@linux.ibm.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com> References: <20260527180816.2749186-1-adityag@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNTI3MDE4MiBTYWx0ZWRfX8OeyhjEM6epN K9LbzxOdJPbJYetzp5DubvcWmOQiksAPUfptT4FPSQulUiqYEdEw7ozZR4dnT3fE7qd4bCMdK+6 qFMgWgIv1VMdf4VpPA00zP/VhR7Yj26SnXLiR6D92lUL8c5HNbzj3hsvBc2hDtidqvLmZpoCljr Q/AIiMG8LYH2exgW6NNh0PXRDpmcO/oaiTw8VmwtNkpThcosBKtnjGcbY24Pk0A/5Rua6krvjnw lJjywddcC3zGl6SV64qzR5lWgr9NBGSV5tW4WxI/Gd7Lpl+kBVtCXCnc4ORNmBe0oAh91u7mXP8 At7vCSSg226ZIfcCMvNi/+fQmXfG7bJt0uZRtnGZNO9MOxjNNXaPei6pgTwWS0tlDv/GxrP+kDW ADQ4aqr/Uav4Cf7hxDdGxS4XFcGuIWkD3MRScAu15KRrgX0hsRuKGhiqHE2sckow4L0lxkAYmnH Bs3f0VbXXCDC042yfZg== X-Authority-Analysis: v=2.4 cv=UtJT8ewB c=1 sm=1 tr=0 ts=6a173333 cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=NGcC8JguVDcA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=2CTBcJULQSvMIThFTPkA:9 X-Proofpoint-ORIG-GUID: 7JLdXtoD7sCI2m37uW2x3VWRzRfLXjXA X-Proofpoint-GUID: OHo431b-WlO5WFm2Lig5AZRtFZWIy2rs X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-05-27_03,2026-05-26_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 adultscore=0 clxscore=1011 bulkscore=0 phishscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605130000 definitions=main-2605270182 Content-Type: text/plain; charset="utf-8" For opencapi phb direct slots, the .pdev for php_slots will be NULL Various sections of the code in pnv_php can do a null dereference and crash the kernel. Originally, the issue was hit during boot: [ 1.568588] PowerPC PowerNV PCI Hotplug Driver version: 0.1 [ 1.569722] BUG: Kernel NULL pointer dereference at 0x00000074 [ 1.569811] Faulting instruction address: 0xc000000000b75fd0 [ 1.569890] Oops: Kernel access of bad area, sig: 11 [#1] [ 1.569963] LE PAGE_SIZE=3D64K MMU=3DHash SMP NR_CPUS=3D2048 NUMA P= owerNV ... [ 1.571492] NIP [c000000000b75fd0] pnv_php_get_adapter_state+0x60/0x= 154 [ 1.571604] LR [c000000000b75fbc] pnv_php_get_adapter_state+0x4c/0x1= 54 [ 1.571690] Call Trace: [ 1.571725] [c000c0000688f990] [c000000000b75fbc] pnv_php_get_adapte= r_state+0x4c/0x154 (unreliable) [ 1.571783] [c000c0000688fa20] [c000000000b78bd0] pnv_php_enable+0x9= 4/0x378 [ 1.571951] [c000c0000688fac0] [c000000000b7912c] pnv_php_register_o= ne.isra.0+0x11c/0x1e0 This occurs for hotplug slots on root buses where bus->self =3D=3D NULL, such as OpenCAPI PHB direct slots. An added debug print (not part of this patch) confirmed it was opencapi: [ 1.617227] pnv_php: slot 'OPENCAPI-0009' has NULL pdev (bus 0009:00= , parent=3DNO (root bus)) [ 1.617308] pnv_php: slot 'OPENCAPI-0009' dn->full_name=3D'pciex@603= a000000000', compatible=3D'ibm,power10-pau-opencapi-pciex' This only required null check in 'pnv_php_get_adapter_state', which caused the kernel to boot. Even with 'pnv_php_get_adapter_state' null check, there are more possible null dereferences pointed by sashiko, including cases where userspace crashes the kernel, such as: $ cat /sys/bus/pci/slots/*/attention ... [ 557.036295] Kernel attempted to read user page (6e) - exploit attemp= t? (uid: 0) [ 557.036354] BUG: Kernel NULL pointer dereference on read at 0x000000= 6e [ 557.036383] Faulting instruction address: 0xc000000000a83334 [ 557.036413] Oops: Kernel access of bad area, sig: 11 [#1] [ 557.036449] LE PAGE_SIZE=3D64K MMU=3DHash SMP NR_CPUS=3D2048 NUMA P= owerNV ... [ 557.037749] [c000000046707a20] [c000000046707b90] 0xc000000046707b90= (unreliable) [ 557.037795] [c000000046707a70] [0000000000000001] 0x1 [ 557.037850] [c000000046707ab0] [c000000000acb00c] attention_read_fil= e+0x54/0xa8 [ 557.037910] [c000000046707b30] [c000000000abfbfc] pci_slot_attr_show= +0x3c/0x58 [ 557.037977] [c000000046707b50] [c0000000008181ec] sysfs_kf_seq_show+= 0xd4/0x204 [ 557.038022] [c000000046707be0] [c000000000815004] kernfs_seq_show+0x= 44/0x58 Add null checks to prevent the null dereferences. Cc: stable@vger.kernel.org Fixes: 80f9fc236279 ("PCI: pnv_php: Work around switches with broken presen= ce detection") Signed-off-by: Aditya Gupta --- drivers/pci/hotplug/pnv_php.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c index ff92a5c301b8..d0f5e8ad1f71 100644 --- a/drivers/pci/hotplug/pnv_php.c +++ b/drivers/pci/hotplug/pnv_php.c @@ -47,6 +47,9 @@ static void pnv_php_disable_irq(struct pnv_php_slot *php_= slot, struct pci_dev *pdev =3D php_slot->pdev; u16 ctrl; =20 + if (!pdev) + return; + if (php_slot->irq > 0) { pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); ctrl &=3D ~(PCI_EXP_SLTCTL_HPIE | @@ -414,7 +417,8 @@ static int pnv_php_get_adapter_state(struct hotplug_slo= t *slot, u8 *state) */ ret =3D pnv_pci_get_presence_state(php_slot->id, &presence); if (ret >=3D 0) { - if (pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && + if (php_slot->pdev && + pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && presence =3D=3D OPAL_PCI_SLOT_EMPTY) { /* * Similar to pciehp_hpc, check whether the Link Active @@ -442,6 +446,11 @@ static int pnv_php_get_raw_indicator_status(struct hot= plug_slot *slot, u8 *state struct pci_dev *bridge =3D php_slot->pdev; u16 status; =20 + if (!bridge) { + *state =3D 0; + return 0; + } + pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status); *state =3D (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; return 0; @@ -514,11 +523,13 @@ static int pnv_php_activate_slot(struct pnv_php_slot = *php_slot, * fence / freeze. */ SLOT_WARN(php_slot, "Try %d...\n", i + 1); - pci_set_pcie_reset_state(php_slot->pdev, - pcie_warm_reset); - msleep(250); - pci_set_pcie_reset_state(php_slot->pdev, - pcie_deassert_reset); + if (php_slot->pdev) { + pci_set_pcie_reset_state(php_slot->pdev, + pcie_warm_reset); + msleep(250); + pci_set_pcie_reset_state(php_slot->pdev, + pcie_deassert_reset); + } =20 ret =3D pnv_php_set_slot_power_state( slot, OPAL_PCI_SLOT_POWER_ON); @@ -911,6 +922,9 @@ pnv_php_detect_clear_suprise_removal_freeze(struct pnv_= php_slot *php_slot) struct eeh_pe *pe; int i, rc; =20 + if (!pdev) + return; + /* * When a device is surprise removed from a downstream bridge slot, * the upstream bridge port can still end up frozen due to related EEH @@ -1093,6 +1107,9 @@ static void pnv_php_enable_irq(struct pnv_php_slot *p= hp_slot) struct pci_dev *pdev =3D php_slot->pdev; int irq, ret; =20 + if (!pdev) + return; + /* * The MSI/MSIx interrupt might have been occupied by other * drivers. Don't populate the surprise hotplug capability --=20 2.54.0 From nobody Mon Jun 8 17:46:39 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C41C466B53; Wed, 27 May 2026 18:09:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905347; cv=none; b=IBv4U6bUIaZvCQ7F8pKAPj5X3RP4A/ffaQLRJSpqLIB/cFrFIvzkMen6Bwkp37Se2ipyuSWoJPswFNDiw+xpq2zXIUcxfrySSOg2zgZYZaV2io/pJA9sTs4KJAlFxMMSFwClzjufmrSRlbL3hQyhiKzKbIfzeAFGkaeNbQM/ks8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905347; c=relaxed/simple; bh=jIf2O6pNjHy4gmuJO+NgckctqjZaLXxjDqj9aul5YhY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UXgs2gkMns6K3gn9eaPE1SVHUTSgm0PWgeA4vwe0DgO0FK3nlnGJ0+RDExVliZB03XyQi958rkt0s8h0OIbBAU4Gr3MBzg17KMmUwFezGlzsJUz4mNvJtdI4DdNBVJh3djZ8duijo5mhvEwIKm2uN6ztZR8N5MHBZb/CUjFzGOc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=KHqGgOTG; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="KHqGgOTG" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 64RCMxM93811477; Wed, 27 May 2026 18:08:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=rbrwwtxlGutlngBQo Um34N+K3fgrN4lZbrEiXJPoKHY=; b=KHqGgOTGhM7E62zxCIFlQKyPqQVJLH3wm axnqxTkN+VIUnTRQMU8AMFlPgf5Ke41hHRsSrUmW28fU+AiFbC459XoJNNM8m0Ol 4DjvDrni5+80rqf6murfq1/uyUFml6V8//5TJ1fUkMNEu+2PE/eGqZVQJdDBKthj 7kqggaBg/fsdqVHZ70sJ+OK3ETksszl99KfuA+QJeCNeQnc5RZRfTafwfCJIVunQ Af/UkLxiD8StReFyxp3289iy/TU0yg8Jk+WVoeznHMpPXlHSUfJeaZnM6ns0HUVG rQzzjBpT+Cp1jrbY8cBbpabGqt/yOuHHCbDr7iKLoxPZugq0L6b1w== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4eb4qc2sky-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:08:55 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 64RHs4mk023480; Wed, 27 May 2026 18:08:54 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4edjrb4awj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:08:54 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 64RI8oDb45220102 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 27 May 2026 18:08:51 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CF64B20043; Wed, 27 May 2026 18:08:50 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CF3DB20040; Wed, 27 May 2026 18:08:46 +0000 (GMT) Received: from li-3c92a0cc-27cf-11b2-a85c-b804d9ca68fa.ibm.com (unknown [9.124.220.41]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 27 May 2026 18:08:46 +0000 (GMT) From: Aditya Gupta To: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Timothy Pearson , Bjorn Helgaas , Shawn Anastasio Cc: sashiko-bot@kernel.org, linux-pci@vger.kernel.org, Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" Subject: [PATCH v2 2/3] ppc/pnv: Refactor PNV PCI hotplug driver Date: Wed, 27 May 2026 23:38:15 +0530 Message-ID: <20260527180816.2749186-3-adityag@linux.ibm.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com> References: <20260527180816.2749186-1-adityag@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNTI3MDE4MiBTYWx0ZWRfX1ft8FJ5aDfc0 j8UoJdMGPlm8Zu3g/9jdNyGJIa6u952C8CZmq3WxGRm1JsBTSBY4XtKRqLKEeO5XAM2xOg66UKl ZbhgLHE+FbDeWMNieo2vQuYSXX0ErNTFyFV3ksHeNIkFysSILz1K+KZ3bC+WnWEC2xNKcfooAhr i7nu6og+g7LyCnyCXf3rIvXt7sXeC2XhB03pj/wxwoyUBsixhWC/npMOhTyjy9q0E6BCigNDnI/ ZPfyCY1wYSziy6rbQT7dXyEgEWFkwueLgBpJ9VdIkw8ItwWsM09vhWlQHqb5WMisEr1Lfyd5WMM FlWKoZP7kheGv2+Ke38jj8LpS+DPL0KkY2nGjoRS7SB8VLr5bh8agruq5Q/cJeGlGKfz/niQHlI VNQ/xMcnDlQus/7thk50mxAfWw6I0ZwfKNEb8h+nZD9++qWmvbab+NZHnq5U4oJ7DKuhbwsvMix 7cx3r8PsNjKvLsDtSOQ== X-Authority-Analysis: v=2.4 cv=KItqylFo c=1 sm=1 tr=0 ts=6a173337 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=NGcC8JguVDcA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=sFtuphBWuyu6uFSNHX4A:9 X-Proofpoint-ORIG-GUID: dspj0QFFytavG6dFvfuLZOmaZBLDIRkK X-Proofpoint-GUID: oU26Fy5jBHxQ_dTg_eNGo92AdHQEvOTg X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-05-27_03,2026-05-26_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 malwarescore=0 lowpriorityscore=0 spamscore=0 priorityscore=1501 clxscore=1015 adultscore=0 suspectscore=0 bulkscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605130000 definitions=main-2605270182 Content-Type: text/plain; charset="utf-8" Currently the pnv_php driver handles both PCIe and OpenCAPI slots. The slots has many common functionality, but many operations are pcie specific, and assume the slot having a parent device, which isn't the case with opencapi slots This requires handling the case of parent device being NULL, at many places, which can be hard to maintain and add code to. Instead, have PCIe/OpenCAPI operations as .backend_ops in pnv_php_slot, so that PCIe code is cleanly separated. With this, future patches can just edit the PCIe/OpenCAPI specific ops, instead of editing the common code. No functional change is intended other than reset_slot for OpenCAPI slots returning -ENODEV when not probing. Signed-off-by: Aditya Gupta --- arch/powerpc/include/asm/pnv-pci.h | 16 +++ drivers/pci/hotplug/pnv_php.c | 160 +++++++++++++++++++---------- 2 files changed, 123 insertions(+), 53 deletions(-) diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/= pnv-pci.h index 7e9a479951a3..f1020f1e61cd 100644 --- a/arch/powerpc/include/asm/pnv-pci.h +++ b/arch/powerpc/include/asm/pnv-pci.h @@ -27,6 +27,9 @@ extern int pnv_pci_set_power_state(uint64_t id, uint8_t s= tate, int64_t pnv_opal_pci_msi_eoi(struct irq_data *d); bool is_pnv_opal_msi(struct irq_chip *chip); =20 +/* To be set for hotplug operations for PCIe/OpenCAPI */ +struct pnv_php_backend_ops; + struct pnv_php_slot { struct hotplug_slot slot; uint64_t id; @@ -50,10 +53,23 @@ struct pnv_php_slot { void *fdt; void *dt; struct of_changeset ocs; + const struct pnv_php_backend_ops *backend_ops; struct pnv_php_slot *parent; struct list_head children; struct list_head link; }; + +struct pnv_php_backend_ops { + void (*enable_irq)(struct pnv_php_slot *slot); + void (*disable_irq)(struct pnv_php_slot *slot, bool disable_device, bool = disable_msi); + void (*fixup_presence_state)(struct pnv_php_slot *slot, u8 *presence); + void (*get_attention_state)(struct pnv_php_slot *slot, u8 *state); + void (*set_attention_state)(struct pnv_php_slot *slot, u8 state); + void (*fundamental_reset)(struct pnv_php_slot *slot); + void (*detect_surprise_removal)(struct pnv_php_slot *slot); + int (*reset_slot)(struct pnv_php_slot *slot, bool probe); +}; + extern struct pnv_php_slot *pnv_php_find_slot(struct device_node *dn); extern int pnv_php_set_slot_power_state(struct hotplug_slot *slot, uint8_t state); diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c index d0f5e8ad1f71..997412eea486 100644 --- a/drivers/pci/hotplug/pnv_php.c +++ b/drivers/pci/hotplug/pnv_php.c @@ -39,17 +39,53 @@ static void pnv_php_register(struct device_node *dn); static void pnv_php_unregister_one(struct device_node *dn); static void pnv_php_unregister(struct device_node *dn); =20 -static void pnv_php_enable_irq(struct pnv_php_slot *php_slot); +static void pcie_enable_irq(struct pnv_php_slot *php_slot); +static int pcie_check_link_active(struct pci_dev *pdev); +static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot); + +static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *p= resence) +{ + if (pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && + *presence =3D=3D OPAL_PCI_SLOT_EMPTY) { + /* + * Similar to pciehp_hpc, check whether the Link Active + * bit is set to account for broken downstream bridges + * that don't properly assert Presence Detect State, as + * was observed on the Microsemi Switchtec PM8533 PFX + * [11f8:8533]. + */ + if (pcie_check_link_active(php_slot->pdev) > 0) + *presence =3D OPAL_PCI_SLOT_PRESENT; + } +} + +static void pcie_fundamental_reset(struct pnv_php_slot *php_slot) +{ + pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset); + msleep(250); + pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset); +} + +static void pnv_php_enable_irq(struct pnv_php_slot *php_slot) +{ + if (php_slot->backend_ops->enable_irq) + php_slot->backend_ops->enable_irq(php_slot); +} =20 static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, bool disable_device, bool disable_msi) +{ + if (php_slot->backend_ops->disable_irq) + php_slot->backend_ops->disable_irq(php_slot, disable_device, + disable_msi); +} + +static void pcie_disable_irq(struct pnv_php_slot *php_slot, + bool disable_device, bool disable_msi) { struct pci_dev *pdev =3D php_slot->pdev; u16 ctrl; =20 - if (!pdev) - return; - if (php_slot->irq > 0) { pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); ctrl &=3D ~(PCI_EXP_SLTCTL_HPIE | @@ -417,19 +453,8 @@ static int pnv_php_get_adapter_state(struct hotplug_sl= ot *slot, u8 *state) */ ret =3D pnv_pci_get_presence_state(php_slot->id, &presence); if (ret >=3D 0) { - if (php_slot->pdev && - pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && - presence =3D=3D OPAL_PCI_SLOT_EMPTY) { - /* - * Similar to pciehp_hpc, check whether the Link Active - * bit is set to account for broken downstream bridges - * that don't properly assert Presence Detect State, as - * was observed on the Microsemi Switchtec PM8533 PFX - * [11f8:8533]. - */ - if (pcie_check_link_active(php_slot->pdev) > 0) - presence =3D OPAL_PCI_SLOT_PRESENT; - } + if (php_slot->backend_ops->fixup_presence_state) + php_slot->backend_ops->fixup_presence_state(php_slot, &presence); =20 *state =3D presence; ret =3D 0; @@ -440,28 +465,24 @@ static int pnv_php_get_adapter_state(struct hotplug_s= lot *slot, u8 *state) return ret; } =20 -static int pnv_php_get_raw_indicator_status(struct hotplug_slot *slot, u8 = *state) +static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *st= ate) { - struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); struct pci_dev *bridge =3D php_slot->pdev; u16 status; =20 - if (!bridge) { - *state =3D 0; - return 0; - } - pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status); *state =3D (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; - return 0; } =20 - static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *stat= e) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); =20 - pnv_php_get_raw_indicator_status(slot, &php_slot->attention_state); + if (php_slot->backend_ops->get_attention_state) + php_slot->backend_ops->get_attention_state(php_slot, &php_slot->attentio= n_state); + else + php_slot->attention_state =3D 0; + *state =3D php_slot->attention_state; return 0; } @@ -469,13 +490,19 @@ static int pnv_php_get_attention_state(struct hotplug= _slot *slot, u8 *state) static int pnv_php_set_attention_state(struct hotplug_slot *slot, u8 state) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); + + if (php_slot->backend_ops->set_attention_state) + php_slot->backend_ops->set_attention_state(php_slot, state); + + return 0; +} + +static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 sta= te) +{ struct pci_dev *bridge =3D php_slot->pdev; u16 new, mask; =20 php_slot->attention_state =3D state; - if (!bridge) - return 0; - mask =3D PCI_EXP_SLTCTL_AIC; =20 if (state) @@ -484,8 +511,6 @@ static int pnv_php_set_attention_state(struct hotplug_s= lot *slot, u8 state) new =3D PCI_EXP_SLTCTL_ATTN_IND_OFF; =20 pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new); - - return 0; } =20 static int pnv_php_activate_slot(struct pnv_php_slot *php_slot, @@ -523,13 +548,8 @@ static int pnv_php_activate_slot(struct pnv_php_slot *= php_slot, * fence / freeze. */ SLOT_WARN(php_slot, "Try %d...\n", i + 1); - if (php_slot->pdev) { - pci_set_pcie_reset_state(php_slot->pdev, - pcie_warm_reset); - msleep(250); - pci_set_pcie_reset_state(php_slot->pdev, - pcie_deassert_reset); - } + if (php_slot->backend_ops->fundamental_reset) + php_slot->backend_ops->fundamental_reset(php_slot); =20 ret =3D pnv_php_set_slot_power_state( slot, OPAL_PCI_SLOT_POWER_ON); @@ -633,16 +653,18 @@ static int pnv_php_enable(struct pnv_php_slot *php_sl= ot, bool rescan) static int pnv_php_reset_slot(struct hotplug_slot *slot, bool probe) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); + if (php_slot->backend_ops->reset_slot) + return php_slot->backend_ops->reset_slot(php_slot, probe); + return probe ? 0 : -ENODEV; +} + +static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe) +{ struct pci_dev *bridge =3D php_slot->pdev; uint16_t sts; =20 - /* - * The CAPI folks want pnv_php to drive OpenCAPI slots - * which don't have a bridge. Only claim to support - * reset_slot() if we have a bridge device (for now...) - */ if (probe) - return !bridge; + return 0; =20 /* mask our interrupt while resetting the bridge */ if (php_slot->irq > 0) @@ -778,6 +800,26 @@ static void pnv_php_release(struct pnv_php_slot *php_s= lot) pnv_php_put_slot(php_slot->parent); } =20 +static const struct pnv_php_backend_ops pnv_php_pcie_ops =3D { + .enable_irq =3D pcie_enable_irq, + .disable_irq =3D pcie_disable_irq, + .get_attention_state =3D pcie_get_attention_state, + .set_attention_state =3D pcie_set_attention_state, + .fixup_presence_state =3D pcie_fixup_presence_state, + .fundamental_reset =3D pcie_fundamental_reset, + .detect_surprise_removal =3D pcie_detect_surprise_removal, + .reset_slot =3D pcie_reset_slot, +}; + +static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe) +{ + return probe ? 1 : -ENODEV; +} + +static const struct pnv_php_backend_ops pnv_php_opencapi_ops =3D { + .reset_slot =3D opencapi_reset_slot, +}; + static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn) { struct pnv_php_slot *php_slot; @@ -830,6 +872,12 @@ static struct pnv_php_slot *pnv_php_alloc_slot(struct = device_node *dn) php_slot->power_state_check =3D false; php_slot->slot.ops =3D &php_slot_ops; =20 + /* OpenCAPI slots don't have a parent bridge */ + if (php_slot->pdev) + php_slot->backend_ops =3D &pnv_php_pcie_ops; + else + php_slot->backend_ops =3D &pnv_php_opencapi_ops; + INIT_LIST_HEAD(&php_slot->children); INIT_LIST_HEAD(&php_slot->link); =20 @@ -886,7 +934,7 @@ static int pnv_php_register_slot(struct pnv_php_slot *p= hp_slot) return 0; } =20 -static int pnv_php_enable_msix(struct pnv_php_slot *php_slot) +static int pcie_enable_msix(struct pnv_php_slot *php_slot) { struct pci_dev *pdev =3D php_slot->pdev; struct msix_entry entry; @@ -915,7 +963,13 @@ static int pnv_php_enable_msix(struct pnv_php_slot *ph= p_slot) } =20 static void -pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot) +pnv_php_detect_clear_surprise_removal_freeze(struct pnv_php_slot *php_slot) +{ + if (php_slot->backend_ops->detect_surprise_removal) + php_slot->backend_ops->detect_surprise_removal(php_slot); +} + +static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot) { struct pci_dev *pdev =3D php_slot->pdev; struct eeh_dev *edev; @@ -972,7 +1026,7 @@ static void pnv_php_event_handler(struct work_struct *= work) pnv_php_enable_slot(&php_slot->slot); } else { pnv_php_disable_slot(&php_slot->slot); - pnv_php_detect_clear_suprise_removal_freeze(php_slot); + pnv_php_detect_clear_surprise_removal_freeze(php_slot); } =20 kfree(event); @@ -1055,7 +1109,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *d= ata) return IRQ_HANDLED; } =20 -static void pnv_php_init_irq(struct pnv_php_slot *php_slot, int irq) +static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq) { struct pci_dev *pdev =3D php_slot->pdev; u32 broken_pdc =3D 0; @@ -1102,7 +1156,7 @@ static void pnv_php_init_irq(struct pnv_php_slot *php= _slot, int irq) php_slot->irq =3D irq; } =20 -static void pnv_php_enable_irq(struct pnv_php_slot *php_slot) +static void pcie_enable_irq(struct pnv_php_slot *php_slot) { struct pci_dev *pdev =3D php_slot->pdev; int irq, ret; @@ -1127,9 +1181,9 @@ static void pnv_php_enable_irq(struct pnv_php_slot *p= hp_slot) pci_set_master(pdev); =20 /* Enable MSIx interrupt */ - irq =3D pnv_php_enable_msix(php_slot); + irq =3D pcie_enable_msix(php_slot); if (irq > 0) { - pnv_php_init_irq(php_slot, irq); + pcie_init_irq(php_slot, irq); return; } =20 @@ -1140,7 +1194,7 @@ static void pnv_php_enable_irq(struct pnv_php_slot *p= hp_slot) ret =3D pci_enable_msi(pdev); if (!ret || pdev->irq) { irq =3D pdev->irq; - pnv_php_init_irq(php_slot, irq); + pcie_init_irq(php_slot, irq); } } =20 --=20 2.54.0 From nobody Mon Jun 8 17:46:39 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6E5644657F3; Wed, 27 May 2026 18:09:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905353; cv=none; b=o5KVQUSscqDep8lBchF2+Y5PHA0PUL16mirYMPtQ/9haGOm117oWZXt8FgZgpqD3SIRW7JaNkmrTGhdcOJRo19Iltzxx0cVFCF/GVjIFQQF9AhluDf/QBaljDt6IVEqV33ol1j8LfJgvPvvr+g55dqp5cvRSfTTV+tgbg+hgBZg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779905353; c=relaxed/simple; bh=/85KIsWjRLgluNmrjCsxxpm7NEvgH9uOAzePJobu0Dw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C/EZzy/9KbiNohd+UZvz46u4kvB+h5ZDDSrj/9j27fxV14JbowwjzT+CYJeFmeGxLAtiwmr5n+YOQxeHijVDV6GStuyI7Ew6SqUF0R8FhJcqWUD6uv0T3rRnA4p1LnLU4hI9FGl5w9N+B7/UuaoU6XMl/L7Rw+MrGl56qYFMLgg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=ViXqLdFy; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="ViXqLdFy" Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 64RD13E2346180; Wed, 27 May 2026 18:09:00 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=UAYJMGHqRvUjpDgGj N0gjb0WF60PTnqNAsmxL6LbVNM=; b=ViXqLdFyHHYHjAraTIyiT4hagin3b1GBh Rn2EdPYUCib84qEDBiS0MorRe+wRpi2K4Q597MXVnx5sbCAZZsbl4czQGl6g1PsW HzLKD0XUumsVabGouZM5n2OSPXuhBVsR6oNrA79YxFcFSMx7yxHlLU0/lmNFYZBI ysgjLGFCpYFbTjYYM9MG/ugowoyDYNhWto/qdHlUqMP6xTJqUcjdH9RhsuXU2nyD IEGaRCN9c4FFlh6rj5p/dKo4OvLialfqbVcLx83NSAJwk33O972E3my2Qf3k8xgk DDi0hwCguyOVBc5aITFt/yVstaUV0e70k95/kUdtdgmomx4/iUCYw== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4eb4nutwje-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:09:00 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 64RHs5LZ010647; Wed, 27 May 2026 18:08:59 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4edjrb4b1f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 27 May 2026 18:08:59 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (smtpav02.fra02v.mail.ibm.com [10.20.54.101]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 64RI8taM61800922 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 27 May 2026 18:08:55 GMT Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6FBE920043; Wed, 27 May 2026 18:08:55 +0000 (GMT) Received: from smtpav02.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5533F20040; Wed, 27 May 2026 18:08:51 +0000 (GMT) Received: from li-3c92a0cc-27cf-11b2-a85c-b804d9ca68fa.ibm.com (unknown [9.124.220.41]) by smtpav02.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 27 May 2026 18:08:51 +0000 (GMT) From: Aditya Gupta To: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Madhavan Srinivasan , Timothy Pearson , Bjorn Helgaas , Shawn Anastasio Cc: sashiko-bot@kernel.org, linux-pci@vger.kernel.org, Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" Subject: [PATCH v2 3/3] ppc/pnv: Refactor PNV PCI Hotplug to group PCIe functions Date: Wed, 27 May 2026 23:38:16 +0530 Message-ID: <20260527180816.2749186-4-adityag@linux.ibm.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260527180816.2749186-1-adityag@linux.ibm.com> References: <20260527180816.2749186-1-adityag@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNTI3MDE4MiBTYWx0ZWRfX0cGsU2ChPcR7 kEvfwCvjFFnAPfDhKEZ90SYfRfLwvRQ7GNKy1L81XLAdcJ+vbZweejFoFRVWUt2MzmaQI9u/nfI Hu4VGYyAOq5awGrBsJDxz5mU3NqxyreVx1X3mYofLeqTcBCustXIGGcoHPCeyvy7Q3Tdb89Kw3S wK9B2IsT6lwrba/jDnH0e7j9uvkX8meTCh/K7z9cEx085asFRXcZILBAyAEzg1CAikV4Zk910o1 PzV9RpiGD95dXcRIOjqq36/Sx7tIjYlZb8J5w5kWwRnoUC7vLU1j3o5l1dLjbyqc1/gdM0RijcI xF81wJCtmeRTnQ5GzSIO2tQePQO8CSMkC+T4qZM5bI4TXQRUERiC8JGfT5TMeAQ5koGrSySowWg PrqbZ5x7DGnEsl9pnHw1GbAWMOj6hyDzxmilw1VmKrZ/Y9rtO8xjocEJyPoTzjDYFUOqmIpvCgJ 6XHy8GvuaoEJF1C319w== X-Authority-Analysis: v=2.4 cv=UtJT8ewB c=1 sm=1 tr=0 ts=6a17333c cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=NGcC8JguVDcA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VnNF1IyMAAAA:8 a=NniskMT7brAqY532XZ8A:9 X-Proofpoint-ORIG-GUID: xg2bGjhoh-etWC96kx-Tadq8nqJCgNox X-Proofpoint-GUID: wXlQTDsk49ujJxtTvnsFA49CxQuXowOJ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-05-27_03,2026-05-26_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 adultscore=0 clxscore=1011 bulkscore=0 phishscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2605130000 definitions=main-2605270182 Content-Type: text/plain; charset="utf-8" With the refactor change to pnv_php.c, pnv_php_* and pcie_* are mixed up. Move and group pcie, opencapi, and pnv_php*. No functional change. Only moves code, and no logic has been modified. Signed-off-by: Aditya Gupta --- drivers/pci/hotplug/pnv_php.c | 559 +++++++++++++++++----------------- 1 file changed, 279 insertions(+), 280 deletions(-) diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c index 997412eea486..dd8e00b879e1 100644 --- a/drivers/pci/hotplug/pnv_php.c +++ b/drivers/pci/hotplug/pnv_php.c @@ -38,46 +38,125 @@ static DEFINE_SPINLOCK(pnv_php_lock); static void pnv_php_register(struct device_node *dn); static void pnv_php_unregister_one(struct device_node *dn); static void pnv_php_unregister(struct device_node *dn); +static irqreturn_t pnv_php_interrupt(int irq, void *data); +static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, + bool disable_device, bool disable_msi); =20 -static void pcie_enable_irq(struct pnv_php_slot *php_slot); -static int pcie_check_link_active(struct pci_dev *pdev); -static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot); - -static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *p= resence) +static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq) { - if (pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && - *presence =3D=3D OPAL_PCI_SLOT_EMPTY) { - /* - * Similar to pciehp_hpc, check whether the Link Active - * bit is set to account for broken downstream bridges - * that don't properly assert Presence Detect State, as - * was observed on the Microsemi Switchtec PM8533 PFX - * [11f8:8533]. - */ - if (pcie_check_link_active(php_slot->pdev) > 0) - *presence =3D OPAL_PCI_SLOT_PRESENT; + struct pci_dev *pdev =3D php_slot->pdev; + u32 broken_pdc =3D 0; + u16 sts, ctrl; + int ret; + + /* Check PDC (Presence Detection Change) is broken or not */ + ret =3D of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc", + &broken_pdc); + if (!ret && broken_pdc) + php_slot->flags |=3D PNV_PHP_FLAG_BROKEN_PDC; + + /* Clear pending interrupts */ + pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts); + if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) + sts |=3D PCI_EXP_SLTSTA_DLLSC; + else + sts |=3D (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts); + + /* Request the interrupt */ + ret =3D request_irq(irq, pnv_php_interrupt, IRQF_SHARED, + php_slot->name, php_slot); + if (ret) { + pnv_php_disable_irq(php_slot, true, true); + SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq); + return; } -} =20 -static void pcie_fundamental_reset(struct pnv_php_slot *php_slot) -{ - pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset); - msleep(250); - pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset); + /* Enable the interrupts */ + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); + if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) { + ctrl &=3D ~PCI_EXP_SLTCTL_PDCE; + ctrl |=3D (PCI_EXP_SLTCTL_HPIE | + PCI_EXP_SLTCTL_DLLSCE); + } else { + ctrl |=3D (PCI_EXP_SLTCTL_HPIE | + PCI_EXP_SLTCTL_PDCE | + PCI_EXP_SLTCTL_DLLSCE); + } + pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl); + + /* The interrupt is initialized successfully when @irq is valid */ + php_slot->irq =3D irq; } =20 -static void pnv_php_enable_irq(struct pnv_php_slot *php_slot) +static int pcie_enable_msix(struct pnv_php_slot *php_slot) { - if (php_slot->backend_ops->enable_irq) - php_slot->backend_ops->enable_irq(php_slot); + struct pci_dev *pdev =3D php_slot->pdev; + struct msix_entry entry; + int nr_entries, ret; + u16 pcie_flag; + + /* Get total number of MSIx entries */ + nr_entries =3D pci_msix_vec_count(pdev); + if (nr_entries < 0) + return nr_entries; + + /* Check hotplug MSIx entry is in range */ + pcie_capability_read_word(pdev, PCI_EXP_FLAGS, &pcie_flag); + entry.entry =3D FIELD_GET(PCI_EXP_FLAGS_IRQ, pcie_flag); + if (entry.entry >=3D nr_entries) + return -ERANGE; + + /* Enable MSIx */ + ret =3D pci_enable_msix_exact(pdev, &entry, 1); + if (ret) { + SLOT_WARN(php_slot, "Error %d enabling MSIx\n", ret); + return ret; + } + + return entry.vector; } =20 -static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, - bool disable_device, bool disable_msi) +static void pcie_enable_irq(struct pnv_php_slot *php_slot) { - if (php_slot->backend_ops->disable_irq) - php_slot->backend_ops->disable_irq(php_slot, disable_device, - disable_msi); + struct pci_dev *pdev =3D php_slot->pdev; + int irq, ret; + + if (!pdev) + return; + + /* + * The MSI/MSIx interrupt might have been occupied by other + * drivers. Don't populate the surprise hotplug capability + * in that case. + */ + if (pci_dev_msi_enabled(pdev)) + return; + + ret =3D pci_enable_device(pdev); + if (ret) { + SLOT_WARN(php_slot, "Error %d enabling device\n", ret); + return; + } + + pci_set_master(pdev); + + /* Enable MSIx interrupt */ + irq =3D pcie_enable_msix(php_slot); + if (irq > 0) { + pcie_init_irq(php_slot, irq); + return; + } + + /* + * Use MSI if MSIx doesn't work. Fail back to legacy INTx + * if MSI doesn't work either + */ + ret =3D pci_enable_msi(pdev); + if (!ret || pdev->irq) { + irq =3D pdev->irq; + pcie_init_irq(php_slot, irq); + } } =20 static void pcie_disable_irq(struct pnv_php_slot *php_slot, @@ -104,8 +183,176 @@ static void pcie_disable_irq(struct pnv_php_slot *php= _slot, pci_disable_msi(pdev); } =20 - if (disable_device) - pci_disable_device(pdev); + if (disable_device) + pci_disable_device(pdev); +} + +static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *st= ate) +{ + struct pci_dev *bridge =3D php_slot->pdev; + u16 status; + + pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status); + *state =3D (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; +} + +static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 sta= te) +{ + struct pci_dev *bridge =3D php_slot->pdev; + u16 new, mask; + + php_slot->attention_state =3D state; + mask =3D PCI_EXP_SLTCTL_AIC; + + if (state) + new =3D FIELD_PREP(PCI_EXP_SLTCTL_AIC, state); + else + new =3D PCI_EXP_SLTCTL_ATTN_IND_OFF; + + pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new); +} + +static int pcie_check_link_active(struct pci_dev *pdev) +{ + u16 lnk_status; + int ret; + + ret =3D pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); + if (ret =3D=3D PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) + return -ENODEV; + + ret =3D !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); + + return ret; +} + +static void pcie_fixup_presence_state(struct pnv_php_slot *php_slot, u8 *p= resence) +{ + if (pci_pcie_type(php_slot->pdev) =3D=3D PCI_EXP_TYPE_DOWNSTREAM && + *presence =3D=3D OPAL_PCI_SLOT_EMPTY) { + /* + * Similar to pciehp_hpc, check whether the Link Active + * bit is set to account for broken downstream bridges + * that don't properly assert Presence Detect State, as + * was observed on the Microsemi Switchtec PM8533 PFX + * [11f8:8533]. + */ + if (pcie_check_link_active(php_slot->pdev) > 0) + *presence =3D OPAL_PCI_SLOT_PRESENT; + } +} + +static void pcie_fundamental_reset(struct pnv_php_slot *php_slot) +{ + pci_set_pcie_reset_state(php_slot->pdev, pcie_warm_reset); + msleep(250); + pci_set_pcie_reset_state(php_slot->pdev, pcie_deassert_reset); +} + +static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot) +{ + struct pci_dev *pdev =3D php_slot->pdev; + struct eeh_dev *edev; + struct eeh_pe *pe; + int i, rc; + + if (!pdev) + return; + + /* + * When a device is surprise removed from a downstream bridge slot, + * the upstream bridge port can still end up frozen due to related EEH + * events, which will in turn block the MSI interrupts for slot hotplug + * detection. + * + * Detect and thaw any frozen upstream PE after slot deactivation. + */ + edev =3D pci_dev_to_eeh_dev(pdev); + pe =3D edev ? edev->pe : NULL; + rc =3D eeh_pe_get_state(pe); + if ((rc =3D=3D -ENODEV) || (rc =3D=3D -ENOENT)) { + SLOT_WARN( + php_slot, + "Upstream bridge PE state unknown, hotplug detect may fail\n"); + } else { + if (pe->state & EEH_PE_ISOLATED) { + SLOT_WARN( + php_slot, + "Upstream bridge PE %02x frozen, thawing...\n", + pe->addr); + for (i =3D 0; i < 3; i++) + if (!eeh_unfreeze_pe(pe)) + break; + if (i >=3D 3) + SLOT_WARN( + php_slot, + "Unable to thaw PE %02x, hotplug detect will fail!\n", + pe->addr); + else + SLOT_WARN(php_slot, + "PE %02x thawed successfully\n", + pe->addr); + } + } +} + +static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe) +{ + struct pci_dev *bridge =3D php_slot->pdev; + uint16_t sts; + + if (probe) + return 0; + + /* mask our interrupt while resetting the bridge */ + if (php_slot->irq > 0) + disable_irq(php_slot->irq); + + pci_bridge_secondary_bus_reset(bridge); + + /* clear any state changes that happened due to the reset */ + pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts); + sts &=3D (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); + pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts); + + if (php_slot->irq > 0) + enable_irq(php_slot->irq); + + return 0; +} + +static const struct pnv_php_backend_ops pnv_php_pcie_ops =3D { + .enable_irq =3D pcie_enable_irq, + .disable_irq =3D pcie_disable_irq, + .get_attention_state =3D pcie_get_attention_state, + .set_attention_state =3D pcie_set_attention_state, + .fixup_presence_state =3D pcie_fixup_presence_state, + .fundamental_reset =3D pcie_fundamental_reset, + .detect_surprise_removal =3D pcie_detect_surprise_removal, + .reset_slot =3D pcie_reset_slot, +}; + +static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe) +{ + return probe ? 1 : -ENODEV; +} + +static const struct pnv_php_backend_ops pnv_php_opencapi_ops =3D { + .reset_slot =3D opencapi_reset_slot, +}; + +static void pnv_php_enable_irq(struct pnv_php_slot *php_slot) +{ + if (php_slot->backend_ops->enable_irq) + php_slot->backend_ops->enable_irq(php_slot); +} + +static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, + bool disable_device, bool disable_msi) +{ + if (php_slot->backend_ops->disable_irq) + php_slot->backend_ops->disable_irq(php_slot, disable_device, + disable_msi); } =20 static void pnv_php_free_slot(struct kref *kref) @@ -427,20 +674,6 @@ static int pnv_php_get_power_state(struct hotplug_slot= *slot, u8 *state) return 0; } =20 -static int pcie_check_link_active(struct pci_dev *pdev) -{ - u16 lnk_status; - int ret; - - ret =3D pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); - if (ret =3D=3D PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) - return -ENODEV; - - ret =3D !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); - - return ret; -} - static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); @@ -465,15 +698,6 @@ static int pnv_php_get_adapter_state(struct hotplug_sl= ot *slot, u8 *state) return ret; } =20 -static void pcie_get_attention_state(struct pnv_php_slot *php_slot, u8 *st= ate) -{ - struct pci_dev *bridge =3D php_slot->pdev; - u16 status; - - pcie_capability_read_word(bridge, PCI_EXP_SLTCTL, &status); - *state =3D (status & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; -} - static int pnv_php_get_attention_state(struct hotplug_slot *slot, u8 *stat= e) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); @@ -497,22 +721,6 @@ static int pnv_php_set_attention_state(struct hotplug_= slot *slot, u8 state) return 0; } =20 -static void pcie_set_attention_state(struct pnv_php_slot *php_slot, u8 sta= te) -{ - struct pci_dev *bridge =3D php_slot->pdev; - u16 new, mask; - - php_slot->attention_state =3D state; - mask =3D PCI_EXP_SLTCTL_AIC; - - if (state) - new =3D FIELD_PREP(PCI_EXP_SLTCTL_AIC, state); - else - new =3D PCI_EXP_SLTCTL_ATTN_IND_OFF; - - pcie_capability_clear_and_set_word(bridge, PCI_EXP_SLTCTL, mask, new); -} - static int pnv_php_activate_slot(struct pnv_php_slot *php_slot, struct hotplug_slot *slot) { @@ -658,31 +866,6 @@ static int pnv_php_reset_slot(struct hotplug_slot *slo= t, bool probe) return probe ? 0 : -ENODEV; } =20 -static int pcie_reset_slot(struct pnv_php_slot *php_slot, bool probe) -{ - struct pci_dev *bridge =3D php_slot->pdev; - uint16_t sts; - - if (probe) - return 0; - - /* mask our interrupt while resetting the bridge */ - if (php_slot->irq > 0) - disable_irq(php_slot->irq); - - pci_bridge_secondary_bus_reset(bridge); - - /* clear any state changes that happened due to the reset */ - pcie_capability_read_word(php_slot->pdev, PCI_EXP_SLTSTA, &sts); - sts &=3D (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); - pcie_capability_write_word(php_slot->pdev, PCI_EXP_SLTSTA, sts); - - if (php_slot->irq > 0) - enable_irq(php_slot->irq); - - return 0; -} - static int pnv_php_enable_slot(struct hotplug_slot *slot) { struct pnv_php_slot *php_slot =3D to_pnv_php_slot(slot); @@ -800,26 +983,6 @@ static void pnv_php_release(struct pnv_php_slot *php_s= lot) pnv_php_put_slot(php_slot->parent); } =20 -static const struct pnv_php_backend_ops pnv_php_pcie_ops =3D { - .enable_irq =3D pcie_enable_irq, - .disable_irq =3D pcie_disable_irq, - .get_attention_state =3D pcie_get_attention_state, - .set_attention_state =3D pcie_set_attention_state, - .fixup_presence_state =3D pcie_fixup_presence_state, - .fundamental_reset =3D pcie_fundamental_reset, - .detect_surprise_removal =3D pcie_detect_surprise_removal, - .reset_slot =3D pcie_reset_slot, -}; - -static int opencapi_reset_slot(struct pnv_php_slot *slot, bool probe) -{ - return probe ? 1 : -ENODEV; -} - -static const struct pnv_php_backend_ops pnv_php_opencapi_ops =3D { - .reset_slot =3D opencapi_reset_slot, -}; - static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn) { struct pnv_php_slot *php_slot; @@ -934,34 +1097,6 @@ static int pnv_php_register_slot(struct pnv_php_slot = *php_slot) return 0; } =20 -static int pcie_enable_msix(struct pnv_php_slot *php_slot) -{ - struct pci_dev *pdev =3D php_slot->pdev; - struct msix_entry entry; - int nr_entries, ret; - u16 pcie_flag; - - /* Get total number of MSIx entries */ - nr_entries =3D pci_msix_vec_count(pdev); - if (nr_entries < 0) - return nr_entries; - - /* Check hotplug MSIx entry is in range */ - pcie_capability_read_word(pdev, PCI_EXP_FLAGS, &pcie_flag); - entry.entry =3D FIELD_GET(PCI_EXP_FLAGS_IRQ, pcie_flag); - if (entry.entry >=3D nr_entries) - return -ERANGE; - - /* Enable MSIx */ - ret =3D pci_enable_msix_exact(pdev, &entry, 1); - if (ret) { - SLOT_WARN(php_slot, "Error %d enabling MSIx\n", ret); - return ret; - } - - return entry.vector; -} - static void pnv_php_detect_clear_surprise_removal_freeze(struct pnv_php_slot *php_slot) { @@ -969,53 +1104,6 @@ pnv_php_detect_clear_surprise_removal_freeze(struct p= nv_php_slot *php_slot) php_slot->backend_ops->detect_surprise_removal(php_slot); } =20 -static void pcie_detect_surprise_removal(struct pnv_php_slot *php_slot) -{ - struct pci_dev *pdev =3D php_slot->pdev; - struct eeh_dev *edev; - struct eeh_pe *pe; - int i, rc; - - if (!pdev) - return; - - /* - * When a device is surprise removed from a downstream bridge slot, - * the upstream bridge port can still end up frozen due to related EEH - * events, which will in turn block the MSI interrupts for slot hotplug - * detection. - * - * Detect and thaw any frozen upstream PE after slot deactivation. - */ - edev =3D pci_dev_to_eeh_dev(pdev); - pe =3D edev ? edev->pe : NULL; - rc =3D eeh_pe_get_state(pe); - if ((rc =3D=3D -ENODEV) || (rc =3D=3D -ENOENT)) { - SLOT_WARN( - php_slot, - "Upstream bridge PE state unknown, hotplug detect may fail\n"); - } else { - if (pe->state & EEH_PE_ISOLATED) { - SLOT_WARN( - php_slot, - "Upstream bridge PE %02x frozen, thawing...\n", - pe->addr); - for (i =3D 0; i < 3; i++) - if (!eeh_unfreeze_pe(pe)) - break; - if (i >=3D 3) - SLOT_WARN( - php_slot, - "Unable to thaw PE %02x, hotplug detect will fail!\n", - pe->addr); - else - SLOT_WARN(php_slot, - "PE %02x thawed successfully\n", - pe->addr); - } - } -} - static void pnv_php_event_handler(struct work_struct *work) { struct pnv_php_event *event =3D @@ -1109,95 +1197,6 @@ static irqreturn_t pnv_php_interrupt(int irq, void *= data) return IRQ_HANDLED; } =20 -static void pcie_init_irq(struct pnv_php_slot *php_slot, int irq) -{ - struct pci_dev *pdev =3D php_slot->pdev; - u32 broken_pdc =3D 0; - u16 sts, ctrl; - int ret; - - /* Check PDC (Presence Detection Change) is broken or not */ - ret =3D of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc", - &broken_pdc); - if (!ret && broken_pdc) - php_slot->flags |=3D PNV_PHP_FLAG_BROKEN_PDC; - - /* Clear pending interrupts */ - pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &sts); - if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) - sts |=3D PCI_EXP_SLTSTA_DLLSC; - else - sts |=3D (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC); - pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, sts); - - /* Request the interrupt */ - ret =3D request_irq(irq, pnv_php_interrupt, IRQF_SHARED, - php_slot->name, php_slot); - if (ret) { - pnv_php_disable_irq(php_slot, true, true); - SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq); - return; - } - - /* Enable the interrupts */ - pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &ctrl); - if (php_slot->flags & PNV_PHP_FLAG_BROKEN_PDC) { - ctrl &=3D ~PCI_EXP_SLTCTL_PDCE; - ctrl |=3D (PCI_EXP_SLTCTL_HPIE | - PCI_EXP_SLTCTL_DLLSCE); - } else { - ctrl |=3D (PCI_EXP_SLTCTL_HPIE | - PCI_EXP_SLTCTL_PDCE | - PCI_EXP_SLTCTL_DLLSCE); - } - pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, ctrl); - - /* The interrupt is initialized successfully when @irq is valid */ - php_slot->irq =3D irq; -} - -static void pcie_enable_irq(struct pnv_php_slot *php_slot) -{ - struct pci_dev *pdev =3D php_slot->pdev; - int irq, ret; - - if (!pdev) - return; - - /* - * The MSI/MSIx interrupt might have been occupied by other - * drivers. Don't populate the surprise hotplug capability - * in that case. - */ - if (pci_dev_msi_enabled(pdev)) - return; - - ret =3D pci_enable_device(pdev); - if (ret) { - SLOT_WARN(php_slot, "Error %d enabling device\n", ret); - return; - } - - pci_set_master(pdev); - - /* Enable MSIx interrupt */ - irq =3D pcie_enable_msix(php_slot); - if (irq > 0) { - pcie_init_irq(php_slot, irq); - return; - } - - /* - * Use MSI if MSIx doesn't work. Fail back to legacy INTx - * if MSI doesn't work either - */ - ret =3D pci_enable_msi(pdev); - if (!ret || pdev->irq) { - irq =3D pdev->irq; - pcie_init_irq(php_slot, irq); - } -} - static int pnv_php_register_one(struct device_node *dn) { struct pnv_php_slot *php_slot; --=20 2.54.0