From patchwork Mon Oct 7 04:03:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824004 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E43A93C2F for ; Mon, 7 Oct 2024 04:03:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273806; cv=none; b=QCeCUT4vzPHU2EZajlIFLXGbYd4zI6E3rcoCjX4LhG8JTINSa4vmJ+B+XI8Y+HLyktFcsvfu35O+9eeiHNEVDWPm7Lf7uoz+5Y17TEWo2NeEiJP+r6Bxveecpemna7rwyPoBVfN0mqOU6bIN5LxKbP3SosrjViAsnBQD+jK0inQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273806; c=relaxed/simple; bh=0AHYdi66CUseKX9KfJciikHxCnFPbS6rNBFVhBnQySc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MvSVGvXYQgOEOyjizXVqJtcAKHLyP1g8pcv+GAikul/9LHxVTaxAobWvE61HrMjEfSmnsfXGN08XtSBlHp2Ceb//MQM7KYc+hzVj/dLCPwyFmfSweZ5mCjA5JkbX8wmqMXVLLHpZ6OfG5GCl+I3xGJrHo7rWdTVqcRVKLidyG2o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Hq/AqG3u; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Hq/AqG3u" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEB93C4CED4; Mon, 7 Oct 2024 04:03:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273805; bh=0AHYdi66CUseKX9KfJciikHxCnFPbS6rNBFVhBnQySc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hq/AqG3uC/lav6dsDOKv/y1n1Z1/pdYQIGrU9kQ5SgCXo5u42vWhfi9TGmpEtFqnT U5Paq4JxrYfg9iWvU7cVO0Di06x1Iouvsv0xtqldG34D15Fb4VR8Qj3+lMF/4TMAC0 0fBK0agGW6v2Ml3r5KADcBFbHojXDJpM0iVSl6/80SZYP1tjes0e/tYo97P2VeCmTe C+4EoroZzsjQUqBgByFfJZYNpGvTbNL0zlQhZazPxQYTl9uYctrkR78dIcBKvGawmI QQ4M4fGcwhqJgxMYeZN+dH3fyj8JzIVrww3PH+maHiYyJLvHX9K6p2FzlSo/wnybZF Bg8etAdl24EXA== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 1/7] PCI: endpoint: Introduce pci_epc_function_is_valid() Date: Mon, 7 Oct 2024 13:03:13 +0900 Message-ID: <20241007040319.157412-2-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce the epc core helper function pci_epc_function_is_valid() to verify that an epc pointer, a physical function number and a virtual function number are all valid. This avoids repeating the code pattern: if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) return err; if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) return err; in many functions of the endpoint controller core code. Signed-off-by: Damien Le Moal Reviewed-by: Manivannan Sadhasivam Reviewed-by: Niklas Cassel --- drivers/pci/endpoint/pci-epc-core.c | 79 +++++++++++------------------ 1 file changed, 31 insertions(+), 48 deletions(-) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 17f007109255..b854f1bab26f 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -128,6 +128,18 @@ enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features } EXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar); +static bool pci_epc_function_is_valid(struct pci_epc *epc, + u8 func_no, u8 vfunc_no) +{ + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) + return false; + + if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + return false; + + return true; +} + /** * pci_epc_get_features() - get the features supported by EPC * @epc: the features supported by *this* EPC device will be returned @@ -145,10 +157,7 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc, { const struct pci_epc_features *epc_features; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return NULL; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return NULL; if (!epc->ops->get_features) @@ -218,10 +227,7 @@ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no, { int ret; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return -EINVAL; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; if (!epc->ops->raise_irq) @@ -262,10 +268,7 @@ int pci_epc_map_msi_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no, { int ret; - if (IS_ERR_OR_NULL(epc)) - return -EINVAL; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; if (!epc->ops->map_msi_irq) @@ -293,10 +296,7 @@ int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no) { int interrupt; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return 0; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return 0; if (!epc->ops->get_msi) @@ -329,11 +329,10 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 interrupts) int ret; u8 encode_int; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || - interrupts < 1 || interrupts > 32) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (interrupts < 1 || interrupts > 32) return -EINVAL; if (!epc->ops->set_msi) @@ -361,10 +360,7 @@ int pci_epc_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no) { int interrupt; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return 0; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return 0; if (!epc->ops->get_msix) @@ -397,11 +393,10 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no, { int ret; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || - interrupts < 1 || interrupts > 2048) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (interrupts < 1 || interrupts > 2048) return -EINVAL; if (!epc->ops->set_msix) @@ -428,10 +423,7 @@ EXPORT_SYMBOL_GPL(pci_epc_set_msix); void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, phys_addr_t phys_addr) { - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return; if (!epc->ops->unmap_addr) @@ -459,10 +451,7 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, { int ret; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return -EINVAL; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; if (!epc->ops->map_addr) @@ -489,12 +478,11 @@ EXPORT_SYMBOL_GPL(pci_epc_map_addr); void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar) { - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || - (epf_bar->barno == BAR_5 && - epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return; - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (epf_bar->barno == BAR_5 && + epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) return; if (!epc->ops->clear_bar) @@ -521,18 +509,16 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, int ret; int flags = epf_bar->flags; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions || - (epf_bar->barno == BAR_5 && - flags & PCI_BASE_ADDRESS_MEM_TYPE_64) || + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + return -EINVAL; + + if ((epf_bar->barno == BAR_5 && flags & PCI_BASE_ADDRESS_MEM_TYPE_64) || (flags & PCI_BASE_ADDRESS_SPACE_IO && flags & PCI_BASE_ADDRESS_IO_MASK) || (upper_32_bits(epf_bar->size) && !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64))) return -EINVAL; - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) - return -EINVAL; - if (!epc->ops->set_bar) return 0; @@ -561,10 +547,7 @@ int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no, { int ret; - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions) - return -EINVAL; - - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no])) + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) return -EINVAL; /* Only Virtual Function #1 has deviceID */ From patchwork Mon Oct 7 04:03:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824005 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 978243C2F for ; Mon, 7 Oct 2024 04:03:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273807; cv=none; b=UoOmDjJUgmYyHjQ6bBcYN7hKLq7wWSQF7MflU3owknBslKH65oSoDAKtikUy4yqKBBhPLR44/AQBZg1L5S31L3kumObyBBnI1ZVzr+YiRkD7F1DJv8++8iJsSw7VUQzj1PkX814VapN1C4P2SbeVb9uWYQxR/k/MONF3/L4TU8M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273807; c=relaxed/simple; bh=qoR8yo6M7hX1O5vreks+sMkUAhiVyWxm12I+3OEZ1HY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p1okHrHqft0CF2dU/V8Mcb1Otmc26xeGqq+pmaYNZobTvAho/MTvw6glHoTdmH/3Eijv8H6a5cZCdloDpJI67H/eoA3n0gI6nuasYHX8wlbfqv8b80hhdcUJ48IYC5F9O/47wI8YD39Auo9XJsler03e9th6L1Fvdku6MhkEgnI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d+nd7Q76; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d+nd7Q76" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C1C27C4CED3; Mon, 7 Oct 2024 04:03:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273807; bh=qoR8yo6M7hX1O5vreks+sMkUAhiVyWxm12I+3OEZ1HY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=d+nd7Q76HNzg3A0hxUHnPpXrgWO5xDA7JccinSWZ0e/phQUtxDBFdm5KDci/xym+t FFelk5cs/+aPyNN0PZW+PeHJY172L21NMg0KFBhwTHDmGvvharzfBfzQVL2zh2afPW nWnWqgAgRG/zb6gAHmFj2onZE6gaP2JPqXaCIKCZ76gI68gp2bHUQrgzIQo+GJnmv3 qW2BKqtfM6cROoieSYw47Vi9GIvCN7W1w3XdT75LG5di1ig2U2g3GlM6KuaDq2Ka5y IbiX0N8hyo4luAUViEiKY7DyMxbu2KdH90oi2CrrnloRHGIlcpLEwsAs9ztWET0rL9 7ixzAvtjGsJwA== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 2/7] PCI: endpoint: Improve pci_epc_mem_alloc_addr() Date: Mon, 7 Oct 2024 13:03:14 +0900 Message-ID: <20241007040319.157412-3-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 There is no point in attempting to allocate memory from an endpoint controller memory window if the requested size is larger than the memory window size. Add a check to skip bitmap_find_free_region() calls for such case. This check can be done without the mem->lock mutex held as memory window sizes are constant and never modified at runtime. Also change the final return to return NULL to simplify the code. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam --- drivers/pci/endpoint/pci-epc-mem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c index a9c028f58da1..218a60e945db 100644 --- a/drivers/pci/endpoint/pci-epc-mem.c +++ b/drivers/pci/endpoint/pci-epc-mem.c @@ -178,7 +178,7 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_exit); void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, phys_addr_t *phys_addr, size_t size) { - void __iomem *virt_addr = NULL; + void __iomem *virt_addr; struct pci_epc_mem *mem; unsigned int page_shift; size_t align_size; @@ -188,10 +188,13 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, for (i = 0; i < epc->num_windows; i++) { mem = epc->windows[i]; - mutex_lock(&mem->lock); + if (size > mem->window.size) + continue; + align_size = ALIGN(size, mem->window.page_size); order = pci_epc_mem_get_order(mem, align_size); + mutex_lock(&mem->lock); pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order); if (pageno >= 0) { @@ -211,7 +214,7 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, mutex_unlock(&mem->lock); } - return virt_addr; + return NULL; } EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr); From patchwork Mon Oct 7 04:03:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824006 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 DE4DA3C2F for ; Mon, 7 Oct 2024 04:03:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273810; cv=none; b=trHvgQU49RR09ssYtXekWJpLY41prN30fr1WBXd5Wn4Oz+tg4y7FhdP027khcc4C9vFjk0grX0g9vDKGsepkY9J+DFoY38+OuxpwBOzQ5OrTthEqzIOigbTQVIagQzBB9gh5UsIiiqXMXazMfXZv1isfxGN/JNI7SyiBC/zxev8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273810; c=relaxed/simple; bh=UUXdM1jQ/TU3bBVAZx9KnWiIMLvAC44zvvkJDss6DKc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=alpjdrdY64cvb5KWu20Er1yNgXP9uCqoQFmiD0w1SvlKe+Rb27J8SQwb9QI04k1rEAfoXt/tn6+xwcwb8233UraQUyc+80i/6n1P3cpkRIulUJtoCGaOlGy1IqP91uaH5haBqeO4sXVw0lQDeeLLTjpqYqB7VBXVoiGgomrWd8E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QlCpVJk5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QlCpVJk5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C3F8DC4CED2; Mon, 7 Oct 2024 04:03:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273809; bh=UUXdM1jQ/TU3bBVAZx9KnWiIMLvAC44zvvkJDss6DKc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QlCpVJk5GCM3bw1E72lsYZi3xx/burIXhxlDR5DVSR2tXwaTjYQoJgR+Y/+Ls+eoO l9QG8+3bEmVK10Mf++p52FzqOHGaKtfdkjmUTvq8Zi61IcDJJF+MohPKquUGq0YaXz QC9YGenArahxfce+yC/UdhS/zIClWwlEoZqa1kZ071zimhFCHNWgOuEd0FvViHg4eD +prlTgELOdK0RntUkwFT0GqguhVONGOfjNsFEsbiAuLGLKxYcEx3ATgxJ7uDN0QntF MY90iVOPwZwLSKSPVKw+YiQgm4ljNwYsGDMB0rrbnNInbeUWNbjHdjTmh2t1StHZAe AhuO5C8iSuQCA== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 3/7] PCI: endpoint: Introduce pci_epc_map_align() Date: Mon, 7 Oct 2024 13:03:15 +0900 Message-ID: <20241007040319.157412-4-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Some endpoint controllers have requirements on the alignment of the controller physical memory address that must be used to map a RC PCI address region. For instance, the rockchip endpoint controller uses at most the lower 20 bits of a physical memory address region as the lower bits of an RC PCI address. For mapping a PCI address region of size bytes starting from pci_addr, the exact number of address bits used is the number of address bits changing in the address range [pci_addr..pci_addr + size - 1]. For this example, this creates the following constraints: 1) The offset into the controller physical memory allocated for a mapping depends on the mapping size *and* the starting PCI address for the mapping. 2) A mapping size cannot exceed the controller windows size (1MB) minus the offset needed into the allocated physical memory, which can end up being a smaller size than the desired mapping size. Handling these constraints independently of the controller being used in an endpoint function driver is not possible with the current EPC API as only the ->align field in struct pci_epc_features is provided and used for BAR (inbound ATU mappings) mapping. A new API is needed for function drivers to discover mapping constraints and handle non-static requirements based on the RC PCI address range to access. Introduce the function pci_epc_map_align() and the endpoint controller operation ->map_align to allow endpoint function drivers to obtain the size and the offset into a controller address region that must be allocated and mapped to access an RC PCI address region. The size of the mapping provided by pci_epc_map_align() can then be used as the size argument for the function pci_epc_mem_alloc_addr(). The offset into the allocated controller memory provided can be used to correctly handle data transfers. For endpoint controllers that have PCI address alignment constraints, pci_epc_map_align() may indicate upon return an effective PCI address region mapping size that is smaller (but not 0) than the requested PCI address region size. For such case, an endpoint function driver must handle data accesses over the desired PCI address range in fragments, by repeatedly using pci_epc_map_align() over the PCI address range. The controller operation ->map_align is optional: controllers that do not have any alignment constraints for mapping a RC PCI address region do not need to implement this operation. For such controllers, pci_epc_map_align() always returns the mapping size as equal to the requested size of the PCI region and an offset equal to 0. The new structure struct pci_epc_map is introduced to represent a mapping start PCI address, mapping effective size, the size and offset into the controller memory needed for mapping the PCI address region as well as the physical and virtual CPU addresses of the mapping (phys_base and virt_base fields). For convenience, the physical and virtual CPU addresses within that mapping to access the target RC PCI address region are also provided (phys_addr and virt_addr fields). Co-developed-by: Rick Wertenbroek Signed-off-by: Rick Wertenbroek Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/pci/endpoint/pci-epc-core.c | 66 +++++++++++++++++++++++++++++ include/linux/pci-epc.h | 37 ++++++++++++++++ 2 files changed, 103 insertions(+) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index b854f1bab26f..1adccf07c33e 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -435,6 +435,72 @@ void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, } EXPORT_SYMBOL_GPL(pci_epc_unmap_addr); +/** + * pci_epc_map_align() - Get the offset into and the size of a controller memory + * address region needed to map a RC PCI address region + * @epc: the EPC device on which address is allocated + * @func_no: the physical endpoint function number in the EPC device + * @vfunc_no: the virtual endpoint function number in the physical function + * @pci_addr: The RC PCI address to map + * @pci_size: the number of bytes to map starting from @pci_addr + * @map: populate here the actual size and offset into the controller memory + * that must be allocated for the mapping + * + * If defined, invoke the controller map_align operation to obtain the size and + * the offset into a controller address region that must be allocated to map + * @pci_size bytes of the RC PCI address space starting from @pci_addr. + * + * On return, @map->pci_size indicates the effective size of the mapping that + * can be handled by the controller. This size may be smaller than the requested + * @pci_size. In such case, the endpoint function driver must handle the mapping + * using several fragments. The offset into the controller memory for the + * effective mapping of the RC PCI address range + * @pci_addr..@pci_addr+@map->pci_size is indicated by @map->map_ofst. + * + * If the target controller does not define a map_align operation, it is assumed + * that the controller has no PCI address mapping alignment constraint. + */ +int pci_epc_map_align(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + u64 pci_addr, size_t pci_size, struct pci_epc_map *map) +{ + int ret; + + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + return -EINVAL; + + if (!pci_size || !map) + return -EINVAL; + + /* + * Initialize and remember the PCI address region to be mapped. The + * controller ->map_align() operation may change the map->pci_size to a + * smaller value. + */ + memset(map, 0, sizeof(*map)); + map->pci_addr = pci_addr; + map->pci_size = pci_size; + + if (!epc->ops->map_align) { + /* + * Assume that the EP controller has no alignment constraint, + * that is, that the PCI address to map and the size of the + * controller memory needed for the mapping are the same as + * specified by the caller. + */ + map->map_pci_addr = pci_addr; + map->map_size = pci_size; + map->map_ofst = 0; + return 0; + } + + mutex_lock(&epc->lock); + ret = epc->ops->map_align(epc, func_no, vfunc_no, map); + mutex_unlock(&epc->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(pci_epc_map_align); + /** * pci_epc_map_addr() - map CPU address to PCI address * @epc: the EPC device on which address is allocated diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 42ef06136bd1..9df8a83e8d10 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -32,11 +32,44 @@ pci_epc_interface_string(enum pci_epc_interface_type type) } } +/** + * struct pci_epc_map - information about EPC memory for mapping a RC PCI + * address range + * @pci_addr: start address of the RC PCI address range to map + * @pci_size: size of the RC PCI address range mapped from @pci_addr + * @map_pci_addr: RC PCI address used as the first address mapped (may be lower + * than @pci_addr) + * @map_size: size of the controller memory needed for mapping the RC PCI address + * range @pci_addr..@pci_addr+@pci_size + * @map_ofst: offset into the mapped controller memory to access @pci_addr + * @phys_base: base physical address of the allocated EPC memory for mapping the + * RC PCI address range + * @phys_addr: physical address at which @pci_addr is mapped + * @virt_base: base virtual address of the allocated EPC memory for mapping the + * RC PCI address range + * @virt_addr: virtual address at which @pci_addr is mapped + */ +struct pci_epc_map { + phys_addr_t pci_addr; + size_t pci_size; + + phys_addr_t map_pci_addr; + size_t map_size; + phys_addr_t map_ofst; + + phys_addr_t phys_base; + phys_addr_t phys_addr; + void __iomem *virt_base; + void __iomem *virt_addr; +}; + /** * struct pci_epc_ops - set of function pointers for performing EPC operations * @write_header: ops to populate configuration space header * @set_bar: ops to configure the BAR * @clear_bar: ops to reset the BAR + * @map_align: operation to get the size and offset into a controller memory + * window needed to map an RC PCI address region * @map_addr: ops to map CPU address to PCI address * @unmap_addr: ops to unmap CPU address and PCI address * @set_msi: ops to set the requested number of MSI interrupts in the MSI @@ -61,6 +94,8 @@ struct pci_epc_ops { struct pci_epf_bar *epf_bar); void (*clear_bar)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar); + int (*map_align)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_map *map); int (*map_addr)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, phys_addr_t addr, u64 pci_addr, size_t size); void (*unmap_addr)(struct pci_epc *epc, u8 func_no, u8 vfunc_no, @@ -241,6 +276,8 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar); void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no, struct pci_epf_bar *epf_bar); +int pci_epc_map_align(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + u64 pci_addr, size_t size, struct pci_epc_map *map); int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, phys_addr_t phys_addr, u64 pci_addr, size_t size); From patchwork Mon Oct 7 04:03:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824007 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 901853C2F for ; Mon, 7 Oct 2024 04:03:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273811; cv=none; b=GjdxxkIg7A5zlrh1wi/vgjC0jolPl5RfkM7nePIIXNrQzyVylNTNji0bieSmTWHx6YHOR37443enf6UqKXrV1pIxAoDkSjqXroCndDOiwdIwUYEx9dw1royYJq4caIsMqN3U4BkaLrHShmgwxd2nux7F6X5ctER2alM+Yuh6/FI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273811; c=relaxed/simple; bh=KOlzri2s1hJeQueXMQVc7/f1GBi2mQLHYnXMS6K4sb8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JcD+tAFD44+UlzfnbKfdq7wfZCluXwAPtGO9yEGDbvcA0I5MEV993pj2Hrqz2qIpL6WPvsAAJDhbO5akRIiHPaLkRV1hSIyoyl/6wJE/Ssm/HoIPY7FberMpsSYAUoijXdUcZyhrSO1NG3zvKyavB4ddElJGifBS2jcNVNaeZkE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eaWrsK45; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="eaWrsK45" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1372C4CED4; Mon, 7 Oct 2024 04:03:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273811; bh=KOlzri2s1hJeQueXMQVc7/f1GBi2mQLHYnXMS6K4sb8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eaWrsK45aZB0oP7egIxQlvGoj4+JyowvmL9hGmPst9hbhUy0FnnlZsHBf2DyXX2vD TQjRRsttbMenZ8Br7RUNcGRIdNPcFzjcozu8hlP/sY1ST784BF1jwvSds5zexwA2Jj gMe0uYNnXTt2xUhBnUOSCSLKMus1KFbCJfscO9lyNUa86hJuKueZyxNSuh8d7Ybi4a rqSYOtY/43OkbqQqeVIpLGQ2NweX9BotLjblY5SdIQKek/qWBnBVf6e+nx/NyQyOzN Vml3iR2B8ovEQ9M0//VqGLn2+J8Wf1l6wrZ08Tl5LarrNHNmxvzK/SnBtpKFKKh3er +gETinZIhq2kA== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 4/7] PCI: endpoint: Introduce pci_epc_mem_map()/unmap() Date: Mon, 7 Oct 2024 13:03:16 +0900 Message-ID: <20241007040319.157412-5-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Introduce the function pci_epc_mem_map() to facilitate controller memory address allocation and mapping to a RC PCI address region in endpoint function drivers. This function first uses pci_epc_map_align() to determine the controller memory address size (and offset into) depending on the controller address alignment constraints. The result of this function is used to allocate a controller physical memory region using pci_epc_mem_alloc_addr() and map that memory to the RC PCI address space with pci_epc_map_addr(). Since pci_epc_map_align() may indicate that the effective mapping of a PCI address region is smaller than the user requested size, pci_epc_mem_map() may only partially map the RC PCI address region specified. It is the responsibility of the caller (an endpoint function driver) to handle such smaller mapping. The counterpart of pci_epc_mem_map() to unmap and free the controller memory address region is pci_epc_mem_unmap(). Both functions operate using a struct pci_epc_map data structure Endpoint function drivers can use struct pci_epc_map to access the mapped RC PCI address region using the ->virt_addr and ->pci_size fields. Co-developed-by: Rick Wertenbroek Signed-off-by: Rick Wertenbroek Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/pci/endpoint/pci-epc-core.c | 78 +++++++++++++++++++++++++++++ include/linux/pci-epc.h | 4 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index 1adccf07c33e..d03c753d0a53 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -532,6 +532,84 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, } EXPORT_SYMBOL_GPL(pci_epc_map_addr); +/** + * pci_epc_mem_map() - allocate and map a PCI address to a CPU address + * @epc: the EPC device on which the CPU address is to be allocated and mapped + * @func_no: the physical endpoint function number in the EPC device + * @vfunc_no: the virtual endpoint function number in the physical function + * @pci_addr: PCI address to which the CPU address should be mapped + * @pci_size: the number of bytes to map starting from @pci_addr + * @map: where to return the mapping information + * + * Allocate a controller memory address region and map it to a RC PCI address + * region, taking into account the controller physical address mapping + * constraints using pci_epc_map_align(). + * The effective size of the PCI address range mapped from @pci_addr is + * indicated by @map->pci_size. This size may be less than the requested + * @pci_size. The local virtual CPU address for the mapping is indicated by + * @map->virt_addr (@map->phys_addr indicates the physical address). + * The size and CPU address of the controller memory allocated and mapped are + * respectively indicated by @map->map_size and @map->virt_base (and + * @map->phys_base). + * + * Returns 0 on success and a negative error code in case of error. + */ +int pci_epc_mem_map(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + u64 pci_addr, size_t pci_size, struct pci_epc_map *map) +{ + int ret; + + ret = pci_epc_map_align(epc, func_no, vfunc_no, pci_addr, pci_size, map); + if (ret) + return ret; + + map->virt_base = pci_epc_mem_alloc_addr(epc, &map->phys_base, + map->map_size); + if (!map->virt_base) + return -ENOMEM; + + map->phys_addr = map->phys_base + map->map_ofst; + map->virt_addr = map->virt_base + map->map_ofst; + + ret = pci_epc_map_addr(epc, func_no, vfunc_no, map->phys_base, + map->map_pci_addr, map->map_size); + if (ret) { + pci_epc_mem_free_addr(epc, map->phys_base, map->virt_base, + map->map_size); + map->virt_base = 0; + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(pci_epc_mem_map); + +/** + * pci_epc_mem_unmap() - unmap and free a CPU address region + * @epc: the EPC device on which the CPU address is allocated and mapped + * @func_no: the physical endpoint function number in the EPC device + * @vfunc_no: the virtual endpoint function number in the physical function + * @map: the mapping information + * + * Unmap and free a CPU address region that was allocated and mapped with + * pci_epc_mem_map(). + */ +void pci_epc_mem_unmap(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_map *map) +{ + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no)) + return; + + if (!map || !map->virt_base) + return; + + pci_epc_unmap_addr(epc, func_no, vfunc_no, map->phys_base); + pci_epc_mem_free_addr(epc, map->phys_base, map->virt_base, + map->map_size); + map->map_size = 0; +} +EXPORT_SYMBOL_GPL(pci_epc_mem_unmap); + /** * pci_epc_clear_bar() - reset the BAR * @epc: the EPC device for which the BAR has to be cleared diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h index 9df8a83e8d10..97d2fbb740fd 100644 --- a/include/linux/pci-epc.h +++ b/include/linux/pci-epc.h @@ -315,6 +315,10 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc, phys_addr_t *phys_addr, size_t size); void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr, void __iomem *virt_addr, size_t size); +int pci_epc_mem_map(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + u64 pci_addr, size_t pci_size, struct pci_epc_map *map); +void pci_epc_mem_unmap(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_map *map); #else static inline void pci_epc_init_notify(struct pci_epc *epc) From patchwork Mon Oct 7 04:03:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824008 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 D89963C2F for ; Mon, 7 Oct 2024 04:03:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273813; cv=none; b=fDcKI+MN5N0llAHxezE++tpgNm4IjvkHRt4u4O4uDlxLJmmugiBIkIVr7WkSP8VAJqvB1iqtHLS/3iqa4oQbru64Z3se/EhcFanDegySv4nZUUEi3wuUCELl98nboYVlqGl/GM2GDtvE5vN2WGPcf8+RKVciWFcJ8Yg1+/P0tD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273813; c=relaxed/simple; bh=sM14zTUreXFzXcTyE03VL6AugWuiYFlUp4lJMpEASrI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P5ahn+J3Tq+naPbbstnPJCq9GT3Z7FoMeUEXJSeymljghSm3ZxXo+F0r4zcC/3DUVWTzXePA3mKdfnhfsSJ8uwpvOChXx/t60K0W4Tvly26+0GftcsnH/FzXebRy0r60MXBnwcj4UKokQifi5J1V9kkh3v6IS+p5ycLPfZoSm80= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fekEmLoB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fekEmLoB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C981FC4CED2; Mon, 7 Oct 2024 04:03:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273813; bh=sM14zTUreXFzXcTyE03VL6AugWuiYFlUp4lJMpEASrI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fekEmLoBCZqTAX5yeXnfnAfyloGVAKqCNhQ7JWoQjAOibKDNaTvVbLi3bgpsid33t b2soqP71mmNwGSEVOo7kxLKmk/UfkUAIihxw0wJR3PuWKPt38Ko6TYEirrMOx8J0f2 tbBpfFE8x4xeTWzi5+3MkLYJh3lF+7+rxUucyhEsqdT8jq2cO3DRO8WEs1tGN10Lge +b8zKom/GM1GKtJN7jmFL3yiM4ytrz2NtdYpB2GQwagMIiyJBQQt4JH4cjTS4ob3M0 1ndPCbyyZPo96vRjoyZh/9kLqS3ybX6CSOhZH0EHby6W5z6+c2vbKnDtd2AA161sSA 5R2uBjzxJEJXA== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 5/7] PCI: endpoint: Update documentation Date: Mon, 7 Oct 2024 13:03:17 +0900 Message-ID: <20241007040319.157412-6-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Document the new functions pci_epc_map_align(), pci_epc_mem_map() and pci_epc_mem_unmap(). Also add the documentation for the functions pci_epc_map_addr() and pci_epc_unmap_addr() that were missing. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- Documentation/PCI/endpoint/pci-endpoint.rst | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst index 21507e3cc238..8e86cd209f9a 100644 --- a/Documentation/PCI/endpoint/pci-endpoint.rst +++ b/Documentation/PCI/endpoint/pci-endpoint.rst @@ -117,6 +117,41 @@ by the PCI endpoint function driver. The PCI endpoint function driver should use pci_epc_mem_free_addr() to free the memory space allocated using pci_epc_mem_alloc_addr(). +* pci_epc_map_align() + + A PCI endpoint controller may impose constraints on the RC PCI addresses + that can be mapped. The function pci_epc_map_align() allows endpoint + function drivers to discover and handle such constraints by providing the + size of the memory that must be allocated with pci_epc_mem_alloc_addr() + for successfully mapping any RC PCI address. This function will also + indicate the size of the PCI address range that can be mapped, which can be + less than the requested size, as well as the offset into the allocated + memory to use for accessing the RC PCI address range that can be mapped. + +* pci_epc_map_addr() + + A PCI endpoint function driver should use pci_epc_map_addr() to map to a RC + PCI address the CPU address of local memory obtained with + pci_epc_mem_alloc_addr(). + +* pci_epc_unmap_addr() + + A PCI endpoint function driver should use pci_epc_unmap_addr() to unmap the + CPU address of local memory mapped to a RC address with pci_epc_map_addr(). + +* pci_epc_mem_map() + + A PCI endpoint function driver can use pci_epc_mem_map() to allocate and map + a RC PCI address range. This function combines calls to pci_epc_map_align(), + pci_epc_mem_alloc_addr() and pci_epc_mem_alloc_addr() into a single function + to simplify the PCI address mapping handling in endpoint function drivers. + +* pci_epc_mem_unmap() + + A PCI endpoint function driver can use pci_epc_mem_unmap() to unmap and free + memory that was allocated and mapped using pci_epc_mem_map(). + + Other EPC APIs ~~~~~~~~~~~~~~ From patchwork Mon Oct 7 04:03:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824009 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 00A644430 for ; Mon, 7 Oct 2024 04:03:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273816; cv=none; b=qwtgOdUxca6U5s0BR1rqZ7oVhiU0UzrRoIeVNeIz6i4isAEZim/q76jQWkQoeMON2zbebfHls5Gyof2CYscuWDAsfe/+1t/Nv2iWPm8Jm+VUPTasiZbAGm/Z9lyjJBhMk40ocKlT64YRoc8JI4FPyQJCxY4mM+0BmyxiBgKYeJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273816; c=relaxed/simple; bh=z1T4GvXAzBQMx0pdZObj1tDkhM6X+SAMlzpX3rMFcqw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ImjZhBNMEXqn8iwr1geXbTfE55QFwUUIb7E9PRJOhdldPemYVnXMkZEvcq+Yo7XzL1Pq44vokn4A8DeFHhlyNyyVRA838H/QQXbmEh7aQCHsDVnjKzocGpFe9pZTBq06Q2qvS8kFkyGdLKYZJ6Gep3tCaDD2SWCS4Qh0QmKLT7s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fxiAnkaB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fxiAnkaB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CF0FDC4CED4; Mon, 7 Oct 2024 04:03:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273815; bh=z1T4GvXAzBQMx0pdZObj1tDkhM6X+SAMlzpX3rMFcqw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fxiAnkaBDnV3DJvbxX7o0TJZbTfw33rxRtZHiAFPOARWfazLg+MM9X8pULyuOWizh k5ByxgagsX+G0XCB+noeRjJj7hhNskA5NKI2ZOaJpv8l41aZosOnkwDuFWA4h9Lcau UJgyEtab+PCF5PydW0Il8OA2nNtw++sRQTUy03C/Ahv7zsg1na4FHPEhOdb5J2r7MK uFLd6v4wVwGutyjG78qxys5DTLuhyurOk8J1w6qzVcwV8caakGVVvbHlQGsQWojNin XJvn3lTAZn8kGbbfuPGpTdM5JV2j2h+NK5J8DWxtk4ZzkrH25KQszkSoHvgDudeJTP 6qZDM9PcHhP+A== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 6/7] PCI: endpoint: test: Use pci_epc_mem_map/unmap() Date: Mon, 7 Oct 2024 13:03:18 +0900 Message-ID: <20241007040319.157412-7-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Modify the endpoint test driver to use the functions pci_epc_mem_map() and pci_epc_mem_unmap() for the read, write and copy tests. For each test case, the transfer (dma or mmio) are executed in a loop to ensure that potentially partial mappings returned by pci_epc_mem_map() are correctly handled. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel Reviewed-by: Manivannan Sadhasivam --- drivers/pci/endpoint/functions/pci-epf-test.c | 372 +++++++++--------- 1 file changed, 193 insertions(+), 179 deletions(-) diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c index 7c2ed6eae53a..a73bc0771d35 100644 --- a/drivers/pci/endpoint/functions/pci-epf-test.c +++ b/drivers/pci/endpoint/functions/pci-epf-test.c @@ -317,91 +317,92 @@ static void pci_epf_test_print_rate(struct pci_epf_test *epf_test, static void pci_epf_test_copy(struct pci_epf_test *epf_test, struct pci_epf_test_reg *reg) { - int ret; - void __iomem *src_addr; - void __iomem *dst_addr; - phys_addr_t src_phys_addr; - phys_addr_t dst_phys_addr; + int ret = 0; struct timespec64 start, end; struct pci_epf *epf = epf_test->epf; - struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; + struct pci_epc_map src_map, dst_map; + u64 src_addr = reg->src_addr; + u64 dst_addr = reg->dst_addr; + size_t copy_size = reg->size; + ssize_t map_size = 0; + void *copy_buf = NULL, *buf; - src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size); - if (!src_addr) { - dev_err(dev, "Failed to allocate source address\n"); - reg->status = STATUS_SRC_ADDR_INVALID; - ret = -ENOMEM; - goto err; - } - - ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr, - reg->src_addr, reg->size); - if (ret) { - dev_err(dev, "Failed to map source address\n"); - reg->status = STATUS_SRC_ADDR_INVALID; - goto err_src_addr; - } - - dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size); - if (!dst_addr) { - dev_err(dev, "Failed to allocate destination address\n"); - reg->status = STATUS_DST_ADDR_INVALID; - ret = -ENOMEM; - goto err_src_map_addr; - } - - ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr, - reg->dst_addr, reg->size); - if (ret) { - dev_err(dev, "Failed to map destination address\n"); - reg->status = STATUS_DST_ADDR_INVALID; - goto err_dst_addr; - } - - ktime_get_ts64(&start); if (reg->flags & FLAG_USE_DMA) { if (epf_test->dma_private) { dev_err(dev, "Cannot transfer data using DMA\n"); ret = -EINVAL; - goto err_map_addr; + goto set_status; } - - ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr, - src_phys_addr, reg->size, 0, - DMA_MEM_TO_MEM); - if (ret) - dev_err(dev, "Data transfer failed\n"); } else { - void *buf; - - buf = kzalloc(reg->size, GFP_KERNEL); - if (!buf) { + copy_buf = kzalloc(copy_size, GFP_KERNEL); + if (!copy_buf) { ret = -ENOMEM; - goto err_map_addr; + goto set_status; } - - memcpy_fromio(buf, src_addr, reg->size); - memcpy_toio(dst_addr, buf, reg->size); - kfree(buf); + buf = copy_buf; } - ktime_get_ts64(&end); - pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, &end, - reg->flags & FLAG_USE_DMA); -err_map_addr: - pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, dst_phys_addr); + while (copy_size) { + ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no, + src_addr, copy_size, &src_map); + if (ret) { + dev_err(dev, "Failed to map source address\n"); + reg->status = STATUS_SRC_ADDR_INVALID; + goto free_buf; + } + + ret = pci_epc_mem_map(epf->epc, epf->func_no, epf->vfunc_no, + dst_addr, copy_size, &dst_map); + if (ret) { + dev_err(dev, "Failed to map destination address\n"); + reg->status = STATUS_DST_ADDR_INVALID; + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, + &src_map); + goto free_buf; + } + + map_size = min_t(size_t, dst_map.pci_size, src_map.pci_size); + + ktime_get_ts64(&start); + if (reg->flags & FLAG_USE_DMA) { + ret = pci_epf_test_data_transfer(epf_test, + dst_map.phys_addr, src_map.phys_addr, + map_size, 0, DMA_MEM_TO_MEM); + if (ret) { + dev_err(dev, "Data transfer failed\n"); + goto unmap; + } + } else { + memcpy_fromio(buf, src_map.virt_addr, map_size); + memcpy_toio(dst_map.virt_addr, buf, map_size); + buf += map_size; + } + ktime_get_ts64(&end); -err_dst_addr: - pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size); + copy_size -= map_size; + src_addr += map_size; + dst_addr += map_size; -err_src_map_addr: - pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, src_phys_addr); + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map); + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map); + map_size = 0; + } -err_src_addr: - pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size); + pci_epf_test_print_rate(epf_test, "COPY", reg->size, &start, + &end, reg->flags & FLAG_USE_DMA); -err: +unmap: + if (map_size) { + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &dst_map); + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &src_map); + } + +free_buf: + kfree(copy_buf); + +set_status: if (!ret) reg->status |= STATUS_COPY_SUCCESS; else @@ -411,82 +412,89 @@ static void pci_epf_test_copy(struct pci_epf_test *epf_test, static void pci_epf_test_read(struct pci_epf_test *epf_test, struct pci_epf_test_reg *reg) { - int ret; - void __iomem *src_addr; - void *buf; + int ret = 0; + void *src_buf, *buf; u32 crc32; - phys_addr_t phys_addr; + struct pci_epc_map map; phys_addr_t dst_phys_addr; struct timespec64 start, end; struct pci_epf *epf = epf_test->epf; - struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; struct device *dma_dev = epf->epc->dev.parent; + u64 src_addr = reg->src_addr; + size_t src_size = reg->size; + ssize_t map_size = 0; - src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); - if (!src_addr) { - dev_err(dev, "Failed to allocate address\n"); - reg->status = STATUS_SRC_ADDR_INVALID; + src_buf = kzalloc(src_size, GFP_KERNEL); + if (!src_buf) { ret = -ENOMEM; - goto err; + goto set_status; } + buf = src_buf; - ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr, - reg->src_addr, reg->size); - if (ret) { - dev_err(dev, "Failed to map address\n"); - reg->status = STATUS_SRC_ADDR_INVALID; - goto err_addr; - } - - buf = kzalloc(reg->size, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto err_map_addr; - } + while (src_size) { + ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no, + src_addr, src_size, &map); + if (ret) { + dev_err(dev, "Failed to map address\n"); + reg->status = STATUS_SRC_ADDR_INVALID; + goto free_buf; + } - if (reg->flags & FLAG_USE_DMA) { - dst_phys_addr = dma_map_single(dma_dev, buf, reg->size, - DMA_FROM_DEVICE); - if (dma_mapping_error(dma_dev, dst_phys_addr)) { - dev_err(dev, "Failed to map destination buffer addr\n"); - ret = -ENOMEM; - goto err_dma_map; + map_size = map.pci_size; + if (reg->flags & FLAG_USE_DMA) { + dst_phys_addr = dma_map_single(dma_dev, buf, map_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(dma_dev, dst_phys_addr)) { + dev_err(dev, + "Failed to map destination buffer addr\n"); + ret = -ENOMEM; + goto unmap; + } + + ktime_get_ts64(&start); + ret = pci_epf_test_data_transfer(epf_test, + dst_phys_addr, map.phys_addr, + map_size, src_addr, DMA_DEV_TO_MEM); + if (ret) + dev_err(dev, "Data transfer failed\n"); + ktime_get_ts64(&end); + + dma_unmap_single(dma_dev, dst_phys_addr, map_size, + DMA_FROM_DEVICE); + + if (ret) + goto unmap; + } else { + ktime_get_ts64(&start); + memcpy_fromio(buf, map.virt_addr, map_size); + ktime_get_ts64(&end); } - ktime_get_ts64(&start); - ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr, - phys_addr, reg->size, - reg->src_addr, DMA_DEV_TO_MEM); - if (ret) - dev_err(dev, "Data transfer failed\n"); - ktime_get_ts64(&end); + src_size -= map_size; + src_addr += map_size; + buf += map_size; - dma_unmap_single(dma_dev, dst_phys_addr, reg->size, - DMA_FROM_DEVICE); - } else { - ktime_get_ts64(&start); - memcpy_fromio(buf, src_addr, reg->size); - ktime_get_ts64(&end); + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map); + map_size = 0; } - pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, &end, - reg->flags & FLAG_USE_DMA); + pci_epf_test_print_rate(epf_test, "READ", reg->size, &start, + &end, reg->flags & FLAG_USE_DMA); - crc32 = crc32_le(~0, buf, reg->size); + crc32 = crc32_le(~0, src_buf, reg->size); if (crc32 != reg->checksum) ret = -EIO; -err_dma_map: - kfree(buf); - -err_map_addr: - pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr); +unmap: + if (map_size) + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map); -err_addr: - pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size); +free_buf: + kfree(src_buf); -err: +set_status: if (!ret) reg->status |= STATUS_READ_SUCCESS; else @@ -496,71 +504,79 @@ static void pci_epf_test_read(struct pci_epf_test *epf_test, static void pci_epf_test_write(struct pci_epf_test *epf_test, struct pci_epf_test_reg *reg) { - int ret; - void __iomem *dst_addr; - void *buf; - phys_addr_t phys_addr; + int ret = 0; + void *dst_buf, *buf; + struct pci_epc_map map; phys_addr_t src_phys_addr; struct timespec64 start, end; struct pci_epf *epf = epf_test->epf; - struct device *dev = &epf->dev; struct pci_epc *epc = epf->epc; + struct device *dev = &epf->dev; struct device *dma_dev = epf->epc->dev.parent; + u64 dst_addr = reg->dst_addr; + size_t dst_size = reg->size; + ssize_t map_size = 0; - dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size); - if (!dst_addr) { - dev_err(dev, "Failed to allocate address\n"); - reg->status = STATUS_DST_ADDR_INVALID; + dst_buf = kzalloc(dst_size, GFP_KERNEL); + if (!dst_buf) { ret = -ENOMEM; - goto err; + goto set_status; } + get_random_bytes(dst_buf, dst_size); + reg->checksum = crc32_le(~0, dst_buf, dst_size); + buf = dst_buf; - ret = pci_epc_map_addr(epc, epf->func_no, epf->vfunc_no, phys_addr, - reg->dst_addr, reg->size); - if (ret) { - dev_err(dev, "Failed to map address\n"); - reg->status = STATUS_DST_ADDR_INVALID; - goto err_addr; - } - - buf = kzalloc(reg->size, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto err_map_addr; - } - - get_random_bytes(buf, reg->size); - reg->checksum = crc32_le(~0, buf, reg->size); - - if (reg->flags & FLAG_USE_DMA) { - src_phys_addr = dma_map_single(dma_dev, buf, reg->size, - DMA_TO_DEVICE); - if (dma_mapping_error(dma_dev, src_phys_addr)) { - dev_err(dev, "Failed to map source buffer addr\n"); - ret = -ENOMEM; - goto err_dma_map; + while (dst_size) { + ret = pci_epc_mem_map(epc, epf->func_no, epf->vfunc_no, + dst_addr, dst_size, &map); + if (ret) { + dev_err(dev, "Failed to map address\n"); + reg->status = STATUS_DST_ADDR_INVALID; + goto free_buf; } - ktime_get_ts64(&start); + map_size = map.pci_size; + if (reg->flags & FLAG_USE_DMA) { + src_phys_addr = dma_map_single(dma_dev, buf, map_size, + DMA_TO_DEVICE); + if (dma_mapping_error(dma_dev, src_phys_addr)) { + dev_err(dev, + "Failed to map source buffer addr\n"); + ret = -ENOMEM; + goto unmap; + } + + ktime_get_ts64(&start); + + ret = pci_epf_test_data_transfer(epf_test, + map.phys_addr, src_phys_addr, + map_size, dst_addr, + DMA_MEM_TO_DEV); + if (ret) + dev_err(dev, "Data transfer failed\n"); + ktime_get_ts64(&end); + + dma_unmap_single(dma_dev, src_phys_addr, map_size, + DMA_TO_DEVICE); + + if (ret) + goto unmap; + } else { + ktime_get_ts64(&start); + memcpy_toio(map.virt_addr, buf, map_size); + ktime_get_ts64(&end); + } - ret = pci_epf_test_data_transfer(epf_test, phys_addr, - src_phys_addr, reg->size, - reg->dst_addr, - DMA_MEM_TO_DEV); - if (ret) - dev_err(dev, "Data transfer failed\n"); - ktime_get_ts64(&end); + dst_size -= map_size; + dst_addr += map_size; + buf += map_size; - dma_unmap_single(dma_dev, src_phys_addr, reg->size, - DMA_TO_DEVICE); - } else { - ktime_get_ts64(&start); - memcpy_toio(dst_addr, buf, reg->size); - ktime_get_ts64(&end); + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map); + map_size = 0; } - pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, &end, - reg->flags & FLAG_USE_DMA); + pci_epf_test_print_rate(epf_test, "WRITE", reg->size, &start, + &end, reg->flags & FLAG_USE_DMA); /* * wait 1ms inorder for the write to complete. Without this delay L3 @@ -568,16 +584,14 @@ static void pci_epf_test_write(struct pci_epf_test *epf_test, */ usleep_range(1000, 2000); -err_dma_map: - kfree(buf); - -err_map_addr: - pci_epc_unmap_addr(epc, epf->func_no, epf->vfunc_no, phys_addr); +unmap: + if (map_size) + pci_epc_mem_unmap(epc, epf->func_no, epf->vfunc_no, &map); -err_addr: - pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size); +free_buf: + kfree(dst_buf); -err: +set_status: if (!ret) reg->status |= STATUS_WRITE_SUCCESS; else From patchwork Mon Oct 7 04:03:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 13824010 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 F0E8E3C2F for ; Mon, 7 Oct 2024 04:03:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273819; cv=none; b=P+KUCtotJP8XTR5KqjJ52eUmBCE7h5HpITxelhrdeMAEcWW1Cb5Oy/l+MLRA7Y8XyzCghMPwAKVzIkZJlDY/TfqDk0gplQw6MlemJYj8K1y5fMSxYvY37YJIuAXFlKs7XvAY8xODNrGPvR0huMnU3Y6D8vEgzidoOTa5TlgFxjM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728273819; c=relaxed/simple; bh=yx4Q/rn6pqKvqmdQqzU9Qy7oW1jSZp2YseRN8m9MKkg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GycEjsSakOIexxrcGiRn8GYRutXPVbL/o6dP2q6fcsBbwuKhHlbqZLYc1wtlO0J4veUEjwu2sfFjqX1g6wVdX6EWfxJ43OqNjva2js94B5DS3LvnHo2+YkzNUlvcB2/4qx72IUNANyw1BKFRNlIARJkoIL0WC1iXqq6Pw2iew4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rHAXNMHa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="rHAXNMHa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E3198C4CED3; Mon, 7 Oct 2024 04:03:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728273817; bh=yx4Q/rn6pqKvqmdQqzU9Qy7oW1jSZp2YseRN8m9MKkg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rHAXNMHaxU8cLQDlI6L10MU7XkB3OHUvzSAlXTrzQGMQv8OpX/Ni9s7zBjLmKRDZN AvZ0Ysez8ODpAE5OxpsqnOxFwHaqGFKEgUAGOQAnKYNT1ZPLNh+tccRw04sH3kA3Xy NzxScwTFRRSEGDXktohs/eEYaL6LfB+LavmdFv0kmF0RynM5x1effcf3qhKFayeiZ1 13mHZavxUSLav96ABdgSGoFaWD2VX00AN6hdIoK7gFZFeg/onyAj44cYlEv271zUB2 1Q0QUkZE+QIe6CKu1Ybkbcy4ldXS95mOYkGx07AM3hqk4zD0ePCP5RglemIXNfZOcQ woDjIpiZ9d/Ww== From: Damien Le Moal To: Manivannan Sadhasivam , =?utf-8?q?Krzy?= =?utf-8?q?sztof_Wilczy=C5=84ski?= , Kishon Vijay Abraham I , Bjorn Helgaas , Lorenzo Pieralisi , Rob Herring , Jonathan Corbet , Jingoo Han , linux-pci@vger.kernel.org Cc: Rick Wertenbroek , Niklas Cassel Subject: [PATCH v4 7/7] PCI: dwc: endpoint: Define the .map_align() controller operation Date: Mon, 7 Oct 2024 13:03:19 +0900 Message-ID: <20241007040319.157412-8-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241007040319.157412-1-dlemoal@kernel.org> References: <20241007040319.157412-1-dlemoal@kernel.org> Precedence: bulk X-Mailing-List: linux-pci@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The function dw_pcie_prog_outbound_atu() used to program outbound ATU entries for mapping RC PCI addresses to local CPU addresses does not allow PCI addresses that are not aligned to the value of region_align of struct dw_pcie. This value is determined from the iATU hardware registers during probing of the iATU (done by dw_pcie_iatu_detect()). This value is thus valid for all DWC PCIe controllers, and valid regardless of the hardware configuration used when synthesizing the DWC PCIe controller. Handle this PCI address alignment constraint by defining the endpoint controller .map_align() operation to calculate a mapping size and the offset into the mapping based on the requested RC PCI address and size to map. Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/pci/controller/dwc/pcie-designware-ep.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 43ba5c6738df..501e527c188e 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -268,6 +268,20 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr, return -EINVAL; } +static int dw_pcie_ep_map_align(struct pci_epc *epc, u8 func_no, u8 vfunc_no, + struct pci_epc_map *map) +{ + struct dw_pcie_ep *ep = epc_get_drvdata(epc); + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + size_t mask = pci->region_align - 1; + + map->map_pci_addr = map->pci_addr & ~mask; + map->map_ofst = map->pci_addr & mask; + map->map_size = ALIGN(map->map_ofst + map->pci_size, ep->page_size); + + return 0; +} + static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, phys_addr_t addr) { @@ -444,6 +458,7 @@ static const struct pci_epc_ops epc_ops = { .write_header = dw_pcie_ep_write_header, .set_bar = dw_pcie_ep_set_bar, .clear_bar = dw_pcie_ep_clear_bar, + .map_align = dw_pcie_ep_map_align, .map_addr = dw_pcie_ep_map_addr, .unmap_addr = dw_pcie_ep_unmap_addr, .set_msi = dw_pcie_ep_set_msi,