From nobody Sat Feb 7 17:48:35 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 87CD21339A4; Wed, 12 Nov 2025 15:41: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=1762962068; cv=none; b=Vc3AStEZuq73fo3iN5kcJUq6oTBu2wuYkOTRceg9gfI34PEbWM9D4H8nqkk50XZzhKNYoEFE2+hhUvkXsXwgeCOTOcdt2q131DUlvu43k/+vsxBMK7wyJiy9S3RbY4YL28OkokxjKQwvVR2OsiD1HQEj9oKnZZcYEy8tHiTq7yk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762962068; c=relaxed/simple; bh=zD22bqyKwraBRhUj83aMTd4RxFbbpXqMswP7Be1a3AE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fYrXE8+DPpJ+fxphTV/vrq0myAxOpp7GgdxmfE03QCRlw91HNtW8BRpqJW3YHRS39H45fq7p3ekwuXCEZgeuPvbmn8XrK5pCtmJTmv6dc/JoQwfXRDM9/gRGJw5UUIMSdwOsujaeuW/6qxnBBW7gekyzgXlhRiA3ociXk0p6fmE= 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=L5gynTM0; 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="L5gynTM0" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 5AC5KrsF020676; Wed, 12 Nov 2025 15:40:49 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pp1; bh=WPtCvj Oy8xf8UDGt47QzHjX1Zr0mV/mEOHG069OitmU=; b=L5gynTM0TQBic8Im+fs2n6 m7poozeiPpZ2I4TIk5o93YWmeafFJkFSh7V7NHnMagknRwchBJZ3ko/foPtyGliv 6KR29EL/HsCfJvlLmyobhqIyBVPt/WXex4ajKU/PbC+aZaa6tWpcPtOwf8H/PQaX asRK1eNMvUbQwrfw4JFuAUSJF7FZdwJpqa+8tS1JCLlbtjD2BilF69AtmFk9A19x G6NZNN1rCgvIbHFaDZkompqV6XIB42zPa+3AkSNRifxRphbcGYiDrFPtfsEqo1cQ NjLF0q5cdiuI/E2280bnsZ3rll78zSaXwTHARnGpmDd2As/rO/kQ6AjBuYWXSpoA == Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4a9wk8ba9x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 12 Nov 2025 15:40:49 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 5ACDVFFd011600; Wed, 12 Nov 2025 15:40:48 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4aajw1gnm4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 12 Nov 2025 15:40:48 +0000 Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 5ACFej4D49283384 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 12 Nov 2025 15:40:45 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0762F20040; Wed, 12 Nov 2025 15:40:45 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CCC702004E; Wed, 12 Nov 2025 15:40:44 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 12 Nov 2025 15:40:44 +0000 (GMT) From: Tobias Schumacher Date: Wed, 12 Nov 2025 16:40:44 +0100 Subject: [PATCH 1/2] genirq: Change hwirq parameter to irq_hw_number_t Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251112-implement-msi-domain-v1-1-103dd123de14@linux.ibm.com> References: <20251112-implement-msi-domain-v1-0-103dd123de14@linux.ibm.com> In-Reply-To: <20251112-implement-msi-domain-v1-0-103dd123de14@linux.ibm.com> To: Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , Niklas Schnelle , Gerald Schaefer , Gerd Bayer , Halil Pasic , Matthew Rosato , Thomas Gleixner Cc: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Tobias Schumacher X-Mailer: b4 0.14.2 X-TM-AS-GCONF: 00 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA4MDAyMiBTYWx0ZWRfXyHIMdCWvSq6F wYYNweChsITjyZR2aXjUlnDVryqIYMQJQ//ouTXp15hWVDiWRusufX+beFPtPzmWwZ1OG7b685b +vlu2AL3tmYtXRrXJKmAHWW6ZUGP/HHrdxQCL6NeFWZLotEa3wMXckN+63wnzVQupkb79z/hLjc yXE1bgBIVjs3l49GAgCnFugPTI7pYVRYjPzkbdzef85CVOjOdm7+k/YlvBgO7IIUD7AXsDyTqcO DDOL1jrXZqEbAe3iaGkW+/54l0rjEP7aitsxo5Eku6r7TxsGRe6SwOxfBKCUUDP7u83sToh/gm3 AmMILDkagB+gME+rUg7t0xeB1leuxkIczaPSw9NEqCmlv6sMICAhxzUOVng/WNeoVl4Mu82+seL zgA57IagvHsLW8UW+W/sWUJOYwDg9g== X-Authority-Analysis: v=2.4 cv=ZK3aWH7b c=1 sm=1 tr=0 ts=6914aa81 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=IkcTkHD0fZMA:10 a=6UeiqGixMTsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=VnNF1IyMAAAA:8 a=ksSNG-jg9v29UnNErXoA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-ORIG-GUID: dd0i4D_0VNAskw4ManR5GHeElUGjHHvf X-Proofpoint-GUID: dd0i4D_0VNAskw4ManR5GHeElUGjHHvf X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-12_04,2025-11-11_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 phishscore=0 impostorscore=0 spamscore=0 bulkscore=0 adultscore=0 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2510240000 definitions=main-2511080022 The irqdomain implementation internally represents hardware IRQs as irq_hw_number_t, which is defined as unsigned long int. When providing an irq_hw_number_t to the generic_handle_domain() functions that expect and unsigned int hwirq, this can lead to a loss of information. Change the hwirq parameter to irq_hw_number_t to support the full range of hwirqs. Signed-off-by: Tobias Schumacher Reviewed-by: Thomas Gleixner --- include/linux/irqdesc.h | 6 +++--- kernel/irq/irqdesc.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index fd091c35d5721eee37a2fd3d5526559671d5048d..03b63aea73bb21ae1456910afa5= 34d60f9cfa94d 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -183,9 +183,9 @@ int generic_handle_irq_safe(unsigned int irq); * and handle the result interrupt number. Return -EINVAL if * conversion failed. */ -int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwir= q); -int generic_handle_domain_irq_safe(struct irq_domain *domain, unsigned int= hwirq); -int generic_handle_domain_nmi(struct irq_domain *domain, unsigned int hwir= q); +int generic_handle_domain_irq(struct irq_domain *domain, irq_hw_number_t h= wirq); +int generic_handle_domain_irq_safe(struct irq_domain *domain, irq_hw_numbe= r_t hwirq); +int generic_handle_domain_nmi(struct irq_domain *domain, irq_hw_number_t h= wirq); #endif =20 /* Test to see if a driver has successfully requested an irq */ diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index db714d3014b5f7b62403ea04b80331ec6b1dc642..0cd3198496bc0766c81c353c3ff= 80ea184793d6a 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -720,7 +720,7 @@ EXPORT_SYMBOL_GPL(generic_handle_irq_safe); * This function must be called from an IRQ context with irq regs * initialized. */ -int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwir= q) +int generic_handle_domain_irq(struct irq_domain *domain, irq_hw_number_t h= wirq) { return handle_irq_desc(irq_resolve_mapping(domain, hwirq)); } @@ -738,7 +738,7 @@ EXPORT_SYMBOL_GPL(generic_handle_domain_irq); * context). If the interrupt is marked as 'enforce IRQ-context only' then * the function must be invoked from hard interrupt context. */ -int generic_handle_domain_irq_safe(struct irq_domain *domain, unsigned int= hwirq) +int generic_handle_domain_irq_safe(struct irq_domain *domain, irq_hw_numbe= r_t hwirq) { unsigned long flags; int ret; @@ -761,7 +761,7 @@ EXPORT_SYMBOL_GPL(generic_handle_domain_irq_safe); * This function must be called from an NMI context with irq regs * initialized. **/ -int generic_handle_domain_nmi(struct irq_domain *domain, unsigned int hwir= q) +int generic_handle_domain_nmi(struct irq_domain *domain, irq_hw_number_t h= wirq) { WARN_ON_ONCE(!in_nmi()); return handle_irq_desc(irq_resolve_mapping(domain, hwirq)); --=20 2.48.1 From nobody Sat Feb 7 17:48:35 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (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 ADF953396F7; Wed, 12 Nov 2025 15:40:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762962060; cv=none; b=pboh25BiFKRj/iao9YFS7kFHcssIImF5ClBQegykYwVolKBijTWzqk2AVv4MpKLJECFXMniCZNiJh5hs8ebfSDl99wdBsutxeHTK2LlkEiY4fxeEQCk0RbhJDwcc3yc0je+gwep4fyTVjBHxkYep25yPOAfW/OdByj8+GvjxMls= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762962060; c=relaxed/simple; bh=K5Ng2yy8DZ5/UUJoTvWT/UaNFmfroIdi7KQwP6PWHXk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NOQOLD9tnliquNsyrEPC2Pv87iBMnraZOCyJnMg5weFJnvdygjZckP7Nz0VwtO86ezOpf0YDq5dsGeK9FQqYKL5C+4PnCL/MxutgV7Df0ajqym/OEyDdQu+iItvV5NSKM53Led8q+VW44vVTa4GNIoHxstkknuVvf1nUNvceRXo= 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=cZJICSS2; arc=none smtp.client-ip=148.163.158.5 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="cZJICSS2" Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 5ACBVWU3003484; Wed, 12 Nov 2025 15:40:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pp1; bh=gQBd34 jxgtfGGS1x+s+aV9obzKjXcFodLl/ye1zACy8=; b=cZJICSS2IcdlxvnnWyQKfX N5t1CxGXTxgZ/ryVaY2iwgUH+FrBKt3/oNTUGOknpWXIrKK7Fbd8PRL14xv9AZTd Bf6lhL9NGPh6+lTUK2h/GTo4NBOhdi6cFeMWqA/eHVAJzQWNjXq4zNoyQVriPmlk HkPBtz74CpOqgWHLPVdeBr3Qp5d+GNSfnsXUg8IFEx4O/qNKBNF21oiw5//CRQwn LifIeyqAS6tSsudIhyaayIdxFOUZik1okDhojkSMrgSzGxNNoqD5NBqr2iqiABUN MKe8n/jeyryF2Pyi+vuVnnW8t7U7AbxWY7V0Ms+PPKlzAXEfLtQdmblwkINkM+mQ == Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4a9wgx1xsv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 12 Nov 2025 15:40:50 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 5ACDSEMk008218; Wed, 12 Nov 2025 15:40:49 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4aah6n0ydm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 12 Nov 2025 15:40:49 +0000 Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 5ACFejuU49283388 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 12 Nov 2025 15:40:45 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4E2CC20040; Wed, 12 Nov 2025 15:40:45 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0BBC420043; Wed, 12 Nov 2025 15:40:45 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 12 Nov 2025 15:40:44 +0000 (GMT) From: Tobias Schumacher Date: Wed, 12 Nov 2025 16:40:45 +0100 Subject: [PATCH 2/2] s390/pci: Migrate s390 IRQ logic to IRQ domain API Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251112-implement-msi-domain-v1-2-103dd123de14@linux.ibm.com> References: <20251112-implement-msi-domain-v1-0-103dd123de14@linux.ibm.com> In-Reply-To: <20251112-implement-msi-domain-v1-0-103dd123de14@linux.ibm.com> To: Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Christian Borntraeger , Sven Schnelle , Niklas Schnelle , Gerald Schaefer , Gerd Bayer , Halil Pasic , Matthew Rosato , Thomas Gleixner Cc: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org, Tobias Schumacher X-Mailer: b4 0.14.2 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: HPmfIKOjyT1Zf_SyrSDseYG8mS2Z1sei X-Proofpoint-ORIG-GUID: HPmfIKOjyT1Zf_SyrSDseYG8mS2Z1sei X-Authority-Analysis: v=2.4 cv=VMPQXtPX c=1 sm=1 tr=0 ts=6914aa82 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=IkcTkHD0fZMA:10 a=6UeiqGixMTsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=ZWjmTSsJ56F6Ip2C3hIA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTA4MDAyMiBTYWx0ZWRfXwhpXMUupSUif c1q1n85BPSG4D2nTpdlWIaaV5pg69M309Z3wfAInlA09R7gjRprq0WMba4eCJuabFIRYutYDovn auVvWGjkVMNYWZIPEhQGOeMYK3jJBhUkAqOQWnLcrCRs9JSkl1m4bRsf8bZASp+ttnofORLKYrR TeaV3dB2pkuZc5FvMVtVm1cyxdeC9FJp8lpu8X1SxdIJvjz4t5hIySp4soZUK+4OiKj9bpTAMrn LcICY5nZdTV4lPgAEBi3b9rfi/g0M00Tj7DH2J+zh3Hjiv9o1kSdSdD1K75qm2SP1OQLDabErj0 8U46M67OJp2lC6oaQWD+VtINNU9kHmdtXtHgKqPyMA05tqF5+JNFM0ZTcRGU67EB+NXvEJrQLlG Etrs8b8IGQFgrWKjfmr1VHgsg3qyZA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.9,FMLib:17.12.100.49 definitions=2025-11-12_04,2025-11-11_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 priorityscore=1501 lowpriorityscore=0 bulkscore=0 clxscore=1015 phishscore=0 spamscore=0 malwarescore=0 adultscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2510240000 definitions=main-2511080022 s390 is one of the last architectures using the legacy API for setup and teardown of PCI MSI IRQs. Migrate the s390 IRQ allocation and teardown to the MSI parent domain API. For details, see: https://lore.kernel.org/lkml/20221111120501.026511281@linutronix.de In detail, create an MSI parent domain for zpci which is used by all PCI devices. When a PCI device sets up MSI or MSI-X IRQs, the library creates a per-device IRQ domain for this device, which is be used by the device for allocating and freeing IRQs. The per-device domain delegates this allocation and freeing to the parent-domain. In the end, the corresponding callbacks of the parent domain are responsible for allocating and freeing the IRQs. The allocation is split into two parts: - zpci_msi_prepare() is called once for each device and allocates the required resources. On s390, each PCI function has its own airq vector and a summary bit, which must be configured once per function. This is done in prepare(). - zpci_msi_alloc() can be called multiple times for allocating one or more MSI/MSI-X IRQs. This creates a mapping between the virtual IRQ number in the kernel and the hardware IRQ number. Freeing is split into two counterparts: - zpci_msi_free() reverts the effects of zpci_msi_alloc() and - zpci_msi_teardown() reverts the effects of zpci_msi_prepare(). This is callend once when all IRQs are freed before a device is removed. Since the parent domain in the end allocates the IRQs, the hwirq encoding must be unambiguous for all IRQs of all devices. This is achieved by encoding the hwirq using the PCI function id and the MSI index. Signed-off-by: Tobias Schumacher --- arch/s390/Kconfig | 1 + arch/s390/include/asm/pci.h | 1 + arch/s390/pci/pci_bus.c | 1 + arch/s390/pci/pci_irq.c | 323 +++++++++++++++++++++++++++-------------= ---- 4 files changed, 203 insertions(+), 123 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index df22b10d91415e1ed183cc8add9ad0ac4293c50e..739a9a9a86a277be1ba750cb2e9= 8af0547df89fd 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -251,6 +251,7 @@ config S390 select HOTPLUG_SMT select IOMMU_HELPER if PCI select IOMMU_SUPPORT if PCI + select IRQ_MSI_LIB if PCI select KASAN_VMALLOC if KASAN select LOCK_MM_AND_FIND_VMA select MMU_GATHER_MERGE_VMAS diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index a32f465ecf73a5cc3408a312d94ec888d62848cc..462e87bdb7acdfa4e7df0f9ca8e= 82c269e1f98aa 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -310,6 +310,7 @@ int zpci_dma_exit_device(struct zpci_dev *zdev); /* IRQ */ int __init zpci_irq_init(void); void __init zpci_irq_exit(void); +void zpci_set_msi_parent_domain(struct zpci_bus *zbus); =20 /* FMB */ int zpci_fmb_enable_device(struct zpci_dev *); diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index be8c697fea0cc755cfdb4fb0a9e3b95183bec0dc..2be33cfb8970409db4fcb75ea73= 543f49b583a5c 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -210,6 +210,7 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *zbu= s, struct zpci_dev *fr, s } =20 zbus->bus =3D bus; + zpci_set_msi_parent_domain(zbus); =20 return 0; } diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index e73be96ce5fe6473fc193d65b8f0ff635d6a98ba..7412906b5fec695aa62155a8ecc= 34fb1f93e0f4b 100644 --- a/arch/s390/pci/pci_irq.c +++ b/arch/s390/pci/pci_irq.c @@ -7,6 +7,7 @@ #include #include #include +#include #include =20 #include @@ -29,6 +30,8 @@ static struct airq_iv *zpci_sbv; */ static struct airq_iv **zpci_ibv; =20 +static struct irq_domain *zpci_msi_parent_domain; + /* Modify PCI: Register floating adapter interruptions */ static int zpci_set_airq(struct zpci_dev *zdev) { @@ -110,19 +113,6 @@ static int zpci_set_irq(struct zpci_dev *zdev) return rc; } =20 -/* Clear adapter interruptions */ -static int zpci_clear_irq(struct zpci_dev *zdev) -{ - int rc; - - if (irq_delivery =3D=3D DIRECTED) - rc =3D zpci_clear_directed_irq(zdev); - else - rc =3D zpci_clear_airq(zdev); - - return rc; -} - static int zpci_set_irq_affinity(struct irq_data *data, const struct cpuma= sk *dest, bool force) { @@ -137,16 +127,40 @@ static int zpci_set_irq_affinity(struct irq_data *dat= a, const struct cpumask *de return IRQ_SET_MASK_OK; } =20 +static void zpci_compose_msi_msg(struct irq_data *data, struct msi_msg *ms= g) +{ + struct msi_desc *desc =3D irq_data_get_msi_desc(data); + struct zpci_dev *zdev =3D to_zpci_dev(desc->dev); + + if (irq_delivery =3D=3D DIRECTED) { + int cpu =3D 0; + + if (desc->affinity) + cpu =3D cpumask_first(&desc->affinity->mask); + else + cpu =3D 0; + msg->address_lo =3D zdev->msi_addr & 0xff0000ff; + msg->address_lo |=3D (smp_cpu_get_cpu_address(cpu) << 8); + } else { + msg->address_lo =3D zdev->msi_addr & 0xffffffff; + } + msg->address_hi =3D zdev->msi_addr >> 32; + msg->data =3D data->hwirq - zdev->msi_first_bit; +} + static struct irq_chip zpci_irq_chip =3D { .name =3D "PCI-MSI", + .irq_set_affinity =3D irq_chip_set_affinity_parent, .irq_unmask =3D pci_msi_unmask_irq, .irq_mask =3D pci_msi_mask_irq, + .irq_compose_msi_msg =3D zpci_compose_msi_msg }; =20 static void zpci_handle_cpu_local_irq(bool rescan) { struct airq_iv *dibv =3D zpci_ibv[smp_processor_id()]; union zpci_sic_iib iib =3D {{0}}; + irq_hw_number_t hwirq; unsigned long bit; int irqs_on =3D 0; =20 @@ -164,7 +178,8 @@ static void zpci_handle_cpu_local_irq(bool rescan) continue; } inc_irq_stat(IRQIO_MSI); - generic_handle_irq(airq_iv_get_data(dibv, bit)); + hwirq =3D airq_iv_get_ptr(dibv, bit); + generic_handle_domain_irq(zpci_msi_parent_domain, hwirq); } } =20 @@ -229,6 +244,7 @@ static void zpci_floating_irq_handler(struct airq_struc= t *airq, struct tpi_info *tpi_info) { union zpci_sic_iib iib =3D {{0}}; + irq_hw_number_t hwirq; unsigned long si, ai; struct airq_iv *aibv; int irqs_on =3D 0; @@ -256,7 +272,9 @@ static void zpci_floating_irq_handler(struct airq_struc= t *airq, break; inc_irq_stat(IRQIO_MSI); airq_iv_lock(aibv, ai); - generic_handle_irq(airq_iv_get_data(aibv, ai)); + + hwirq =3D airq_iv_get_ptr(aibv, ai); + generic_handle_domain_irq(zpci_msi_parent_domain, hwirq); airq_iv_unlock(aibv, ai); } } @@ -278,7 +296,7 @@ static int __alloc_airq(struct zpci_dev *zdev, int msi_= vecs, zdev->aisb =3D *bit; =20 /* Create adapter interrupt vector */ - zdev->aibv =3D airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK, = NULL); + zdev->aibv =3D airq_iv_create(msi_vecs, AIRQ_IV_PTR | AIRQ_IV_BITLOCK, N= ULL); if (!zdev->aibv) return -ENOMEM; =20 @@ -290,146 +308,197 @@ static int __alloc_airq(struct zpci_dev *zdev, int = msi_vecs, return 0; } =20 -int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) +static struct airq_struct zpci_airq =3D { + .handler =3D zpci_floating_irq_handler, + .isc =3D PCI_ISC, +}; + +/* + * Encode the hwirq number for the parent domain. The encoding must be uni= que + * for each IRQ of each device in the parent domain, so it uses the fid to + * identify the device and the msi_index to identify the IRQ within that d= evice. + */ +static inline irq_hw_number_t zpci_encode_hwirq(u32 fid, u16 msi_index) { - unsigned int hwirq, msi_vecs, irqs_per_msi, i, cpu; - struct zpci_dev *zdev =3D to_zpci(pdev); - struct msi_desc *msi; - struct msi_msg msg; - unsigned long bit; - int cpu_addr; - int rc, irq; + return ((irq_hw_number_t)fid << 32) | msi_index; +} =20 - zdev->aisb =3D -1UL; - zdev->msi_first_bit =3D -1U; +static inline u16 zpci_decode_hwirq_msi_index(irq_hw_number_t irq) +{ + return irq & 0xFFFF; +} + +static int zpci_msi_prepare(struct irq_domain *domain, + struct device *dev, int nvec, + msi_alloc_info_t *info) +{ + struct zpci_dev *zdev =3D to_zpci_dev(dev); + struct pci_dev *pdev =3D to_pci_dev(dev); + unsigned long bit; + int msi_vecs, rc; =20 msi_vecs =3D min_t(unsigned int, nvec, zdev->max_msi); - if (msi_vecs < nvec) { + if (msi_vecs < nvec) pr_info("%s requested %d irqs, allocate system limit of %d", pci_name(pdev), nvec, zdev->max_msi); - } =20 rc =3D __alloc_airq(zdev, msi_vecs, &bit); - if (rc < 0) + if (rc) { + pr_err("Allocating AIRQ for %s failed\n", pci_name(pdev)); return rc; + } =20 - /* - * Request MSI interrupts: - * When using MSI, nvec_used interrupt sources and their irq - * descriptors are controlled through one msi descriptor. - * Thus the outer loop over msi descriptors shall run only once, - * while two inner loops iterate over the interrupt vectors. - * When using MSI-X, each interrupt vector/irq descriptor - * is bound to exactly one msi descriptor (nvec_used is one). - * So the inner loops are executed once, while the outer iterates - * over the MSI-X descriptors. - */ - hwirq =3D bit; - msi_for_each_desc(msi, &pdev->dev, MSI_DESC_NOTASSOCIATED) { - if (hwirq - bit >=3D msi_vecs) - break; - irqs_per_msi =3D min_t(unsigned int, msi_vecs, msi->nvec_used); - irq =3D __irq_alloc_descs(-1, 0, irqs_per_msi, 0, THIS_MODULE, - (irq_delivery =3D=3D DIRECTED) ? - msi->affinity : NULL); - if (irq < 0) - return -ENOMEM; - - for (i =3D 0; i < irqs_per_msi; i++) { - rc =3D irq_set_msi_desc_off(irq, i, msi); - if (rc) - return rc; - irq_set_chip_and_handler(irq + i, &zpci_irq_chip, - handle_percpu_irq); - } - - msg.data =3D hwirq - bit; + zdev->msi_first_bit =3D bit; + rc =3D zpci_set_irq(zdev); + if (rc) { + pr_err("Registering floating adapter interruptions for %s failed\n", + pci_name(pdev)); if (irq_delivery =3D=3D DIRECTED) { - if (msi->affinity) - cpu =3D cpumask_first(&msi->affinity->mask); - else - cpu =3D 0; - cpu_addr =3D smp_cpu_get_cpu_address(cpu); - - msg.address_lo =3D zdev->msi_addr & 0xff0000ff; - msg.address_lo |=3D (cpu_addr << 8); - - for_each_possible_cpu(cpu) { - for (i =3D 0; i < irqs_per_msi; i++) - airq_iv_set_data(zpci_ibv[cpu], - hwirq + i, irq + i); - } + airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, msi_vecs); } else { - msg.address_lo =3D zdev->msi_addr & 0xffffffff; - for (i =3D 0; i < irqs_per_msi; i++) - airq_iv_set_data(zdev->aibv, hwirq + i, irq + i); + zpci_clear_airq(zdev); + airq_iv_release(zdev->aibv); + zdev->aibv =3D NULL; + airq_iv_free_bit(zpci_sbv, zdev->aisb); + zdev->aisb =3D -1UL; } - msg.address_hi =3D zdev->msi_addr >> 32; - pci_write_msi_msg(irq, &msg); - hwirq +=3D irqs_per_msi; + zdev->msi_first_bit =3D -1U; + return rc; } =20 - zdev->msi_first_bit =3D bit; - zdev->msi_nr_irqs =3D hwirq - bit; + zdev->msi_nr_irqs =3D msi_vecs; =20 - rc =3D zpci_set_irq(zdev); - if (rc) - return rc; + return 0; +} =20 - return (zdev->msi_nr_irqs =3D=3D nvec) ? 0 : zdev->msi_nr_irqs; +static void zpci_msi_teardown_directed(struct zpci_dev *zdev) +{ + zpci_clear_directed_irq(zdev); + airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->max_msi); + zdev->msi_first_bit =3D -1U; } =20 -void arch_teardown_msi_irqs(struct pci_dev *pdev) +static void zpci_msi_teardown_floating(struct zpci_dev *zdev) { - struct zpci_dev *zdev =3D to_zpci(pdev); - struct msi_desc *msi; - unsigned int i; - int rc; + zpci_clear_airq(zdev); + airq_iv_release(zdev->aibv); + zdev->aibv =3D NULL; + airq_iv_free_bit(zpci_sbv, zdev->aisb); + zdev->aisb =3D -1UL; + zdev->msi_first_bit =3D -1U; +} =20 - /* Disable interrupts */ - rc =3D zpci_clear_irq(zdev); - if (rc) - return; +static void zpci_msi_teardown(struct irq_domain *domain, msi_alloc_info_t = *arg) +{ + struct zpci_dev *zdev =3D to_zpci_dev(domain->dev); + + if (irq_delivery =3D=3D DIRECTED) + zpci_msi_teardown_directed(zdev); + else + zpci_msi_teardown_floating(zdev); +} + +static int zpci_msi_domain_alloc(struct irq_domain *domain, unsigned int v= irq, + unsigned int nr_irqs, void *args) +{ + struct msi_desc *desc =3D ((msi_alloc_info_t *)args)->desc; + struct zpci_dev *zdev =3D to_zpci_dev(desc->dev); + irq_hw_number_t hwirq; + unsigned long bit; + int i; + + bit =3D zdev->msi_first_bit + desc->msi_index; + hwirq =3D zpci_encode_hwirq(zdev->fid, desc->msi_index); + + if (desc->msi_index + nr_irqs > zdev->max_msi) + return -EINVAL; + + for (i =3D 0; i < nr_irqs; i++) { + irq_domain_set_info(domain, virq + i, hwirq + i, + &zpci_irq_chip, zdev, + handle_percpu_irq, NULL, NULL); =20 - /* Release MSI interrupts */ - msi_for_each_desc(msi, &pdev->dev, MSI_DESC_ASSOCIATED) { - for (i =3D 0; i < msi->nvec_used; i++) { - irq_set_msi_desc(msi->irq + i, NULL); - irq_free_desc(msi->irq + i); + if (irq_delivery =3D=3D DIRECTED) { + airq_iv_set_ptr(zpci_ibv[smp_processor_id()], + bit + i, hwirq + i); + } else { + airq_iv_set_ptr(zdev->aibv, bit + i, hwirq + i); } - msi->msg.address_lo =3D 0; - msi->msg.address_hi =3D 0; - msi->msg.data =3D 0; - msi->irq =3D 0; } =20 - if (zdev->aisb !=3D -1UL) { - zpci_ibv[zdev->aisb] =3D NULL; - airq_iv_free_bit(zpci_sbv, zdev->aisb); - zdev->aisb =3D -1UL; - } - if (zdev->aibv) { - airq_iv_release(zdev->aibv); - zdev->aibv =3D NULL; - } + return 0; +} =20 - if ((irq_delivery =3D=3D DIRECTED) && zdev->msi_first_bit !=3D -1U) - airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->msi_nr_irqs); +static void zpci_msi_domain_free(struct irq_domain *domain, unsigned int v= irq, + unsigned int nr_irqs) +{ + irq_hw_number_t hwirq; + struct irq_data *d; + u16 msi_index; + int i; + + for (i =3D 0; i < nr_irqs; i++) { + d =3D irq_domain_get_irq_data(domain, virq + i); + hwirq =3D d->hwirq; + msi_index =3D zpci_decode_hwirq_msi_index(hwirq); + irq_domain_reset_irq_data(d); + } } =20 -bool arch_restore_msi_irqs(struct pci_dev *pdev) +static const struct irq_domain_ops zpci_msi_domain_ops =3D { + .alloc =3D zpci_msi_domain_alloc, + .free =3D zpci_msi_domain_free +}; + +static bool zpci_init_dev_msi_info(struct device *dev, struct irq_domain *= domain, + struct irq_domain *real_parent, + struct msi_domain_info *info) { - struct zpci_dev *zdev =3D to_zpci(pdev); + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) + return false; + + info->ops->msi_prepare =3D zpci_msi_prepare; + info->ops->msi_teardown =3D zpci_msi_teardown; =20 - zpci_set_irq(zdev); return true; } =20 -static struct airq_struct zpci_airq =3D { - .handler =3D zpci_floating_irq_handler, - .isc =3D PCI_ISC, +static const struct msi_parent_ops zpci_msi_parent_ops =3D { + .supported_flags =3D MSI_GENERIC_FLAGS_MASK | + MSI_FLAG_PCI_MSIX | + MSI_FLAG_MULTI_PCI_MSI, + .required_flags =3D MSI_FLAG_USE_DEF_DOM_OPS | + MSI_FLAG_USE_DEF_CHIP_OPS | + MSI_FLAG_PCI_MSI_MASK_PARENT, + .init_dev_msi_info =3D zpci_init_dev_msi_info }; =20 +static int __init zpci_create_parent_msi_domain(void) +{ + struct irq_domain_info info =3D { + .fwnode =3D irq_domain_alloc_named_fwnode("zpci_msi"), + .ops =3D &zpci_msi_domain_ops + }; + if (!info.fwnode) { + pr_err("Failed to allocate fwnode for MSI IRQ domain\n"); + return -ENOMEM; + } + + zpci_msi_parent_domain =3D msi_create_parent_irq_domain(&info, &zpci_msi_= parent_ops); + if (!zpci_msi_parent_domain) { + irq_domain_free_fwnode(info.fwnode); + pr_err("Failed to create MSI IRQ domain\n"); + return -ENOMEM; + } + + return 0; +} + +void zpci_set_msi_parent_domain(struct zpci_bus *zbus) +{ + dev_set_msi_domain(&zbus->bus->dev, zpci_msi_parent_domain); +} + static void __init cpu_enable_directed_irq(void *unused) { union zpci_sic_iib iib =3D {{0}}; @@ -466,7 +535,7 @@ static int __init zpci_directed_irq_init(void) * is only done on the first vector. */ zpci_ibv[cpu] =3D airq_iv_create(cache_line_size() * BITS_PER_BYTE, - AIRQ_IV_DATA | + AIRQ_IV_PTR | AIRQ_IV_CACHELINE | (!cpu ? AIRQ_IV_ALLOC : 0), NULL); if (!zpci_ibv[cpu]) @@ -511,6 +580,11 @@ int __init zpci_irq_init(void) rc =3D register_adapter_interrupt(&zpci_airq); if (rc) goto out; + + zpci_create_parent_msi_domain(); + if (!zpci_msi_parent_domain) + goto out_airq; + /* Set summary to 1 to be called every time for the ISC. */ *zpci_airq.lsi_ptr =3D 1; =20 @@ -524,7 +598,7 @@ int __init zpci_irq_init(void) } =20 if (rc) - goto out_airq; + goto out_msi_domain; =20 /* * Enable floating IRQs (with suppression after one IRQ). When using @@ -533,6 +607,8 @@ int __init zpci_irq_init(void) zpci_set_irq_ctrl(SIC_IRQ_MODE_SINGLE, PCI_ISC, &iib); =20 return 0; +out_msi_domain: + irq_domain_remove(zpci_msi_parent_domain); out_airq: unregister_adapter_interrupt(&zpci_airq); out: @@ -549,6 +625,7 @@ void __init zpci_irq_exit(void) } } kfree(zpci_ibv); + irq_domain_remove(zpci_msi_parent_domain); if (zpci_sbv) airq_iv_release(zpci_sbv); unregister_adapter_interrupt(&zpci_airq); --=20 2.48.1