From nobody Fri Dec 19 21:10:00 2025 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 0D2322FFDDA; Wed, 3 Dec 2025 14:37:01 +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=1764772624; cv=none; b=a8JqTd94LMYHgVwfpLvGpcEmjpZLvdpG114fj/1Is1tLLir5KexDqlkBSlDBrO2SP64nNgtBaypLDAqQqRU6JbOvk1FO4FeM5+LVuEYupbVew9HZnHX1hgBUfVah9E1PkdcQyFOBWTyK0S84HwzsqUidRu6bg3UXLFb4Sa6dyHs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764772624; c=relaxed/simple; bh=h+0JO5F1BsCL6T/czUkyOQMStbUrks45PvRwGKRVQak=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A93opzAUmTSiKplFUXHID308ceXq8W4rRVmPBPM7pljfOCUcN/WRB94u8TKTcbolmGsvS7/e4viQePBCmufUl+kDpRFT6YQcBoPtH9oVQrEaXPY7UTKONbTbdYXox6v0NclIKRcKAekm+B+JN1R2HE0LPynz6ySIZrdY0VStJQA= 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=WSqatb1R; 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="WSqatb1R" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 5B33hGGk018535; Wed, 3 Dec 2025 14:36:46 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=8fugNI aWueeCYJGLShvhSZYH/P22+ioQYQT4sBg2aJs=; b=WSqatb1R6UjJzSNlXawwGo URQvD+MHHMFmh9qkyEvSANAKSU5JYb+PDwKUWHhtQCvySleAgOdmEg4Zv8fQhtjc 2O+7Ygwv6TQdFfH4y99TN/j/FepBf/1z6wVK7rqbdOo6UFKIHx1tZibx5JTnqCAK JryqFtlu5MAaJS2U/2Z6HMz+D5r02l69CYElxFcIbCFjYDDvVDPsh2trdrXYCsIC WbrCDxqqnl4LFlgeNMqhKL9wWAEHUHEp6oPJ3dSMvPlItpCFFJXfnnAaWPRUNb+m 0kNr8GZfDOo4yW2OaUXwxG9av8PE6Jueo/i+GzjVOH4xPUuIZQufAjJAMjfXyCIg == 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 4aqp8q2xrg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 03 Dec 2025 14:36:46 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 5B3Djoi8010237; Wed, 3 Dec 2025 14:36:45 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4arcnkafxs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 03 Dec 2025 14:36:45 +0000 Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 5B3EafFl24904164 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 3 Dec 2025 14:36:41 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7842120040; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 46C3A2004B; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) From: Tobias Schumacher Date: Wed, 03 Dec 2025 15:36:29 +0100 Subject: [PATCH v8 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: <20251203-implement-msi-domain-v8-1-94836907490b@linux.ibm.com> References: <20251203-implement-msi-domain-v8-0-94836907490b@linux.ibm.com> In-Reply-To: <20251203-implement-msi-domain-v8-0-94836907490b@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 , Farhan Ali X-Mailer: b4 0.14.2 X-TM-AS-GCONF: 00 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTI5MDAwMCBTYWx0ZWRfX5LyXBATSuTUU LRlWBQyDDqFU21vUAWpB9lLK01gp+aFHIlTAHLvrd5AUPSZeNHYqsktWBG76acHLl8O/Odk8qNK C3WjOHaUlQVEqfRYRyT/ij9SCHDXqSuRpoRvk2fvLSEUPfy2psjibt1+n5Ly1zlXDrQb0Ya1Pbd Kr+4b7uSWBuqZMw10r9y+DmT0PeAQmQgrDNyJOq9o2O8oy4Jg4ZLmkCzSGmknUW2n22o9ulG33x RrmDDn8bpG8/xdb0WgCnZykZYz3QsLESebmkfnuMiPonkjLr1XvyNnUXLxG2ihS/41HSrEqR4yi 8rVuE5wQ0+PNMjQkhToIomWdZDeqbKDb18f9o+qQdM+nb4ggWvQvI0iO3DCdFuo4Sm7Mb2tV/xk kUNK8YgJsQwR/XAQYbGG6IAulD/bGA== X-Authority-Analysis: v=2.4 cv=dIerWeZb c=1 sm=1 tr=0 ts=69304afe cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=IkcTkHD0fZMA:10 a=wP3pNCr1ah4A:10 a=VkNPw1HP01LnGYTKEx00:22 a=VnNF1IyMAAAA:8 a=apPMBW2BC5_Ovgk0KuUA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-ORIG-GUID: -v4slcApNUbSLxjliS8xVpXu83Tpo2J6 X-Proofpoint-GUID: -v4slcApNUbSLxjliS8xVpXu83Tpo2J6 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-12-03_01,2025-11-27_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 spamscore=0 malwarescore=0 suspectscore=0 adultscore=0 bulkscore=0 impostorscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2510240000 definitions=main-2511290000 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. Reviewed-by: Thomas Gleixner Reviewed-by: Niklas Schnelle Reviewed-by: Farhan Ali Signed-off-by: Tobias Schumacher --- 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.51.0 From nobody Fri Dec 19 21:10:00 2025 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 ACF292FF164; Wed, 3 Dec 2025 14:36:50 +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=1764772613; cv=none; b=brGhBmypqWJQ0IgI2tYZJjhYik+JrYrcrtpOZjBvtEYngBZ2Qlm8hSgzGwkw1ZYZyKoXntmnOrUYrSO1/CPLXZsFowyrDy5+dcEyQJL3OHVBtG6hpM9SdZyJmDPsplTDZrJrNH1x5+pq6nZZHnSkvbL/K6BGK4ROMNx7HbyT3Qs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764772613; c=relaxed/simple; bh=k+ghMg+qDAL0qRdrBlG1uYI1mFR+0RJ6YT+oLyVGzNg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KlDFaLC6N8z9fha4GH3C0N9ZnF14qmJijVzGCBv9OV7uWBg+oK8x3W4zyo0RdrQku71kOa1AMVQrsTYvBEey8wHbiOl1TyJOQKesRlKhBaeqPdp49OvMy362y8vSEWnnIJMLGgtgbZaNtHHScfokPwCRcXh9MUgGDn/YbwD4aMA= 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=Ed1FCWA8; 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="Ed1FCWA8" Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 5B3Cg5Nf006483; Wed, 3 Dec 2025 14:36:46 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=7+FLk7 hz4AaTy1yyZYg5pJixWhgm9rbeQbNUDl2siA4=; b=Ed1FCWA81TqFab1+rLoNOT eEPR41Ua0Z/rVWkzfSDBXgsfueoSrekTn9wtA+NTAxe/Chrv4kGgPQTkjGBjf3Fy SHwvZi+qF2ZkHe5jFnt2yp4Sb68GqGLMmM+zBJbc7tn6XyP4Z4qyzgZLyO/6kZ2d 3XoSkxTl5/IVN5rQ4Ane/ae6Wd087bh9/svCxXnmzVg9710hPFsqZbGD7OpTU200 Bhkku4JW1OPMxB0K/Su0yXywWAkPP/vESZNpOlmIVh/TtzFRZSYzwsbrGc2UPliD qg7XIOmtYvtC5snTgdwuavKGziSpv3JFcwcXGD5K3w1bTI+o3PHcmBSR+VZ7cedw == 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 4aqrbgbbut-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 03 Dec 2025 14:36:46 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 5B3E5oUR003847; Wed, 3 Dec 2025 14:36:45 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4ardcjtabn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 03 Dec 2025 14:36:45 +0000 Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 5B3EafxY24904166 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 3 Dec 2025 14:36:41 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BFD6120040; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7C7B320043; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Wed, 3 Dec 2025 14:36:41 +0000 (GMT) From: Tobias Schumacher Date: Wed, 03 Dec 2025 15:36:30 +0100 Subject: [PATCH v8 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: <20251203-implement-msi-domain-v8-2-94836907490b@linux.ibm.com> References: <20251203-implement-msi-domain-v8-0-94836907490b@linux.ibm.com> In-Reply-To: <20251203-implement-msi-domain-v8-0-94836907490b@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 , Farhan Ali X-Mailer: b4 0.14.2 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: VNHsedZ2vJtSTKLV2-4AeU628TdcvJkt X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMTI5MDAxNiBTYWx0ZWRfX0Ey9ZwVncvNZ 9SSO+x8Vl6mZwleI7j2zlpHjbtr05xl6OjB5+s8N/qqMUXRe9ma81Hkwr+DUDZS8duhLDKoYa3S w4J8js2KutHXYe1b2bgXQfJNBRM3apFaLXuS6UH4bxpWis6fY557fp3ZBAc3DZ7NGk1QVNjp6Al v1NRBO7Gc1tAF9n9xqbVwlH0USEOSrhUuy1G8UiwFYuZ3lO4GlYAipKDkngE2eXvbqLNvZdE8dB AKomz7EdrzlSomsv/FGykKbz81Nu6xkGnsTKqxRoabrdFrsK2sHLQJue7ZpKnWM/4LMqgQBzqEc kYnA0qmhIJTrxPuJm4tkMOKIgGhUsONik3/BqYcXLKXpGixZjcm9VZHw34GPvA7Rwwai1moEou6 OR35pM+vDbBiUg/U/blzHrRHxPKS1Q== X-Authority-Analysis: v=2.4 cv=UO7Q3Sfy c=1 sm=1 tr=0 ts=69304afe cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=IkcTkHD0fZMA:10 a=wP3pNCr1ah4A:10 a=VkNPw1HP01LnGYTKEx00:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pn-msHsI0j841b3IYMsA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-GUID: VNHsedZ2vJtSTKLV2-4AeU628TdcvJkt 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-12-03_01,2025-11-27_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 malwarescore=0 bulkscore=0 adultscore=0 priorityscore=1501 impostorscore=0 spamscore=0 phishscore=0 clxscore=1015 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2510240000 definitions=main-2511290016 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 each PCI domain. When a PCI device sets up MSI or MSI-X IRQs, the library creates a per-device IRQ domain for this device, which is 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 called 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 devfn and the MSI index. Reviewed-by: Niklas Schnelle Reviewed-by: Farhan Ali Signed-off-by: Tobias Schumacher --- arch/s390/Kconfig | 1 + arch/s390/include/asm/pci.h | 5 + arch/s390/pci/pci.c | 6 + arch/s390/pci/pci_bus.c | 18 ++- arch/s390/pci/pci_irq.c | 329 +++++++++++++++++++++++++++++-----------= ---- 5 files changed, 244 insertions(+), 115 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 778ce20d34046cad84dd4ef57cab5a662e5796d9..fc82dd4f893d78f12837f36ab82= a05f2c52e0501 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..0aa6915346a50077f22868cef39= 638919979d478 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,7 @@ struct zpci_bus { struct list_head resources; struct list_head bus_next; struct resource bus_resource; + struct irq_domain *msi_parent_domain; int topo; /* TID if topo_is_tid, PCHID otherwise */ int domain_nr; u8 multifunction : 1; @@ -310,6 +312,9 @@ int zpci_dma_exit_device(struct zpci_dev *zdev); /* IRQ */ int __init zpci_irq_init(void); void __init zpci_irq_exit(void); +int zpci_set_irq(struct zpci_dev *zdev); +int zpci_create_parent_msi_domain(struct zpci_bus *zbus); +void zpci_remove_parent_msi_domain(struct zpci_bus *zbus); =20 /* FMB */ int zpci_fmb_enable_device(struct zpci_dev *); diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index c82c577db2bcd2143476cb8189fd89b9a4dc9836..2e47bf6a3289615307c71cae7b0= 4ef77d964144a 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -709,6 +709,12 @@ int zpci_reenable_device(struct zpci_dev *zdev) if (rc) return rc; =20 + if (zdev->msi_nr_irqs > 0) { + rc =3D zpci_set_irq(zdev); + if (rc) + return rc; + } + rc =3D zpci_iommu_register_ioat(zdev, &status); if (rc) zpci_disable_device(zdev); diff --git a/arch/s390/pci/pci_bus.c b/arch/s390/pci/pci_bus.c index be8c697fea0cc755cfdb4fb0a9e3b95183bec0dc..2d7b389f36e8682c3f0a10befe8= 7698751596584 100644 --- a/arch/s390/pci/pci_bus.c +++ b/arch/s390/pci/pci_bus.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -199,19 +200,27 @@ static int zpci_bus_create_pci_bus(struct zpci_bus *z= bus, struct zpci_dev *fr, s zbus->multifunction =3D zpci_bus_is_multifunction_root(fr); zbus->max_bus_speed =3D fr->max_bus_speed; =20 + if (zpci_create_parent_msi_domain(zbus)) + goto out_free_domain; + /* * Note that the zbus->resources are taken over and zbus->resources * is empty after a successful call */ bus =3D pci_create_root_bus(NULL, ZPCI_BUS_NR, ops, zbus, &zbus->resource= s); - if (!bus) { - zpci_free_domain(zbus->domain_nr); - return -EFAULT; - } + if (!bus) + goto out_remove_msi_domain; =20 zbus->bus =3D bus; + dev_set_msi_domain(&zbus->bus->dev, zbus->msi_parent_domain); =20 return 0; + +out_remove_msi_domain: + zpci_remove_parent_msi_domain(zbus); +out_free_domain: + zpci_free_domain(zbus->domain_nr); + return -ENOMEM; } =20 static void zpci_bus_release(struct kref *kref) @@ -232,6 +241,7 @@ static void zpci_bus_release(struct kref *kref) mutex_lock(&zbus_list_lock); list_del(&zbus->bus_next); mutex_unlock(&zbus_list_lock); + zpci_remove_parent_msi_domain(zbus); kfree(zbus); } =20 diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c index e73be96ce5fe6473fc193d65b8f0ff635d6a98ba..e1c5e683c2a6eef1806284adb43= 3a3cdf4c69b9a 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 @@ -98,7 +99,7 @@ static int zpci_clear_directed_irq(struct zpci_dev *zdev) } =20 /* Register adapter interruptions */ -static int zpci_set_irq(struct zpci_dev *zdev) +int zpci_set_irq(struct zpci_dev *zdev) { int rc; =20 @@ -126,27 +127,53 @@ static int zpci_clear_irq(struct zpci_dev *zdev) static int zpci_set_irq_affinity(struct irq_data *data, const struct cpuma= sk *dest, bool force) { - struct msi_desc *entry =3D irq_data_get_msi_desc(data); - struct msi_msg msg =3D entry->msg; - int cpu_addr =3D smp_cpu_get_cpu_address(cpumask_first(dest)); + irq_data_update_affinity(data, dest); + return IRQ_SET_MASK_OK; +} =20 - msg.address_lo &=3D 0xff0000ff; - msg.address_lo |=3D (cpu_addr << 8); - pci_write_msi_msg(data->irq, &msg); +/* + * 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 devfn = to + * identify the device and the msi_index to identify the IRQ within that d= evice. + */ +static inline u32 zpci_encode_hwirq(u8 devfn, u16 msi_index) +{ + return (devfn << 16) | msi_index; +} =20 - return IRQ_SET_MASK_OK; +static inline u16 zpci_decode_hwirq_msi_index(irq_hw_number_t hwirq) +{ + return hwirq & 0xffff; +} + +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 cpumask_first(irq_data_get_affinity_mask(data)); + + 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 zpci_decode_hwirq_msi_index(data->hwirq); } =20 static struct irq_chip zpci_irq_chip =3D { .name =3D "PCI-MSI", - .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}}; + struct irq_domain *msi_domain; + irq_hw_number_t hwirq; unsigned long bit; int irqs_on =3D 0; =20 @@ -164,7 +191,9 @@ 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_data(dibv, bit); + msi_domain =3D (struct irq_domain *)airq_iv_get_ptr(dibv, bit); + generic_handle_domain_irq(msi_domain, hwirq); } } =20 @@ -229,6 +258,8 @@ static void zpci_floating_irq_handler(struct airq_struc= t *airq, struct tpi_info *tpi_info) { union zpci_sic_iib iib =3D {{0}}; + struct irq_domain *msi_domain; + irq_hw_number_t hwirq; unsigned long si, ai; struct airq_iv *aibv; int irqs_on =3D 0; @@ -256,7 +287,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_data(aibv, ai); + msi_domain =3D (struct irq_domain *)airq_iv_get_ptr(aibv, ai); + generic_handle_domain_irq(msi_domain, hwirq); airq_iv_unlock(aibv, ai); } } @@ -278,7 +311,9 @@ 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_DATA | AIRQ_IV_BITLOCK, + NULL); if (!zdev->aibv) return -ENOMEM; =20 @@ -290,146 +325,217 @@ 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) +bool arch_restore_msi_irqs(struct pci_dev *pdev) { - 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; =20 + zpci_set_irq(zdev); + return true; +} + +static struct airq_struct zpci_airq =3D { + .handler =3D zpci_floating_irq_handler, + .isc =3D PCI_ISC, +}; + +static void zpci_msi_teardown_directed(struct zpci_dev *zdev) +{ + airq_iv_free(zpci_ibv[0], zdev->msi_first_bit, zdev->max_msi); + zdev->msi_first_bit =3D -1U; + zdev->msi_nr_irqs =3D 0; +} + +static void zpci_msi_teardown_floating(struct zpci_dev *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; + zdev->msi_nr_irqs =3D 0; +} + +static void zpci_msi_teardown(struct irq_domain *domain, msi_alloc_info_t = *arg) +{ + struct zpci_dev *zdev =3D to_zpci_dev(domain->dev); + + zpci_clear_irq(zdev); + if (irq_delivery =3D=3D DIRECTED) + zpci_msi_teardown_directed(zdev); + else + zpci_msi_teardown_floating(zdev); +} + +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) { - pr_info("%s requested %d irqs, allocate system limit of %d", + pr_info("%s requested %d IRQs, allocate system limit of %d\n", pci_name(pdev), nvec, zdev->max_msi); } =20 rc =3D __alloc_airq(zdev, msi_vecs, &bit); - if (rc < 0) + if (rc) { + pr_err("Allocating adapter IRQs 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; + zdev->msi_first_bit =3D bit; + zdev->msi_nr_irqs =3D msi_vecs; + rc =3D zpci_set_irq(zdev); + if (rc) { + pr_err("Registering adapter IRQs for %s failed\n", + pci_name(pdev)); + + if (irq_delivery =3D=3D DIRECTED) + zpci_msi_teardown_directed(zdev); + else + zpci_msi_teardown_floating(zdev); + return rc; + } + return 0; +} =20 - 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); - } +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); + struct zpci_bus *zbus =3D zdev->zbus; + unsigned int cpu, hwirq; + unsigned long bit; + int i; + + bit =3D zdev->msi_first_bit + desc->msi_index; + hwirq =3D zpci_encode_hwirq(zdev->devfn, 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 - msg.data =3D hwirq - bit; 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); + for_each_possible_cpu(cpu) { + airq_iv_set_ptr(zpci_ibv[cpu], bit + i, + (unsigned long)zbus->msi_parent_domain); + airq_iv_set_data(zpci_ibv[cpu], bit + i, hwirq + i); + } + } else { + airq_iv_set_ptr(zdev->aibv, bit + i, + (unsigned long)zbus->msi_parent_domain); + airq_iv_set_data(zdev->aibv, bit + i, hwirq + i); + } + } =20 - msg.address_lo =3D zdev->msi_addr & 0xff0000ff; - msg.address_lo |=3D (cpu_addr << 8); + return 0; +} + +static void zpci_msi_domain_free(struct irq_domain *domain, unsigned int v= irq, + unsigned int nr_irqs) +{ + struct zpci_dev *zdev; + struct msi_desc *desc; + struct irq_data *d; + unsigned long bit; + unsigned int cpu; + u16 msi_index; + int i; + + for (i =3D 0; i < nr_irqs; i++) { + d =3D irq_domain_get_irq_data(domain, virq + i); + msi_index =3D zpci_decode_hwirq_msi_index(d->hwirq); + desc =3D irq_data_get_msi_desc(d); + zdev =3D to_zpci_dev(desc->dev); + bit =3D zdev->msi_first_bit + msi_index; =20 + if (irq_delivery =3D=3D DIRECTED) { 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_set_ptr(zpci_ibv[cpu], bit + i, 0); + airq_iv_set_data(zpci_ibv[cpu], bit + i, 0); } } 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); + airq_iv_set_ptr(zdev->aibv, bit + i, 0); + airq_iv_set_data(zdev->aibv, bit + i, 0); } - msg.address_hi =3D zdev->msi_addr >> 32; - pci_write_msi_msg(irq, &msg); - hwirq +=3D irqs_per_msi; + + irq_domain_reset_irq_data(d); } +} =20 - zdev->msi_first_bit =3D bit; - zdev->msi_nr_irqs =3D hwirq - bit; +static const struct irq_domain_ops zpci_msi_domain_ops =3D { + .alloc =3D zpci_msi_domain_alloc, + .free =3D zpci_msi_domain_free, +}; =20 - rc =3D zpci_set_irq(zdev); - if (rc) - return rc; +static bool zpci_init_dev_msi_info(struct device *dev, struct irq_domain *= domain, + struct irq_domain *real_parent, + struct msi_domain_info *info) +{ + 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 - return (zdev->msi_nr_irqs =3D=3D nvec) ? 0 : zdev->msi_nr_irqs; + return true; } =20 -void arch_teardown_msi_irqs(struct pci_dev *pdev) +static 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, + .init_dev_msi_info =3D zpci_init_dev_msi_info, +}; + +int zpci_create_parent_msi_domain(struct zpci_bus *zbus) { - struct zpci_dev *zdev =3D to_zpci(pdev); - struct msi_desc *msi; - unsigned int i; - int rc; + char fwnode_name[18]; =20 - /* Disable interrupts */ - rc =3D zpci_clear_irq(zdev); - if (rc) - return; + snprintf(fwnode_name, sizeof(fwnode_name), "ZPCI_MSI_DOM_%04x", zbus->dom= ain_nr); + struct irq_domain_info info =3D { + .fwnode =3D irq_domain_alloc_named_fwnode(fwnode_name), + .ops =3D &zpci_msi_domain_ops, + }; =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); - } - msi->msg.address_lo =3D 0; - msi->msg.address_hi =3D 0; - msi->msg.data =3D 0; - msi->irq =3D 0; + if (!info.fwnode) { + pr_err("Failed to allocate fwnode for MSI IRQ domain\n"); + return -ENOMEM; } =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; + if (irq_delivery =3D=3D FLOATING) + zpci_msi_parent_ops.required_flags |=3D MSI_FLAG_NO_AFFINITY; + + zbus->msi_parent_domain =3D msi_create_parent_irq_domain(&info, &zpci_msi= _parent_ops); + if (!zbus->msi_parent_domain) { + irq_domain_free_fwnode(info.fwnode); + pr_err("Failed to create MSI IRQ domain\n"); + return -ENOMEM; } =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); + return 0; } =20 -bool arch_restore_msi_irqs(struct pci_dev *pdev) +void zpci_remove_parent_msi_domain(struct zpci_bus *zbus) { - struct zpci_dev *zdev =3D to_zpci(pdev); + struct fwnode_handle *fn; =20 - zpci_set_irq(zdev); - return true; + fn =3D zbus->msi_parent_domain->fwnode; + irq_domain_remove(zbus->msi_parent_domain); + irq_domain_free_fwnode(fn); } =20 -static struct airq_struct zpci_airq =3D { - .handler =3D zpci_floating_irq_handler, - .isc =3D PCI_ISC, -}; - static void __init cpu_enable_directed_irq(void *unused) { union zpci_sic_iib iib =3D {{0}}; @@ -466,6 +572,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_PTR | AIRQ_IV_DATA | AIRQ_IV_CACHELINE | (!cpu ? AIRQ_IV_ALLOC : 0), NULL); --=20 2.51.0