From patchwork Fri Oct 4 05:07:36 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: 13821781 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 A89D628F3 for ; Fri, 4 Oct 2024 05:07:46 +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=1728018466; cv=none; b=AoH8r0t7FFQpJnpC9OD7+IW7PGGZClBg1yCkhM0frMdURf6CN/1SK+qdqR0CuPo+T6HMBmKh3G0OavNQol8NMT1B8RZXAyI9unP2Z0/7+vqsjWBO0Q7p0FbdDAvQj9sNqdklZ+GlPt1fPhkUqIFnRNPoa+TInnwKKm94WLMhZtU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018466; c=relaxed/simple; bh=0AHYdi66CUseKX9KfJciikHxCnFPbS6rNBFVhBnQySc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UNE8LsWmM+u6F3i3R3I0YbZ64FWBXfGgzj85QTU4mwWkGHQdAIs32LOZjHESvjmnQy27lxNrJWZ19YeGSJ/W0D/Ld3mbrktBGppcZHWWJFH6M8UrEMLrUBpsfe2TqLBDa10v+vFHdytfPuCxbd+3bam4um2NFyQKpuRIRdBCIK0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tN2r+SSJ; 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="tN2r+SSJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1F12C4CED0; Fri, 4 Oct 2024 05:07:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018466; bh=0AHYdi66CUseKX9KfJciikHxCnFPbS6rNBFVhBnQySc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tN2r+SSJ2Yy2qDPdYtXSa9DDeF7I2q1458TjDSOcAN0xd0Fgqy+GYu0fwYhIDEY/C diw5kep16oTIPuAcw0a05ORpXtkOn3sjpfUr5ieRFLaqFWDAd63OeYAV8M51st09lU wdsB/FcYhais3u1JTyJ/WUrOWs7997Tj7EqYtRQFQo6lv8f7eAEOg5nqOV5TpABX1l VXI+zDBR0id4jdvP6xl+ug30HTT1Q7DM3wKGxXona7fjL9oXOqiZMX44IJzFN8pxVM Tr0vHgfxqpt65U2fdJiySF0vHr0WUq+7OwzmI0wPOmsVJu3I7N2wc9wWxzAlWKsG9R ILD+Nq2Wsf84A== 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 v3 1/7] PCI: endpoint: Introduce pci_epc_function_is_valid() Date: Fri, 4 Oct 2024 14:07:36 +0900 Message-ID: <20241004050742.140664-2-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 Fri Oct 4 05:07:37 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: 13821782 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 D710528F3 for ; Fri, 4 Oct 2024 05:07:47 +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=1728018467; cv=none; b=QIHtLM/rWKf5qiL02Z7lru6PeSSzQU7nWPr6fd1pZh3UAfhp74y9g0fTy9rfQAVOJFOk+jWVsPAtKTWhTaSo/gb/BK2osOdWrc46E3vtCtjwVQMckZ2+cdwK0qANs9/zUEjUnvXPEZJI5TaYeZAXagRdiqYe0c0gK3ix891wvrU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018467; c=relaxed/simple; bh=OEJNUJ+A1DCBBOwnLmpeP8AJh0oB7xPkq284SDdeLs8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lf7PrrjLcNfI/Eex/N9v445gWSe1Ihe8dFYBTJg5pqdF2c0bPGx5UAv/YzdvSjlNeXcvWEcaqWejzLJucRGkUdCX1ffM1NUVx46UKbUiPwnM8aMJmpnkmRRlPBURm+AUD/u452QM2x3A3YWsaFYSFhGYFnTPn1kYIbMi/ShJxEk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PnhVCia+; 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="PnhVCia+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7A33EC4CECD; Fri, 4 Oct 2024 05:07:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018467; bh=OEJNUJ+A1DCBBOwnLmpeP8AJh0oB7xPkq284SDdeLs8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PnhVCia+BLT9nmoo1mf5SfKX0+u/o1UhJqCctZEvzty2PgpCPtt/myeYRsLdM2Qul ouBgpKsoi40C1ayi6RCoG+Z3OyqIyOy3X4VkPR9GXEjJDixXqLcnMYtIdA4mu0VNjL SniUkgrLO3Q9ufMFgnqAh0iZmRQqurbO8xeKOoWvpoiaKCV08sy2i/kfoJzTe9d2PF 46smVlKhIz63tJK9tCZBM2UOCCosoGE4rDLjhELyKjWZiXIfmwFG/K2wRYYdLhqtyn z3mHlFbwfADr9zIbGBBfYlUw0fI9Adsh54UnEehiHkMQXTxmHSscFGb2pe+zJWauAW RekYL7GZLiJ+Q== 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 v3 2/7] PCI: endpoint: Improve pci_epc_mem_alloc_addr() Date: Fri, 4 Oct 2024 14:07:37 +0900 Message-ID: <20241004050742.140664-3-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 window size. Add a check to skip bitmap_find_free_region() calls for such case. Also change the final return to return NULL to simplify the code. Signed-off-by: Damien Le Moal --- 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 Fri Oct 4 05:07:38 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: 13821783 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 51D9D28F3 for ; Fri, 4 Oct 2024 05:07:49 +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=1728018469; cv=none; b=XEEhyeYDb+/wHiJeej5DPTGQhVoOTxniopNiWezqCZSQ4GrEtcb3vm026MKcbCWaBZ93MdLehF2ebtYNfQRVnuaemSWRS9pRjD5sC4zG3GlagEu3Kd8BGqF2TWzxhG+rQeI/KdJ3+A1xJDwlwiR8CdoGCsRT2rv5TgwLF7jr9/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018469; c=relaxed/simple; bh=oT22oxE0jFfZHpFjv7TN6YXdBj9Itsrn2j8QJgZtGYk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Fj48ipM0SvDRIPrh9vuAD9Ev9xohGt0TMFg5A8UkDczvSRj1x8dIlfA11ZX/xJ3V7iPOdMu2gYbEf1le7miy9uXM01olbezuftHaMZ9u6ulZKp6++nOWybnOQUXmNsk3HjYFBRSUc1mDob36dcZl4kJMvNkmv/YBbc7HJUfhC28= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EpDMYsO8; 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="EpDMYsO8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F1F0EC4CED0; Fri, 4 Oct 2024 05:07:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018469; bh=oT22oxE0jFfZHpFjv7TN6YXdBj9Itsrn2j8QJgZtGYk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EpDMYsO8iFyCkUnLa+HqSrtDU9tuuRl7+gneuTHs2xV97Xnrz59E4S4W6aYuamI5r S2a4CKL/TXGWG6CHl+pVWoOuQ3t9LI1G/Ar2+eQ8vHQXHcWAegrPRh1+Khtdv8GDXy mJmwAcG7kwX8YMAvjJgptfmQVpjXK1Nzl+AUHrRX7/Oi5AY4f05SHbFbZHpphao6CC dGWlpAUoTDrQ3rVsDcMIYwpU1S0hOPxJ/4zpduyI1K4k71reAdbPcVOKUop/nLZkuz 7uw4qs9hOUB/x9brtKgmNF/36DT4cY52cO/vbpfSQ7k/+QXlXpaCAbS0hrKNW6a47k MmhU8JydCxAmg== 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 v3 3/7] PCI: endpoint: Introduce pci_epc_map_align() Date: Fri, 4 Oct 2024 14:07:38 +0900 Message-ID: <20241004050742.140664-4-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 | 56 +++++++++++++++++++++++++++++ include/linux/pci-epc.h | 37 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c index b854f1bab26f..48dd3c28ac4c 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -435,6 +435,62 @@ 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; + + 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 */ + 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 Fri Oct 4 05:07:39 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: 13821784 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 0A23328F3 for ; Fri, 4 Oct 2024 05:07:50 +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=1728018471; cv=none; b=BAPVpu5v3ArwA5LHexmh1bR1pAJASwmIuFLyWSHgXkffxPHtEwQm9DcBMpR+YUH5wg7S9d/oDS/BQtcFrL5rbSn4E/MFieng7Bijslmr6S5ZqZrqLljRSqGOqx7pSBs8QPcym1gU/3DYqayvTbichvzSSDkFGXD0RImWKQydj7o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018471; c=relaxed/simple; bh=oa8mRw8TDpxjvIkSC6a8Senr13Su2YagH/W9NdfmVXs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FMr1YERaOEz8P0nA2T/YHQ+rm1h7qfEQr+xp94AcoYndfrONxYDRNbD6NBaVpGA9LjIn55N4y3bioRmMwDJPLvSd8QqjCUDm70m5Za0PvB5N386cLq80AACKFloJJLAuqZPsh0iet5S8Rler8QzRu7RxGEZKvbpHCRtVcsBkfcU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JRptTZ1j; 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="JRptTZ1j" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6FEC8C4CECD; Fri, 4 Oct 2024 05:07:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018470; bh=oa8mRw8TDpxjvIkSC6a8Senr13Su2YagH/W9NdfmVXs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JRptTZ1jTYP8JgDPioviakGDajXR4Mlqb9nRGDrKoX+Ux4IzjEuOxVwKf/OywXkd2 O2kUCBfBQkNs5Zm/6VFkuOlMIvSs1oMfBohoTTLyngb3b/8yFP+5nbHq/PAIugNAGt ksrbQ6kYPVMssyGpMXrVFJcuAwaMiJpggTBqrLD6m7IKNozD1MJCim0m35HCrWlSBO 7vFJcSaymTOa0E648ogcn7qBGTAAEa1WmjbIaHQmjmOI0jHh6XUJAxYPZvs7GfyUST 5FaeBlPBGgqt0hoe7a7qmNH2XUTXhSqWPk/3KNnINt1E1+/m55AI/nmK97nAFXof7b lAGRUOLeCVKtg== 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 v3 4/7] PCI: endpoint: Introduce pci_epc_mem_map()/unmap() Date: Fri, 4 Oct 2024 14:07:39 +0900 Message-ID: <20241004050742.140664-5-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 48dd3c28ac4c..5f3b0a86d6fe 100644 --- a/drivers/pci/endpoint/pci-epc-core.c +++ b/drivers/pci/endpoint/pci-epc-core.c @@ -522,6 +522,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 Fri Oct 4 05:07:40 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: 13821785 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 407B42868E for ; Fri, 4 Oct 2024 05:07:52 +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=1728018472; cv=none; b=FBUA/9vMfSeUy25rO+Ad1xoY+AmEo1I9AaHPTBGaPzmex5Aqb85YtjUxy9Pttmq8eeaR//eR1SEoBY2EevMe2bXkj9iYZL6gY3ltmk5p+yTwN9X+3zZfvC7QQaCSkQ7Bg3pN2OdNxwstApeW/qzLyy1avV2uv38YOvmuh180v8s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018472; c=relaxed/simple; bh=a6NqLeJydd97b8EHnOSDAMW27491LOJQ6VXC6fEYHu0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pRNLLlLaHZ2hbPKBgtadAAKWnLBtiQsEDSM0pWnDEUabq8D81dt2oX6azGwgscTrLHSvDtSb6XNBbPPpr1qJ/b4kNvFavNKwgJNYnjBhLk9iZ3eJOG7qHDbpmhk5g4v/B4xyKUH5PXNJHSb8MGsMiZdBGN8VDd7sypak2hncRB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=eLSqnoUb; 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="eLSqnoUb" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E234CC4CED0; Fri, 4 Oct 2024 05:07:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018472; bh=a6NqLeJydd97b8EHnOSDAMW27491LOJQ6VXC6fEYHu0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eLSqnoUb2GfOD5af86smBni5EgMsBgqIezzsCJnslC9PGUTYCkjDwafem2HIRl9dA Rj5SB97Z27ruYXeQ2W33SSht20phsjdZpFIdqxMU+rVzatCNEaDA2S7CtquDjsetsn +OBy4LbTHTOuz2u718e3PqUu1dCb4kGW08clqBzCGGke6MR7CezfRr/sSVi+azrGQn o27dKtz17egaBDpn23HzoVX9g3ovv8qFOvv9zGgq3rabC5qGIF+tiqyX7mUbcWEu08 X4R//H8Ivyv25cQUKDa/Wri73MUrJtPtHtWtvZOwfA5YezZuG4MJdGUv4jk94vqWDh reEhLBNwIMOSg== 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 v3 5/7] PCI: endpoint: Update documentation Date: Fri, 4 Oct 2024 14:07:40 +0900 Message-ID: <20241004050742.140664-6-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Documentation/PCI/endpoint/pci-endpoint.rst b/Documentation/PCI/endpoint/pci-endpoint.rst index 21507e3cc238..80061110441d 100644 --- a/Documentation/PCI/endpoint/pci-endpoint.rst +++ b/Documentation/PCI/endpoint/pci-endpoint.rst @@ -117,6 +117,39 @@ 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() + + The PCI endpoint controller may impose constraints on the RC PCI addresses + that can be mapped. The function pci_epc_map_align() allows endpoint drivers + to discover and handle such constraint 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 offset into the + allocated memory to use for accessing the target RC PCI address. + +* 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 endpoitn 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 Fri Oct 4 05:07:41 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: 13821786 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 BC7B92868E for ; Fri, 4 Oct 2024 05:07:53 +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=1728018473; cv=none; b=ljnwlKQonq1YM29wnzvyXhbWAnYeLiVb3MDVkxqC9K6r/zSCHBCAt+35gF8ijXXwnVgO3mrgmCTUTg0G6EO40uHsvf43G6LbFzeMxAjLTPh8sqBYtW+JiBf5Nmdse2czq3tuDl9KNzMmhKDX0ae1DRcdOg09LoMNIUeGv5krsng= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018473; c=relaxed/simple; bh=z1T4GvXAzBQMx0pdZObj1tDkhM6X+SAMlzpX3rMFcqw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DoR50lQsfWcDpvDFFTiB7d689+9/RP0EbK9QxjDpqVEWFHrMcZ/78K98UoqtTbuhyxmhe61A7iPh7a2DXbcIQydLZXSXBsoc5PVEU4cmZ6O71xmutpghEg+XmO4Y1hTgmtGcF+4zeVoIvc2S42DvcFv8ZR35HCpxOUeoWUKKEbw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bVLiDtEe; 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="bVLiDtEe" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 692DDC4CECD; Fri, 4 Oct 2024 05:07:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018473; bh=z1T4GvXAzBQMx0pdZObj1tDkhM6X+SAMlzpX3rMFcqw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bVLiDtEeLdphrX/VewCRtqVVTqpfP4fC5abfRgskHTOQS8/c57UwvkmFpNIAgf0/Y PavkYWkyGLNaX5XU+EtOr7YrM+RUXtLO5shnGbj6ZcVZLR8NIRG122oLBUNdujdSRI KDKuWjF0vYiXse5+G+eJeEl55gbIVSQcQeDnbCsxKpEJSj9y1fNbkZOEoiJrzMM8ym 1RYnKrm/6qvFsbINN1PkhYB7rW44jamMDO6JnZaRnn7MEbS0txxvuv9DHZcJEcyMJB 8vlMFwFcyf7b9v5s/bXnTrsQ0IOHAhcoyz7VGhRUPUxI0lQD+yFRUN4pKaoATYR5AZ 8T5mrr3k+sZ0Q== 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 v3 6/7] PCI: endpoint: test: Use pci_epc_mem_map/unmap() Date: Fri, 4 Oct 2024 14:07:41 +0900 Message-ID: <20241004050742.140664-7-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 --- 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 Fri Oct 4 05:07:42 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: 13821787 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 424022868E for ; Fri, 4 Oct 2024 05:07:55 +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=1728018475; cv=none; b=gM7/qHsBj8KRzhlf9lNU2HPwPHnRlkBucdOYoWJV1r2qfe2gjDGvH7wCGvusfqC14kb/mDt8Bm2M8HiQat+irYUHRORlGA15nf3RQ4gn8uVVDwE7J9/WMu9rqA61k2m5dLCbuW0XtisMm823j301PkEHKJGGiRTF0M3evEZh2eU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1728018475; c=relaxed/simple; bh=q2TrCapCGc8UI1RQFOlQzQ9SBIo9TvptPVNED+gV1WE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ILfDWqsmzpWdAv1L1ohx2M0TMQj0Kglc0oOLSAi2OWKDHDQSbuSA/y8+piQyP6iP7SzXPERqj2BkXsOui5g4jiK9sQzz5cEAq+kUttjUeqGOln0dIvxMor+LbiwC/KwpXMhkNsC6q1nbquVW9h7RXtKyxjWmmKftxSin9HukGoE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UsRmerkn; 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="UsRmerkn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E450FC4CECE; Fri, 4 Oct 2024 05:07:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1728018475; bh=q2TrCapCGc8UI1RQFOlQzQ9SBIo9TvptPVNED+gV1WE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UsRmerknaI7No+xIlsejgFlqo4v4NRBppi6OOynHhOwD/ON3y6nVFvY/ckYT4e70H RBVldvulBcJNnMuNlvt8f2VlJ1CByZS3IMjRYb2g73AScULBOLfJbOf1UMoQl7oSI9 l3Te2bZe7fMl0/2O/ju28sje6uM3bDz2JwYVftljv42y2gPFJi8ydsE7IkoEawaxkn ofrcf354eCUGPaj9cuTqLoN+PsN5FhVsCc3fDx846EEM3EJsWM6AILwpqsOe4nlaZ7 RhoWjTx1Ghisk31Gqu0g2qw993o18KGnrRuDo/4Etav0ggt9lc79XotNb6kbqHzpB7 xYJSrpK7mK4jw== 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 v3 7/7] PCI: dwc: endpoint: Define the .map_align() controller operation Date: Fri, 4 Oct 2024 14:07:42 +0900 Message-ID: <20241004050742.140664-8-dlemoal@kernel.org> X-Mailer: git-send-email 2.46.2 In-Reply-To: <20241004050742.140664-1-dlemoal@kernel.org> References: <20241004050742.140664-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 struct dw_pcie->region_align (generally 64K). Handle this 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,