From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794312124; b=l21qO1xzhXdCH5EsYCIoFPkf2sSxX/4wMkDgu3Go+EB3h0ycoqJwxnkQYNS/fTU7Wyly DcMQJgAr0kuFKBHyTDPrpolMWIavdpMnqxBcCCgvpGvmfs2QgTX/nqKe9ccVG3JS/BTc6 co+M4Qx01g79zWLKt4rNagpcExQRz5o5PxSauGApz37/47+ER4RwplPoeCAlznB4Mo3i6 hH3iT9MMF6TqyLx4yU6gh+vo+ZmL9Tt5swkJixdulO3zO+RxeX0YRn768h+plTxVEh/Un s1divtJ5F2Mka+FfGR9rwca39ZWP56nQPJWuVEGlfhrBhFtNx/cP2zXyqS+C74ICszQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794312124; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=+JQr3Vc7XjcpSLu/ajq6/OOdIY7aWxwjHT4Ev3delJM=; b=zgzerSlSi5uwrXpA5EzYNi4+HP+gQXnbWIhglIYFGAYBoxd5N0YP5o/NXjEeWNQJ2vOo Qc1OcaffXdDLArfwVaD8dmdWxO3Qo2meqBLQPCf9Pdz0ZwPGec5daVBpglHfgODTya4ZV iKkF7yGdjDLulcrDVMXsoWEuw+Qy3uDH+tfydKvp4295/u0Sr0MrL1kwZ68HlEDA6BlZJ w90ta3CTCubAALeh8udT4Daq4U0vLBM6JA3vP53c/UhWxWdYa1MqDLZCgjHPchNCzHUzF 4U4Bvcx5ANJa87DaMMgRT1iOG77raJPyRQ5vUdgjoDph2c//XXs+Oh/A50Ku6IdwZtg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=kML02HZI; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D4FA606A31C for ; Tue, 10 Nov 2026 12:02:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=kML02HZI Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C51B1F0089F; Tue, 10 Nov 2026 12:02:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1794312123; bh=+JQr3Vc7XjcpSLu/ajq6/OOdIY7aWxwjHT4Ev3delJM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=kML02HZIf2r9SPZaNo3dDGS0Fhy0MHFsT6lLQivEF5x75ZpOGDRhZBgA3j6bf2el5 S6FT7Bflo03gpm8KHMJNvxEO1Pr/C+9aICXI9Ui4cgIY2vnLdYVejF3X+4jjg8pjwO igbgp2h3t675wrOL8p8MMR8Y/lKHzRV8L307r68TP7xTbmPEDwXCnBchBIRvdOLZJh NJ1ieVDqyUQfxI/d3i3PSq9ucMe6XtqwdV4JOO7ivkzC4xfF9x/q3KGSsr+ru0Cvf5 T/kbpjH9LLDgzUY9AuSQVqpRIY5/8aDMk9QsbSlQ7dXIPIXWMV311fvg5cfkeAf3FS iY8ZmpPr3crxw== From: Sasha Levin To: stable@vger.kernel.org Cc: Vishnu Reddy , Vikash Garodia , Dmitry Baryshkov , Bryan O'Donoghue , Sasha Levin Subject: [PATCH 6.18.y] media: iris: Fix iova allocation from restrict region Date: Tue, 10 Nov 2026 07:02:01 -0500 Message-ID: <20261110120129.931826-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261107050741-failed-6.18-200473c198b2@kernel.org> References: <20261107050741-failed-6.18-200473c198b2@kernel.org> X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Vishnu Reddy [ Upstream commit 200473c198b201c308dfb916fb3233074d9407fa ] The VPU issues DMA through several SMMU streams, and the hardware does not give every stream the same addressable range. The non-pixel stream cannot address the low 600MB of IOVA space, while the pixel stream can address the full range: +-----------------------------------------------------------+ | non-pixel stream addressable range (600 MB - 3.5 GB) | | 0x25800000 - 0xe0000000 | +-----------------------------------------------------------+ | pixel stream addressable range (0 - 3.5 GB) | | 0x00000000 - 0xe0000000 | +-----------------------------------------------------------+ A single "iommus" property on the video-codec node puts every stream in one IOMMU domain sharing one IOVA space, so nothing stops a non-pixel buffer from landing below 600MB. Once an allocation lands below that boundary the hardware faults, which shows up as unhandled SMMU page faults and spontaneous reboots. https://gitlab.freedesktop.org/drm/msm/-/work_items/100 Fix this by reserving the 0-600MB range, below the boundary the non-pixel stream cannot address, using dma_iova_try_alloc() so the IOMMU-DMA core never hands that range out to a real DMA mapping. This reserves only IOVA space, it does not allocate any physical memory. Since sub-nodes for non-pixel, pixel, and secure streams do not exist yet and only a single device is available, the restriction is applied to both non-pixel and pixel stream IDs. Fixes: d7378f84e94e ("media: iris: introduce iris core state management with shared queues") Cc: stable@vger.kernel.org Reviewed-by: Vikash Garodia Reviewed-by: Dmitry Baryshkov Signed-off-by: Vishnu Reddy Signed-off-by: Bryan O'Donoghue [ sashal: Adjusted iris_probe() context to retain iris_session_init_caps(core) immediately before the IOVA reservation. ] Signed-off-by: Sasha Levin --- drivers/media/platform/qcom/iris/iris_core.h | 6 ++ drivers/media/platform/qcom/iris/iris_probe.c | 62 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/iris/iris_core.h b/drivers/media/platform/qcom/iris/iris_core.h index fb194c967ad4f..530fe14c3a477 100644 --- a/drivers/media/platform/qcom/iris/iris_core.h +++ b/drivers/media/platform/qcom/iris/iris_core.h @@ -7,6 +7,7 @@ #define __IRIS_CORE_H__ #include +#include #include #include @@ -25,6 +26,9 @@ struct icc_info { #define IRIS_FW_VERSION_LENGTH 128 #define IFACEQ_CORE_PKT_SIZE (1024 * 4) +#define IRIS_NP_RESERVE_IOVA_START 0x0 +#define IRIS_NP_RESERVE_IOVA_SIZE 0x25800000 + enum domain_type { ENCODER = BIT(0), DECODER = BIT(1), @@ -73,6 +77,7 @@ enum domain_type { * @instances: a list_head of all instances * @inst_fw_caps_dec: an array of supported instance capabilities by decoder * @inst_fw_caps_enc: an array of supported instance capabilities by encoder + * @iova_state: a pointer to an array of dma_iova_state entries reserved for restricted IOVA region */ struct iris_core { @@ -117,6 +122,7 @@ struct iris_core { /* encoder and decoder have overlapping caps, so two different arrays are required */ struct platform_inst_fw_cap inst_fw_caps_dec[INST_FW_CAP_MAX]; struct platform_inst_fw_cap inst_fw_caps_enc[INST_FW_CAP_MAX]; + struct dma_iova_state *iova_state; }; int iris_core_init(struct iris_core *core); diff --git a/drivers/media/platform/qcom/iris/iris_probe.c b/drivers/media/platform/qcom/iris/iris_probe.c index cdeb78ba605ae..b6251493bd9cc 100644 --- a/drivers/media/platform/qcom/iris/iris_probe.c +++ b/drivers/media/platform/qcom/iris/iris_probe.c @@ -153,6 +153,57 @@ static int iris_init_resources(struct iris_core *core) return iris_init_resets(core); } +static void iris_unreserve_iova_region(struct device *dev, struct dma_iova_state *iova_state) +{ + unsigned int i; + + for (i = 0; dma_iova_size(&iova_state[i]); i++) + dma_iova_free(dev, &iova_state[i]); +} + +static int iris_reserve_iova_region(struct device *dev, struct dma_iova_state **iova_state, + unsigned long start, unsigned long size) +{ + unsigned long dma_limit = dev->bus_dma_limit; + unsigned long end, rem, chunk; + struct dma_iova_state *state; + unsigned int count = 0; + int ret = -ENOMEM; + + state = devm_kcalloc(dev, BITS_PER_TYPE(dma_addr_t) + 1, sizeof(*state), GFP_KERNEL); + if (!state) + return ret; + + end = start + size; + rem = end - max(start, PAGE_SIZE); + dev->bus_dma_limit = end - 1; + + while (rem) { + chunk = min(end & -end, (u64)1 << (fls64(rem) - 1)); + + if (!dma_iova_try_alloc(dev, &state[count], 0, chunk)) + goto err_free_iova; + + if (state[count].addr != end - chunk || state[count].__size != chunk) + goto err_free_iova; + + rem -= chunk; + end -= chunk; + count++; + } + + *iova_state = state; + dev->bus_dma_limit = dma_limit; + + return 0; + +err_free_iova: + iris_unreserve_iova_region(dev, state); + dev->bus_dma_limit = dma_limit; + + return ret; +} + static int iris_register_video_device(struct iris_core *core, enum domain_type type) { struct video_device *vdev; @@ -210,6 +261,8 @@ static void iris_remove(struct platform_device *pdev) v4l2_device_unregister(&core->v4l2_dev); + iris_unreserve_iova_region(core->dev, core->iova_state); + mutex_destroy(&core->lock); } @@ -272,10 +325,15 @@ static int iris_probe(struct platform_device *pdev) iris_session_init_caps(core); - ret = v4l2_device_register(dev, &core->v4l2_dev); + ret = iris_reserve_iova_region(dev, &core->iova_state, IRIS_NP_RESERVE_IOVA_START, + IRIS_NP_RESERVE_IOVA_SIZE); if (ret) return ret; + ret = v4l2_device_register(dev, &core->v4l2_dev); + if (ret) + goto err_unresv_iova_region; + ret = iris_register_video_device(core, DECODER); if (ret) goto err_v4l2_unreg; @@ -309,6 +367,8 @@ static int iris_probe(struct platform_device *pdev) video_unregister_device(core->vdev_dec); err_v4l2_unreg: v4l2_device_unregister(&core->v4l2_dev); +err_unresv_iova_region: + iris_unreserve_iova_region(dev, core->iova_state); return ret; } -- 2.53.0