Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 09/11] iommu/arm-smmu-v3: Replace smmu with master in arm_smmu_inv
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

Storing master allows to backtrack the master pointer from an invalidation
entry, which will be useful when handling ATC invalidation time outs.

No functional changes.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  2 +-
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c  | 34 +++++++++++--------
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 24 +++++++------
 3 files changed, 33 insertions(+), 27 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index 1d72e5040ea97..26e0ee0bb5b45 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -662,7 +662,7 @@ enum arm_smmu_inv_type {
 };
 
 struct arm_smmu_inv {
-	struct arm_smmu_device *smmu;
+	struct arm_smmu_master *master;
 	u8 type;
 	u8 size_opcode;
 	u8 nsize_opcode;
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
index add671363c828..ef0c0bfe44206 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
@@ -653,39 +653,43 @@ static void arm_smmu_v3_invs_test_verify(struct kunit *test,
 	}
 }
 
+static struct arm_smmu_master invs_master = {
+	.smmu = &smmu,
+};
+
 static struct arm_smmu_invs invs1 = {
 	.num_invs = 3,
-	.inv = { { .type = INV_TYPE_S2_VMID, .id = 1, },
-		 { .type = INV_TYPE_S2_VMID_S1_CLEAR, .id = 1, },
-		 { .type = INV_TYPE_ATS, .id = 3, }, },
+	.inv = { { .master = &invs_master, .type = INV_TYPE_S2_VMID, .id = 1, },
+		 { .master = &invs_master, .type = INV_TYPE_S2_VMID_S1_CLEAR, .id = 1, },
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 3, }, },
 };
 
 static struct arm_smmu_invs invs2 = {
 	.num_invs = 3,
-	.inv = { { .type = INV_TYPE_S2_VMID, .id = 1, }, /* duplicated */
-		 { .type = INV_TYPE_ATS, .id = 4, },
-		 { .type = INV_TYPE_ATS, .id = 5, }, },
+	.inv = { { .master = &invs_master, .type = INV_TYPE_S2_VMID, .id = 1, }, /* dup */
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 4, },
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 5, }, },
 };
 
 static struct arm_smmu_invs invs3 = {
 	.num_invs = 3,
-	.inv = { { .type = INV_TYPE_S2_VMID, .id = 1, }, /* duplicated */
-		 { .type = INV_TYPE_ATS, .id = 5, }, /* recover a trash */
-		 { .type = INV_TYPE_ATS, .id = 6, }, },
+	.inv = { { .master = &invs_master, .type = INV_TYPE_S2_VMID, .id = 1, }, /* dup */
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 5, }, /* recover a trash */
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 6, }, },
 };
 
 static struct arm_smmu_invs invs4 = {
 	.num_invs = 3,
-	.inv = { { .type = INV_TYPE_ATS, .id = 10, .ssid = 1 },
-		 { .type = INV_TYPE_ATS, .id = 10, .ssid = 3 },
-		 { .type = INV_TYPE_ATS, .id = 12, .ssid = 1 }, },
+	.inv = { { .master = &invs_master, .type = INV_TYPE_ATS, .id = 10, .ssid = 1 },
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 10, .ssid = 3 },
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 12, .ssid = 1 }, },
 };
 
 static struct arm_smmu_invs invs5 = {
 	.num_invs = 3,
-	.inv = { { .type = INV_TYPE_ATS, .id = 10, .ssid = 2 },
-		 { .type = INV_TYPE_ATS, .id = 10, .ssid = 3 }, /* duplicate */
-		 { .type = INV_TYPE_ATS, .id = 12, .ssid = 2 }, },
+	.inv = { { .master = &invs_master, .type = INV_TYPE_ATS, .id = 10, .ssid = 2 },
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 10, .ssid = 3 }, /* dup */
+		 { .master = &invs_master, .type = INV_TYPE_ATS, .id = 12, .ssid = 2 }, },
 };
 
 static void arm_smmu_v3_invs_test(struct kunit *test)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f47943f860f3d..13f225f704e73 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -1092,8 +1092,9 @@ arm_smmu_invs_iter_next(struct arm_smmu_invs *invs, size_t next, size_t *idx)
 static int arm_smmu_inv_cmp(const struct arm_smmu_inv *inv_l,
 			    const struct arm_smmu_inv *inv_r)
 {
-	if (inv_l->smmu != inv_r->smmu)
-		return cmp_int((uintptr_t)inv_l->smmu, (uintptr_t)inv_r->smmu);
+	if (inv_l->master->smmu != inv_r->master->smmu)
+		return cmp_int((uintptr_t)inv_l->master->smmu,
+			       (uintptr_t)inv_r->master->smmu);
 	if (inv_l->type != inv_r->type)
 		return cmp_int(inv_l->type, inv_r->type);
 	if (inv_l->id != inv_r->id)
@@ -2650,22 +2651,22 @@ static void arm_smmu_inv_to_cmdq_batch(struct arm_smmu_inv *inv,
 				       unsigned long iova, size_t size,
 				       unsigned int granule)
 {
-	if (arm_smmu_inv_size_too_big(inv->smmu, size, granule)) {
+	if (arm_smmu_inv_size_too_big(inv->master->smmu, size, granule)) {
 		cmd->opcode = inv->nsize_opcode;
-		arm_smmu_cmdq_batch_add(inv->smmu, cmds, cmd);
+		arm_smmu_cmdq_batch_add(inv->master->smmu, cmds, cmd);
 		return;
 	}
 
 	cmd->opcode = inv->size_opcode;
-	arm_smmu_cmdq_batch_add_range(inv->smmu, cmds, cmd, iova, size, granule,
-				      inv->pgsize);
+	arm_smmu_cmdq_batch_add_range(inv->master->smmu, cmds, cmd, iova, size,
+				      granule, inv->pgsize);
 }
 
 static inline bool arm_smmu_invs_end_batch(struct arm_smmu_inv *cur,
 					   struct arm_smmu_inv *next)
 {
 	/* Changing smmu means changing command queue */
-	if (cur->smmu != next->smmu)
+	if (cur->master->smmu != next->master->smmu)
 		return true;
 	/* The batch for S2 TLBI must be done before nested S1 ASIDs */
 	if (cur->type != INV_TYPE_S2_VMID_S1_CLEAR &&
@@ -2692,7 +2693,7 @@ static void __arm_smmu_domain_inv_range(struct arm_smmu_invs *invs,
 		if (READ_ONCE(cur->users))
 			break;
 	while (cur != end) {
-		struct arm_smmu_device *smmu = cur->smmu;
+		struct arm_smmu_device *smmu = cur->master->smmu;
 		struct arm_smmu_cmdq_ent cmd = {
 			/*
 			 * Pick size_opcode to run arm_smmu_get_cmdq(). This can
@@ -2721,7 +2722,8 @@ static void __arm_smmu_domain_inv_range(struct arm_smmu_invs *invs,
 			break;
 		case INV_TYPE_S2_VMID_S1_CLEAR:
 			/* CMDQ_OP_TLBI_S12_VMALL already flushed S1 entries */
-			if (arm_smmu_inv_size_too_big(cur->smmu, size, granule))
+			if (arm_smmu_inv_size_too_big(cur->master->smmu, size,
+						      granule))
 				break;
 			cmd.tlbi.vmid = cur->id;
 			arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd);
@@ -3246,7 +3248,7 @@ arm_smmu_master_build_inv(struct arm_smmu_master *master,
 {
 	struct arm_smmu_invs *build_invs = master->build_invs;
 	struct arm_smmu_inv *cur, inv = {
-		.smmu = master->smmu,
+		.master = master,
 		.type = type,
 		.id = id,
 		.pgsize = pgsize,
@@ -3478,7 +3480,7 @@ static void arm_smmu_inv_flush_iotlb_tag(struct arm_smmu_inv *inv)
 	}
 
 	cmd.opcode = inv->nsize_opcode;
-	arm_smmu_cmdq_issue_cmd_with_sync(inv->smmu, &cmd);
+	arm_smmu_cmdq_issue_cmd_with_sync(inv->master->smmu, &cmd);
 }
 
 /* Should be installed after arm_smmu_install_ste_for_dev() */
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 08/11] iommu/arm-smmu-v3: Mark ATC invalidate timeouts via lockless bitmap
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

An ATC invalidation timeout is a fatal error. While the SMMUv3 hardware is
aware of the timeout via a GERROR interrupt, the driver thread issuing the
commands lacks a direct mechanism to verify whether its specific batch was
the cause or not, as polling the CMD_SYNC status doesn't natively return a
failure code, making it very difficult to coordinate per-device recovery.

Introduce an atc_sync_timeouts bitmap in the cmdq structure to bridge this
gap. When the ISR detects an ATC timeout, set the bit corresponding to the
physical CMDQ index of the faulting CMD_SYNC command.

On the issuer side, after polling completes (or times out), test and clear
its dedicated bit. If set, return -EIO to trigger device quarantine.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  1 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 41 ++++++++++++++++++++-
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
index ef42df4753ec4..1d72e5040ea97 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
@@ -633,6 +633,7 @@ struct arm_smmu_cmdq {
 	atomic_long_t			*valid_map;
 	atomic_t			owner_prod;
 	atomic_t			lock;
+	unsigned long			*atc_sync_timeouts;
 	bool				(*supports_cmd)(struct arm_smmu_cmdq_ent *ent);
 };
 
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index f6901c5437edc..f47943f860f3d 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -445,7 +445,10 @@ void __arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu,
 		 * at the CMD_SYNC. Attempt to complete other pending commands
 		 * by repeating the CMD_SYNC, though we might well end up back
 		 * here since the ATC invalidation may still be pending.
+		 *
+		 * Mark the faulty batch in the bitmap for the issuer to match.
 		 */
+		set_bit(Q_IDX(&q->llq, cons), cmdq->atc_sync_timeouts);
 		return;
 	case CMDQ_ERR_CERROR_ILL_IDX:
 	default:
@@ -895,9 +898,40 @@ int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
 
 	/* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */
 	if (sync) {
+		u32 sync_prod;
+
 		llq.prod = queue_inc_prod_n(&llq, n);
+		sync_prod = llq.prod;
+		/*
+		 * If there is an unhandled ATC timeout, we will have no choice
+		 * but to ignore it, since this was left on the ring buffer in
+		 * the last round. And we certainly don't want it to affect the
+		 * current issue.
+		 */
+		clear_bit(Q_IDX(&llq, sync_prod), cmdq->atc_sync_timeouts);
+
 		ret = arm_smmu_cmdq_poll_until_sync(smmu, cmdq, &llq);
-		if (ret) {
+
+		/*
+		 * Test atc_sync_timeouts first and see if there is ATC timeout
+		 * resulted from this cmdlist. Return -EIO to separate from the
+		 * ARM_SMMU_POLL_TIMEOUT_US software timeout.
+		 *
+		 * FIXME possible unhandled ATC invalidation timeout scenario:
+		 * PCI Completion Timeout can be set to a range longer than the
+		 * ARM_SMMU_POLL_TIMEOUT_US software timeout. -ETIMEDOUT can be
+		 * returned by arm_smmu_cmdq_poll_until_sync() while ATC timeout
+		 * might not be flagged on atc_sync_timeouts yet. In this case,
+		 * we can hardly do anything here since the command queue HW is
+		 * still pending on the ATC command.
+		 */
+		if (test_and_clear_bit(Q_IDX(&llq, sync_prod),
+				       cmdq->atc_sync_timeouts)) {
+			dev_err_ratelimited(smmu->dev,
+					    "CMD_SYNC for ATC_INV timeout at prod=0x%08x\n",
+					    sync_prod);
+			ret = -EIO;
+		} else if (ret) {
 			dev_err_ratelimited(smmu->dev,
 					    "CMD_SYNC timeout at 0x%08x [hwprod 0x%08x, hwcons 0x%08x]\n",
 					    llq.prod,
@@ -4458,6 +4492,11 @@ int arm_smmu_cmdq_init(struct arm_smmu_device *smmu,
 	if (!cmdq->valid_map)
 		return -ENOMEM;
 
+	cmdq->atc_sync_timeouts =
+		devm_bitmap_zalloc(smmu->dev, nents, GFP_KERNEL);
+	if (!cmdq->atc_sync_timeouts)
+		return -ENOMEM;
+
 	return 0;
 }
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 07/11] iommu: Add iommu_report_device_broken() to quarantine a broken device
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

When an IOMMU hardware detects an error due to a faulty device (e.g. an ATS
invalidation timeout), IOMMU drivers may quarantine the device by disabling
specific hardware features or dropping translation capabilities.

However, the core-level states of the faulty device are out of sync, as the
device can be still attached to a translation domain or even potentially be
moved to a new domain that might overwrite the driver-level quarantine.

Given that such an error can likely be triggered from an ISR, introduce an
asynchronous broken_work per group_device, and provide a helper function to
allow driver initiate a quarantine in the core.

Note that the worker function must not use dev->iommu_group that is NULLed
by iommu_deinit_device() holding group->mutex. The cancel_work_sync() only
gets called afterwards outside the mutex. So, this would be a NULL pointer
dereference. Add a stable group backpointer to struct group_device instead.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 include/linux/iommu.h |   6 +++
 drivers/iommu/iommu.c | 100 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 3c5c5fa5cdc6a..97d0e5b90c58f 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -893,6 +893,8 @@ static inline struct iommu_device *__iommu_get_iommu_dev(struct device *dev)
 #define iommu_get_iommu_dev(dev, type, member) \
 	container_of(__iommu_get_iommu_dev(dev), type, member)
 
+void iommu_report_device_broken(struct device *dev);
+
 static inline void iommu_iotlb_gather_init(struct iommu_iotlb_gather *gather)
 {
 	*gather = (struct iommu_iotlb_gather) {
@@ -1207,6 +1209,10 @@ struct iommu_iotlb_gather {};
 struct iommu_dirty_bitmap {};
 struct iommu_dirty_ops {};
 
+static inline void iommu_report_device_broken(struct device *dev)
+{
+}
+
 static inline bool device_iommu_capable(struct device *dev, enum iommu_cap cap)
 {
 	return false;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 810e7b94a1ae2..bb00918e1b70d 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -73,6 +73,7 @@ struct iommu_group {
 };
 
 struct group_device {
+	struct iommu_group *group;
 	struct list_head list;
 	struct device *dev;
 	char *name;
@@ -81,10 +82,12 @@ struct group_device {
 	 * retained. This can happen when:
 	 *  - Device is undergoing a reset
 	 *  - Device failed the last reset
+	 *  - Device is broken and quarantined
 	 */
 	bool blocked;
 	unsigned int reset_depth;
 	struct rcu_head rcu;
+	struct work_struct broken_work;
 };
 
 /* Iterate over each struct group_device in a struct iommu_group */
@@ -170,6 +173,7 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
 						     struct device *dev);
 static void __iommu_group_free_device(struct iommu_group *group,
 				      struct group_device *grp_dev);
+static void iommu_group_broken_worker(struct work_struct *work);
 static void iommu_domain_init(struct iommu_domain *domain, unsigned int type,
 			      const struct iommu_ops *ops);
 
@@ -752,6 +756,8 @@ static void __iommu_group_free_device(struct iommu_group *group,
 	sysfs_remove_link(group->devices_kobj, grp_dev->name);
 	sysfs_remove_link(&dev->kobj, "iommu_group");
 
+	/* Must wait for broken_work to prevent UAF */
+	cancel_work_sync(&grp_dev->broken_work);
 	trace_remove_device_from_group(group->id, dev);
 
 	kfree(grp_dev->name);
@@ -1284,6 +1290,8 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
 		return ERR_PTR(-ENOMEM);
 
 	device->dev = dev;
+	device->group = group;
+	INIT_WORK(&device->broken_work, iommu_group_broken_worker);
 
 	ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
 	if (ret)
@@ -4178,6 +4186,98 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev, bool reset_succeeds)
 }
 EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_done);
 
+static void iommu_group_broken_worker(struct work_struct *work)
+{
+	struct group_device *gdev =
+		container_of(work, struct group_device, broken_work);
+	struct iommu_group *group = gdev->group;
+	struct device *dev = gdev->dev;
+
+	mutex_lock(&group->mutex);
+
+	/*
+	 * iommu_deinit_device() frees dev->iommu under group->mutex. Bail
+	 * out if the device has already been removed from IOMMU handling.
+	 */
+	if (!dev_has_iommu(dev))
+		goto out_unlock;
+
+	if (gdev->blocked) {
+		dev_dbg(dev, "IOMMU has already quarantined the device\n");
+		goto out_unlock;
+	}
+
+	/*
+	 * Quarantine the device completely. For a PCI device, it will be lifted
+	 * upon a pci_dev_reset_iommu_done(pdev, succeeds=true) call indicating
+	 * a device recovery.
+	 *
+	 * For a non-PCI device, currently it has no recovery framework tied to
+	 * the IOMMU subsystem. Quarantine it indefinitely until a recovery path
+	 * is introduced.
+	 */
+	if (!WARN_ON(__iommu_group_block_device(group, gdev)))
+		dev_warn(dev, "IOMMU has quarantined the device\n");
+
+out_unlock:
+	mutex_unlock(&group->mutex);
+	iommu_group_put(group);
+}
+
+/**
+ * iommu_report_device_broken() - Report a broken device to quarantine it
+ * @dev: Device that has encountered an unrecoverable IOMMU-related error
+ *
+ * When an IOMMU driver detects a critical error caused by a device (e.g. an ATC
+ * invalidation timeout), this function should be used to quarantine the device
+ * at the IOMMU core level.
+ *
+ * The quarantine moves the device's RID and PASIDs to group->blocking_domain to
+ * prevent any further DMA/ATS activity that can potentially corrupt the system
+ * memory due to stale device cache entries.
+ *
+ * This function is safe to call from any context, including interrupt handlers,
+ * as it schedules the actual quarantine work asynchronously. The caller should
+ * have already taken driver-level measures (e.g., disabling ATS in hardware) to
+ * contain the fault immediately, before calling this function.
+ *
+ * For PCI devices, the quarantine will be lifted by a successful device reset
+ * via pci_dev_reset_iommu_done(). For non-PCI devices, the quarantine remains
+ * in effect indefinitely until a recovery mechanism is introduced.
+ *
+ * If the device is concurrently being removed or has already been removed from
+ * the IOMMU subsystem, this function will silently return without any action.
+ */
+void iommu_report_device_broken(struct device *dev)
+{
+	struct iommu_group *group = iommu_group_get(dev);
+	struct group_device *gdev;
+	bool scheduled = false;
+
+	if (!group)
+		return;
+	if (!dev_has_iommu(dev))
+		goto out;
+
+	rcu_read_lock();
+	/*
+	 * Note the device might have been concurrently removed from the group
+	 * (list_del_rcu) before iommu_deinit_device() cleared the dev->iommu.
+	 */
+	list_for_each_entry_rcu(gdev, &group->devices, list) {
+		if (gdev->dev != dev)
+			continue;
+		/* iommu_group_broken_worker() must put the group ref */
+		scheduled = schedule_work(&gdev->broken_work);
+		break;
+	}
+	rcu_read_unlock();
+out:
+	if (!scheduled)
+		iommu_group_put(group);
+}
+EXPORT_SYMBOL_GPL(iommu_report_device_broken);
+
 #if IS_ENABLED(CONFIG_IRQ_MSI_IOMMU)
 /**
  * iommu_dma_prepare_msi() - Map the MSI page in the IOMMU domain
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 06/11] iommu: Defer __iommu_group_free_device() to be outside group->mutex
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

__iommu_group_remove_device() holds group->mutex across the entire call to
__iommu_group_free_device() that performs sysfs removals, tracing, and the
final kfree_rcu(). But in fact, most of these operations don't really need
the group->mutex.

The group_device structure will support a work_struct to quarantine broken
devices asynchronously. The work function must hold group->mutex to safely
update group state. cancel_work_sync() must be called, to cancel that work
before freeing the device. But doing so under group->mutex would deadlock
if the worker is already running and waiting to acquire the same lock.

Separate the assertion from __iommu_group_free_device() to another helper
__iommu_group_empty_assert_owner_cnt().

Defer the __iommu_group_free_device() until the mutex is released.

This is a preparatory refactor with no functional change.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommu.c | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index d1be62a07904a..810e7b94a1ae2 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -627,6 +627,19 @@ static struct iommu_domain *pasid_array_entry_to_domain(void *entry)
 
 DEFINE_MUTEX(iommu_probe_device_lock);
 
+static void __iommu_group_empty_assert_owner_cnt(struct iommu_group *group)
+{
+	lockdep_assert_held(&group->mutex);
+	/*
+	 * If the group has become empty then ownership must have been
+	 * released, and the current domain must be set back to NULL or
+	 * the default domain.
+	 */
+	if (list_empty(&group->devices))
+		WARN_ON(group->owner_cnt ||
+			group->domain != group->default_domain);
+}
+
 static int __iommu_probe_device(struct device *dev, struct list_head *group_list)
 {
 	struct iommu_group *group;
@@ -700,10 +713,12 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
 
 err_remove_gdev:
 	list_del_rcu(&gdev->list);
-	__iommu_group_free_device(group, gdev);
+	__iommu_group_empty_assert_owner_cnt(group);
 err_put_group:
 	iommu_deinit_device(dev);
 	mutex_unlock(&group->mutex);
+	if (!IS_ERR(gdev))
+		__iommu_group_free_device(group, gdev);
 	iommu_group_put(group);
 
 	return ret;
@@ -732,20 +747,13 @@ static void __iommu_group_free_device(struct iommu_group *group,
 {
 	struct device *dev = grp_dev->dev;
 
+	lockdep_assert_not_held(&group->mutex);
+
 	sysfs_remove_link(group->devices_kobj, grp_dev->name);
 	sysfs_remove_link(&dev->kobj, "iommu_group");
 
 	trace_remove_device_from_group(group->id, dev);
 
-	/*
-	 * If the group has become empty then ownership must have been
-	 * released, and the current domain must be set back to NULL or
-	 * the default domain.
-	 */
-	if (list_empty(&group->devices))
-		WARN_ON(group->owner_cnt ||
-			group->domain != group->default_domain);
-
 	kfree(grp_dev->name);
 	kfree_rcu(grp_dev, rcu);
 }
@@ -754,7 +762,7 @@ static void __iommu_group_free_device(struct iommu_group *group,
 static void __iommu_group_remove_device(struct device *dev)
 {
 	struct iommu_group *group = dev->iommu_group;
-	struct group_device *device;
+	struct group_device *device, *to_free = NULL;
 
 	mutex_lock(&group->mutex);
 	for_each_group_device(group, device) {
@@ -762,15 +770,18 @@ static void __iommu_group_remove_device(struct device *dev)
 			continue;
 
 		list_del_rcu(&device->list);
-		__iommu_group_free_device(group, device);
+		__iommu_group_empty_assert_owner_cnt(group);
 		if (dev_has_iommu(dev))
 			iommu_deinit_device(dev);
 		else
 			dev->iommu_group = NULL;
+		to_free = device;
 		break;
 	}
 	mutex_unlock(&group->mutex);
 
+	if (to_free)
+		__iommu_group_free_device(group, to_free);
 	/*
 	 * Pairs with the get in iommu_init_device() or
 	 * iommu_group_add_device()
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 05/11] iommu: Change group->devices to RCU-protected list
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

To allow lockless iterations of the group->devices list in an ISR context
that cannot hold the group->mutex, change the list to be RCU protected.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommu.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 768ac728b4cc3..d1be62a07904a 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -84,18 +84,20 @@ struct group_device {
 	 */
 	bool blocked;
 	unsigned int reset_depth;
+	struct rcu_head rcu;
 };
 
 /* Iterate over each struct group_device in a struct iommu_group */
 #define for_each_group_device(group, pos) \
-	list_for_each_entry(pos, &(group)->devices, list)
+	list_for_each_entry_rcu(pos, &(group)->devices, list, \
+				lockdep_is_held(&(group)->mutex))
 
 static struct group_device *__dev_to_gdev(struct device *dev)
 {
 	struct iommu_group *group = dev->iommu_group;
 	struct group_device *gdev;
 
-	lockdep_assert_held(&group->mutex);
+	lockdep_assert(lockdep_is_held(&group->mutex) || rcu_read_lock_held());
 
 	for_each_group_device(group, gdev) {
 		if (gdev->dev == dev)
@@ -666,7 +668,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
 	 * The gdev must be in the list before calling
 	 * iommu_setup_default_domain()
 	 */
-	list_add_tail(&gdev->list, &group->devices);
+	list_add_tail_rcu(&gdev->list, &group->devices);
 	WARN_ON(group->default_domain && !group->domain);
 	if (group->default_domain)
 		iommu_create_device_direct_mappings(group->default_domain, dev);
@@ -697,7 +699,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list
 	return 0;
 
 err_remove_gdev:
-	list_del(&gdev->list);
+	list_del_rcu(&gdev->list);
 	__iommu_group_free_device(group, gdev);
 err_put_group:
 	iommu_deinit_device(dev);
@@ -745,7 +747,7 @@ static void __iommu_group_free_device(struct iommu_group *group,
 			group->domain != group->default_domain);
 
 	kfree(grp_dev->name);
-	kfree(grp_dev);
+	kfree_rcu(grp_dev, rcu);
 }
 
 /* Remove the iommu_group from the struct device. */
@@ -759,7 +761,7 @@ static void __iommu_group_remove_device(struct device *dev)
 		if (device->dev != dev)
 			continue;
 
-		list_del(&device->list);
+		list_del_rcu(&device->list);
 		__iommu_group_free_device(group, device);
 		if (dev_has_iommu(dev))
 			iommu_deinit_device(dev);
@@ -1335,7 +1337,7 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
 	dev->iommu_group = group;
 
 	mutex_lock(&group->mutex);
-	list_add_tail(&gdev->list, &group->devices);
+	list_add_tail_rcu(&gdev->list, &group->devices);
 	mutex_unlock(&group->mutex);
 	return 0;
 }
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 04/11] iommu: Add __iommu_group_block_device helper
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

Move the RID/PASID blocking routine into a separate helper, which will be
reused by a new function to quarantine the device but does not bother the
gdev->reset_depth counter.

No functional changes.

Suggested-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/iommu/iommu.c | 99 ++++++++++++++++++++++++-------------------
 1 file changed, 56 insertions(+), 43 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index df23ef0a26e6c..768ac728b4cc3 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -3958,6 +3958,57 @@ int iommu_replace_group_handle(struct iommu_group *group,
 }
 EXPORT_SYMBOL_NS_GPL(iommu_replace_group_handle, "IOMMUFD_INTERNAL");
 
+static int __iommu_group_block_device(struct iommu_group *group,
+				      struct group_device *gdev)
+{
+	unsigned long pasid;
+	void *entry;
+	int ret;
+
+	lockdep_assert_held(&group->mutex);
+
+	/* Device might be already blocked for a quarantine */
+	if (gdev->blocked)
+		return 0;
+
+	ret = __iommu_group_alloc_blocking_domain(group);
+	if (ret)
+		return ret;
+
+	/* Stage RID domain at blocking_domain while retaining group->domain */
+	if (group->domain != group->blocking_domain) {
+		ret = __iommu_attach_device(group->blocking_domain, gdev->dev,
+					    group->domain);
+		if (ret)
+			return ret;
+	}
+
+	/*
+	 * Update gdev->blocked upon the domain change, as it is used to return
+	 * the correct domain in iommu_driver_get_domain_for_dev() that might be
+	 * called in a set_dev_pasid callback function.
+	 */
+	gdev->blocked = true;
+
+	/*
+	 * Stage PASID domains at blocking_domain while retaining pasid_array.
+	 *
+	 * The pasid_array is mostly fenced by group->mutex, except one reader
+	 * in iommu_attach_handle_get(), so it's safe to read without xa_lock.
+	 */
+	if (gdev->dev->iommu->max_pasids > 0) {
+		xa_for_each_start(&group->pasid_array, pasid, entry, 1) {
+			struct iommu_domain *pasid_dom =
+				pasid_array_entry_to_domain(entry);
+
+			iommu_remove_dev_pasid(gdev->dev, pasid, pasid_dom);
+		}
+	}
+
+	group->recovery_cnt++;
+	return 0;
+}
+
 /**
  * pci_dev_reset_iommu_prepare() - Block IOMMU to prepare for a PCI device reset
  * @pdev: PCI device that is going to enter a reset routine
@@ -3988,8 +4039,6 @@ int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
 {
 	struct iommu_group *group = pdev->dev.iommu_group;
 	struct group_device *gdev;
-	unsigned long pasid;
-	void *entry;
 	int ret;
 
 	if (!pci_ats_supported(pdev) || !dev_has_iommu(&pdev->dev))
@@ -4003,50 +4052,14 @@ int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
 
 	if (gdev->reset_depth++)
 		return 0;
-	/* Device might be already blocked for a quarantine */
-	if (gdev->blocked)
-		return 0;
-
-	ret = __iommu_group_alloc_blocking_domain(group);
-	if (ret)
-		goto err_depth;
 
-	/* Stage RID domain at blocking_domain while retaining group->domain */
-	if (group->domain != group->blocking_domain) {
-		ret = __iommu_attach_device(group->blocking_domain, &pdev->dev,
-					    group->domain);
-		if (ret)
-			goto err_depth;
-	}
-
-	/*
-	 * Update gdev->blocked upon the domain change, as it is used to return
-	 * the correct domain in iommu_driver_get_domain_for_dev() that might be
-	 * called in a set_dev_pasid callback function.
-	 */
-	gdev->blocked = true;
-
-	/*
-	 * Stage PASID domains at blocking_domain while retaining pasid_array.
-	 *
-	 * The pasid_array is mostly fenced by group->mutex, except one reader
-	 * in iommu_attach_handle_get(), so it's safe to read without xa_lock.
-	 */
-	if (pdev->dev.iommu->max_pasids > 0) {
-		xa_for_each_start(&group->pasid_array, pasid, entry, 1) {
-			struct iommu_domain *pasid_dom =
-				pasid_array_entry_to_domain(entry);
-
-			iommu_remove_dev_pasid(&pdev->dev, pasid, pasid_dom);
-		}
+	ret = __iommu_group_block_device(group, gdev);
+	if (ret) {
+		gdev->reset_depth--;
+		return ret;
 	}
 
-	group->recovery_cnt++;
-	return ret;
-
-err_depth:
-	gdev->reset_depth--;
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_prepare);
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 02/11] iommu: Pass in reset result to pci_dev_reset_iommu_done()
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

IOMMU drivers handle ATC cache maintenance. They may encounter ATC-related
errors (e.g., ATC invalidation request timeout), indicating that ATC cache
might have stale entries that can corrupt the memory. In this case, IOMMU
driver has no choice but to block the device's ATS function and wait for a
device recovery.

The pci_dev_reset_iommu_done() called at the end of a reset function could
serve as a reliable signal to the IOMMU subsystem that the physical device
cache is completely clean. However, the function is called unconditionally
even if the reset operation had actually failed, which would re-attach the
faulty device back to a normal translation domain. And this will leave the
system highly exposed, creating vulnerabilities for data corruption:
    IOMMU blocks RID/ATS
    pci_reset_function():
        pci_dev_reset_iommu_prepare(); // Block RID/ATS
        __reset(); // Failed (ATC is still stale)
        pci_dev_reset_iommu_done(); // Unblock RID/ATS (ah-ha)

Instead, add a @reset_succeeds parameter to pci_dev_reset_iommu_done() and
pass the reset result from each caller:
    IOMMU blocks RID/ATS
    pci_reset_function():
        pci_dev_reset_iommu_prepare(); // Block RID/ATS
        rc = __reset();
        pci_dev_reset_iommu_done(!rc); // Unblock or quarantine

On a successful reset, done() restores the device to its RID/PASID domains
and decrements group->recovery_cnt. On failure, the device remains blocked,
and concurrent domain attachment will be rejected until a successful reset.

Suggested-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 include/linux/iommu.h  |  5 +++--
 drivers/iommu/iommu.c  | 28 +++++++++++++++++++++++++---
 drivers/pci/pci-acpi.c |  2 +-
 drivers/pci/pci.c      | 10 +++++-----
 drivers/pci/quirks.c   |  2 +-
 5 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 54b8b48c762e8..d3685967e960a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -1191,7 +1191,7 @@ void iommu_free_global_pasid(ioasid_t pasid);
 
 /* PCI device reset functions */
 int pci_dev_reset_iommu_prepare(struct pci_dev *pdev);
-void pci_dev_reset_iommu_done(struct pci_dev *pdev);
+void pci_dev_reset_iommu_done(struct pci_dev *pdev, bool reset_succeeds);
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
@@ -1521,7 +1521,8 @@ static inline int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
 	return 0;
 }
 
-static inline void pci_dev_reset_iommu_done(struct pci_dev *pdev)
+static inline void pci_dev_reset_iommu_done(struct pci_dev *pdev,
+					    bool reset_succeeds)
 {
 }
 #endif /* CONFIG_IOMMU_API */
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index ff181db687bbf..28d4c1f143a08 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -80,6 +80,7 @@ struct group_device {
 	 * Device is blocked for a pending recovery while its group->domain is
 	 * retained. This can happen when:
 	 *  - Device is undergoing a reset
+	 *  - Device failed the last reset
 	 */
 	bool blocked;
 	unsigned int reset_depth;
@@ -3971,7 +3972,9 @@ EXPORT_SYMBOL_NS_GPL(iommu_replace_group_handle, "IOMMUFD_INTERNAL");
  * reset is finished, pci_dev_reset_iommu_done() can restore everything.
  *
  * Caller must use pci_dev_reset_iommu_prepare() with pci_dev_reset_iommu_done()
- * before/after the core-level reset routine, to decrement the recovery_cnt.
+ * before/after the core-level reset routine. On a successful reset, done() will
+ * decrement group->recovery_cnt and restore domains. On a failure, recovery_cnt
+ * is left intact and the device stays blocked.
  *
  * Return: 0 on success or negative error code if the preparation failed.
  *
@@ -4000,6 +4003,9 @@ int pci_dev_reset_iommu_prepare(struct pci_dev *pdev)
 
 	if (gdev->reset_depth++)
 		return 0;
+	/* Device might be already blocked for a quarantine */
+	if (gdev->blocked)
+		return 0;
 
 	ret = __iommu_group_alloc_blocking_domain(group);
 	if (ret)
@@ -4047,18 +4053,22 @@ EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_prepare);
 /**
  * pci_dev_reset_iommu_done() - Restore IOMMU after a PCI device reset is done
  * @pdev: PCI device that has finished a reset routine
+ * @reset_succeeds: Whether the PCI device reset is successful or not
  *
  * After a PCIe device finishes a reset routine, it wants to restore its IOMMU
  * activity, including new translation and cache invalidation, by re-attaching
  * all RID/PASID of the device back to the domains retained in the core-level
  * structure.
  *
- * Caller must pair it with a successful pci_dev_reset_iommu_prepare().
+ * This is a pairing function for pci_dev_reset_iommu_prepare(). Caller should
+ * pass in the reset state via @reset_succeeds. On a failed reset, the device
+ * remains blocked for a quarantine with the group->recovery_cnt intact, so as
+ * to protect system memory until a subsequent successful reset.
  *
  * Note that, although unlikely, there is a risk that re-attaching domains might
  * fail due to some unexpected happening like OOM.
  */
-void pci_dev_reset_iommu_done(struct pci_dev *pdev)
+void pci_dev_reset_iommu_done(struct pci_dev *pdev, bool reset_succeeds)
 {
 	struct iommu_group *group = pdev->dev.iommu_group;
 	struct group_device *gdev;
@@ -4083,6 +4093,18 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev)
 	if (WARN_ON(!group->blocking_domain))
 		return;
 
+	/*
+	 * A reset failure implies that the device might be unreliable. E.g. its
+	 * device cache might retain stale entries, which potentially results in
+	 * memory corruption. Thus, do not unblock the device until a successful
+	 * reset.
+	 */
+	if (!reset_succeeds) {
+		pci_err(pdev,
+			"Reset failed. Keep it blocked to protect memory\n");
+		return;
+	}
+
 	/* Re-attach RID domain back to group->domain */
 	if (group->domain != group->blocking_domain) {
 		WARN_ON(__iommu_attach_device(group->domain, &pdev->dev,
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 4d0f2cb6c695b..9ffd7f013a7d4 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -977,7 +977,7 @@ int pci_dev_acpi_reset(struct pci_dev *dev, bool probe)
 		ret = -ENOTTY;
 	}
 
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !ret);
 	return ret;
 }
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8479c2e1f74f1..d78e724027c78 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4358,7 +4358,7 @@ int pcie_flr(struct pci_dev *dev)
 
 	ret = pci_dev_wait(dev, "FLR", PCIE_RESET_READY_POLL_MS);
 done:
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !ret);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(pcie_flr);
@@ -4436,7 +4436,7 @@ static int pci_af_flr(struct pci_dev *dev, bool probe)
 
 	ret = pci_dev_wait(dev, "AF_FLR", PCIE_RESET_READY_POLL_MS);
 done:
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !ret);
 	return ret;
 }
 
@@ -4490,7 +4490,7 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
 	pci_dev_d3_sleep(dev);
 
 	ret = pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS);
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !ret);
 	return ret;
 }
 
@@ -4933,7 +4933,7 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
 
 	rc = pci_parent_bus_reset(dev, probe);
 done:
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !rc);
 	return rc;
 }
 
@@ -4978,7 +4978,7 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
 		pci_write_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL,
 				      reg);
 
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !rc);
 	return rc;
 }
 
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 05ce12b6b2f76..6ce79a25e5c76 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4271,7 +4271,7 @@ static int __pci_dev_specific_reset(struct pci_dev *dev, bool probe,
 	}
 
 	ret = i->reset(dev, probe);
-	pci_dev_reset_iommu_done(dev);
+	pci_dev_reset_iommu_done(dev, !ret);
 	return ret;
 }
 
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 03/11] iommu: Add reset_device_done callback for hardware fault recovery
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

When an IOMMU hardware detects an error due to a faulty device (e.g. an ATS
invalidation timeout), IOMMU drivers may quarantine the device by disabling
specific hardware features or dropping translation capabilities.

To recover from these states, the IOMMU driver needs a reliable signal that
the underlying physical hardware has been cleanly reset (e.g., via PCIe AER
or a sysfs Function Level Reset) so as to lift the quarantine.

Introduce a reset_device_done callback in struct iommu_ops. Trigger it from
the existing pci_dev_reset_iommu_done() path to notify the underlying IOMMU
driver that the device's internal state has been sanitized.

Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 include/linux/iommu.h |  4 ++++
 drivers/iommu/iommu.c | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d3685967e960a..3c5c5fa5cdc6a 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -626,6 +626,9 @@ __iommu_copy_struct_to_user(const struct iommu_user_data *dst_data,
  * @release_device: Remove device from iommu driver handling
  * @probe_finalize: Do final setup work after the device is added to an IOMMU
  *                  group and attached to the groups domain
+ * @reset_device_done: Notify the driver that a device has reset successfully.
+ *                     Note that the core invokes the callback function while
+ *                     holding the group->mutex
  * @device_group: find iommu group for a particular device
  * @get_resv_regions: Request list of reserved regions for a device
  * @of_xlate: add OF master IDs to iommu grouping
@@ -683,6 +686,7 @@ struct iommu_ops {
 	struct iommu_device *(*probe_device)(struct device *dev);
 	void (*release_device)(struct device *dev);
 	void (*probe_finalize)(struct device *dev);
+	void (*reset_device_done)(struct device *dev);
 	struct iommu_group *(*device_group)(struct device *dev);
 
 	/* Request/Free a list of reserved regions for a device */
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 28d4c1f143a08..df23ef0a26e6c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -4071,12 +4071,14 @@ EXPORT_SYMBOL_GPL(pci_dev_reset_iommu_prepare);
 void pci_dev_reset_iommu_done(struct pci_dev *pdev, bool reset_succeeds)
 {
 	struct iommu_group *group = pdev->dev.iommu_group;
+	const struct iommu_ops *ops;
 	struct group_device *gdev;
 	unsigned long pasid;
 	void *entry;
 
 	if (!pci_ats_supported(pdev) || !dev_has_iommu(&pdev->dev))
 		return;
+	ops = dev_iommu_ops(&pdev->dev);
 
 	guard(mutex)(&group->mutex);
 
@@ -4105,6 +4107,16 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev, bool reset_succeeds)
 		return;
 	}
 
+	/*
+	 * A PCI device might have been in an error state, so the IOMMU driver
+	 * had to quarantine the device by disabling specific hardware features
+	 * or dropping translation capability. Here notify the IOMMU driver as
+	 * a reliable signal that the faulty PCI device has been cleanly reset
+	 * so now it can lift its quarantine and restore full functionality.
+	 */
+	if (ops->reset_device_done)
+		ops->reset_device_done(&pdev->dev);
+
 	/* Re-attach RID domain back to group->domain */
 	if (group->domain != group->blocking_domain) {
 		WARN_ON(__iommu_attach_device(group->domain, &pdev->dev,
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 01/11] PCI: Propagate FLR return values to callers
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <cover.1776381841.git.nicolinc@nvidia.com>

A reset failure implies that the device might be unreliable. E.g. its ATC
might still retain stale entries. Thus, the IOMMU layer cannot trust this
device to resume its ATS function that can lead to memory corruption. So,
the pci_dev_reset_iommu_done() won't recover the device's IOMMU pathway if
the device reset fails.

Those functions in the pci_dev_reset_methods array invoke pcie_flr(), but
do not check the return value. Propagate them correctly.

Given that these functions have been running okay, and the return values
will be only needed for an incoming work. This is not treated as bug fix.

Suggested-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
 drivers/pci/quirks.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 48946cca4be72..05ce12b6b2f76 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3957,7 +3957,7 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, bool probe)
 	 * supported.
 	 */
 	if (!probe)
-		pcie_flr(dev);
+		return pcie_flr(dev);
 	return 0;
 }
 
@@ -4015,6 +4015,7 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, bool probe)
 {
 	u16 old_command;
 	u16 msix_flags;
+	int ret;
 
 	/*
 	 * If this isn't a Chelsio T4-based device, return -ENOTTY indicating
@@ -4060,7 +4061,7 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, bool probe)
 				      PCI_MSIX_FLAGS_ENABLE |
 				      PCI_MSIX_FLAGS_MASKALL);
 
-	pcie_flr(dev);
+	ret = pcie_flr(dev);
 
 	/*
 	 * Restore the configuration information (BAR values, etc.) including
@@ -4069,7 +4070,7 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, bool probe)
 	 */
 	pci_restore_state(dev);
 	pci_write_config_word(dev, PCI_COMMAND, old_command);
-	return 0;
+	return ret;
 }
 
 #define PCI_DEVICE_ID_INTEL_82599_SFP_VF   0x10ed
@@ -4152,9 +4153,7 @@ static int nvme_disable_and_flr(struct pci_dev *dev, bool probe)
 
 	pci_iounmap(dev, bar);
 
-	pcie_flr(dev);
-
-	return 0;
+	return pcie_flr(dev);
 }
 
 /*
@@ -4166,14 +4165,16 @@ static int nvme_disable_and_flr(struct pci_dev *dev, bool probe)
  */
 static int delay_250ms_after_flr(struct pci_dev *dev, bool probe)
 {
+	int ret;
+
 	if (probe)
 		return pcie_reset_flr(dev, PCI_RESET_PROBE);
 
-	pcie_reset_flr(dev, PCI_RESET_DO_RESET);
+	ret = pcie_reset_flr(dev, PCI_RESET_DO_RESET);
 
 	msleep(250);
 
-	return 0;
+	return ret;
 }
 
 #define PCI_DEVICE_ID_HINIC_VF      0x375E
@@ -4189,6 +4190,7 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe)
 	unsigned long timeout;
 	void __iomem *bar;
 	u32 val;
+	int ret;
 
 	if (probe)
 		return 0;
@@ -4209,7 +4211,7 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe)
 	val = val | HINIC_VF_FLR_PROC_BIT;
 	iowrite32be(val, bar + HINIC_VF_OP);
 
-	pcie_flr(pdev);
+	ret = pcie_flr(pdev);
 
 	/*
 	 * The device must recapture its Bus and Device Numbers after FLR
@@ -4236,7 +4238,7 @@ static int reset_hinic_vf_dev(struct pci_dev *pdev, bool probe)
 reset_complete:
 	pci_iounmap(pdev, bar);
 
-	return 0;
+	return ret;
 }
 
 static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
-- 
2.43.0



^ permalink raw reply related

* [PATCH v3 00/11] iommu/arm-smmu-v3: Quarantine device upon ATC invalidation timeout
From: Nicolin Chen @ 2026-04-16 23:28 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
	Jason Gunthorpe
  Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
	Lu Baolu, Kevin Tian, linux-arm-kernel, iommu, linux-kernel,
	linux-acpi, linux-pci, vsethi, Shuai Xue

Hi all,

This series addresses a critical vulnerability and stability issue where an
unresponsive PCIe device failing to process ATC (Address Translation Cache)
invalidation requests leads to silent data corruption and continuous SMMU
CMDQ error spam.

[ As Jason pointed out, because this series fundamentally introduces a new
  RAS feature to quarantine and recover from hardware faults and relies on
  a recently accepted SMMU driver rework, it is not treated as a standard
  bug fix. Thus, none of the patches here carries a "Fixes" tag. ]

Currently, when an ATC invalidation times out, the SMMUv3 driver skips the
CMDQ_ERR_CERROR_ATC_INV_IDX error. This leaves the device's ATS cache state
desynchronized from the SMMU: the device cache may retain stale ATC entries
for memory pages that the OS has already reclaimed and reassigned, creating
a direct vector for data corruption. Furthermore, the driver might continue
issuing ATC_INV commands, resulting in constant CMDQ errors:
    unexpected global error reported (0x00000001), this could be serious
    CMDQ error (cons 0x0302bb84): ATC invalidate timeout
    unexpected global error reported (0x00000001), this could be serious
    CMDQ error (cons 0x0302bb88): ATC invalidate timeout
    unexpected global error reported (0x00000001), this could be serious
    CMDQ error (cons 0x0302bb8c): ATC invalidate timeout
    ...

To resolve this, introduce a mechanism to quarantine a broken device in the
SMMUv3 driver and the IOMMU core. To achieve this, add preparatory changes:
 - Tighten the semantics of pci_dev_reset_iommu_done() that is now strictly
   called only upon a successful hardware reset
 - Introduce a reset_device_done op, allowing the core to signal the driver
   when the physical hardware has been cleanly recovered (e.g., via AER or
   a manual reset) so the quarantine can be lifted
 - Utilize a per-group_device WQ via an iommu_report_device_broken() helper

On the SMMUv3 driver side, retry the timedout ATC_INV batch to identify the
faulty device(s) via an atc_sync_timeouts tracker. Perform a surgical STE
update and flag the ATS as broken to reject further ATS/ATC requests at the
hardware level and suppress further timeout spam.

This is on Github:
https://github.com/nicolinc/iommufd/commits/smmuv3_atc_timeout-v3

Note that patches are rebased on bug-fix under review:
https://lore.kernel.org/all/20260407194644.171304-1-nicolinc@nvidia.com/

Changelog
v3:
 * Rebase on arm/smmu/updates branch + bug fix
 * Update commit messages and inline comments
 * [iommu] Drop unnecessary ops validation
 * [iommu] Add missed function stub when !CONFIG_IOMMU_API
 * [iommu] Change iommu_report_device_broken() to per gdev
 * [iommu] Separate quarantine from pci_dev_reset_prepare()
 * [iommu] Check reset failure in pci_dev_reset_iommu_done()
 * [smmuv3] Fix STE update with try_cmpxchg64()
 * [smmuv3] Fix "continue" bug when skipping ATC commands
 * [smmuv3] Replace atomic_t prod_err with a lockless bitmap
 * [smmuv3] Drop master->invs_domain; disable ATS per-master directly
 * [smmuv3] Return -EIO for ATC timeout v.s. -ETIMEDOUT for poll timeout
 * [smmuv3] Replace INV_TYPE_ATS_DISABLED with per-master ats_broken flag
v2:
 https://lore.kernel.org/all/cover.1773774441.git.nicolinc@nvidia.com/
 * Rebase on arm_smmu_invs-v13 series [0]
 * Bisect batched atc invalidation commands
 * Drop the direct pci_reset_function() call
 * Move the work queue from SMMUv3 to the core
 * Proceed a surgical STE update to disable EATS
 * Wait for pci_dev_reset_iommu_done() to signal a recovery
v1:
 https://lore.kernel.org/all/cover.1772686998.git.nicolinc@nvidia.com/

[0] https://lore.kernel.org/all/cover.1773733797.git.nicolinc@nvidia.com/

Thanks
Nicolin

Nicolin Chen (11):
  PCI: Propagate FLR return values to callers
  iommu: Pass in reset result to pci_dev_reset_iommu_done()
  iommu: Add reset_device_done callback for hardware fault recovery
  iommu: Add __iommu_group_block_device helper
  iommu: Change group->devices to RCU-protected list
  iommu: Defer __iommu_group_free_device() to be outside group->mutex
  iommu: Add iommu_report_device_broken() to quarantine a broken device
  iommu/arm-smmu-v3: Mark ATC invalidate timeouts via lockless bitmap
  iommu/arm-smmu-v3: Replace smmu with master in arm_smmu_inv
  iommu/arm-smmu-v3: Introduce master->ats_broken flag
  iommu/arm-smmu-v3: Block ATS upon an ATC invalidation timeout

 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |   4 +-
 include/linux/iommu.h                         |  15 +-
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c  |  34 ++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 193 +++++++++++-
 drivers/iommu/iommu.c                         | 284 ++++++++++++++----
 drivers/pci/pci-acpi.c                        |   2 +-
 drivers/pci/pci.c                             |  10 +-
 drivers/pci/quirks.c                          |  24 +-
 8 files changed, 454 insertions(+), 112 deletions(-)

-- 
2.43.0



^ permalink raw reply

* Re: [PATCH v2] gpu: ipu-v3: clean up kernel-doc warnings
From: Randy Dunlap @ 2026-04-16 22:44 UTC (permalink / raw)
  To: dri-devel
  Cc: Philipp Zabel, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, imx,
	linux-arm-kernel, Helge Deller, linux-fbdev
In-Reply-To: <20260219215211.459108-1-rdunlap@infradead.org>

ping.

On 2/19/26 1:52 PM, Randy Dunlap wrote:
> Correct all kernel-doc warnings:
> - fix a typedef kernel-doc comment
> - mark a list_head as private
> - use Returns: for function return values
> 
> Warning: include/video/imx-ipu-image-convert.h:31 struct member 'list' not
>  described in 'ipu_image_convert_run'
> Warning: include/video/imx-ipu-image-convert.h:40 function parameter
>  'ipu_image_convert_cb_t' not described in 'void'
> Warning: include/video/imx-ipu-image-convert.h:40 expecting prototype for
>  ipu_image_convert_cb_t(). Prototype was for void() instead
> Warning: include/video/imx-ipu-image-convert.h:66 No description found for
>  return value of 'ipu_image_convert_verify'
> Warning: include/video/imx-ipu-image-convert.h:90 No description found for
>  return value of 'ipu_image_convert_prepare'
> Warning: include/video/imx-ipu-image-convert.h:125 No description found for
>  return value of 'ipu_image_convert_queue'
> Warning: include/video/imx-ipu-image-convert.h:163 No description found for
>  return value of 'ipu_image_convert'
> 
> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
> ---
> v2: add Reviewed-by, update Cc: list, rebase, resend
> 
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Cc: Maxime Ripard <mripard@kernel.org>
> Cc: Thomas Zimmermann <tzimmermann@suse.de>
> Cc: David Airlie <airlied@gmail.com>
> Cc: Simona Vetter <simona@ffwll.ch>
> Cc: imx@lists.linux.dev
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Helge Deller <deller@gmx.de>
> Cc: linux-fbdev@vger.kernel.org
> 
>  include/video/imx-ipu-image-convert.h |   16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> --- linux-next-20260218.orig/include/video/imx-ipu-image-convert.h
> +++ linux-next-20260218/include/video/imx-ipu-image-convert.h
> @@ -27,12 +27,13 @@ struct ipu_image_convert_run {
>  
>  	int status;
>  
> +	/* private: */
>  	/* internal to image converter, callers don't touch */
>  	struct list_head list;
>  };
>  
>  /**
> - * ipu_image_convert_cb_t - conversion callback function prototype
> + * typedef ipu_image_convert_cb_t - conversion callback function prototype
>   *
>   * @run:	the completed conversion run pointer
>   * @ctx:	a private context pointer for the callback
> @@ -60,7 +61,7 @@ void ipu_image_convert_adjust(struct ipu
>   * @out:	output image format
>   * @rot_mode:	rotation mode
>   *
> - * Returns 0 if the formats and rotation mode meet IPU restrictions,
> + * Returns: 0 if the formats and rotation mode meet IPU restrictions,
>   * -EINVAL otherwise.
>   */
>  int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
> @@ -77,11 +78,11 @@ int ipu_image_convert_verify(struct ipu_
>   * @complete:	run completion callback
>   * @complete_context:	a context pointer for the completion callback
>   *
> - * Returns an opaque conversion context pointer on success, error pointer
> + * In V4L2, drivers should call ipu_image_convert_prepare() at streamon.
> + *
> + * Returns: an opaque conversion context pointer on success, error pointer
>   * on failure. The input/output formats and rotation mode must already meet
>   * IPU retrictions.
> - *
> - * In V4L2, drivers should call ipu_image_convert_prepare() at streamon.
>   */
>  struct ipu_image_convert_ctx *
>  ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
> @@ -122,6 +123,8 @@ void ipu_image_convert_unprepare(struct
>   * In V4L2, drivers should call ipu_image_convert_queue() while
>   * streaming to queue the conversion of a received input buffer.
>   * For example mem2mem devices this would be called in .device_run.
> + *
> + * Returns: 0 on success or -errno on error.
>   */
>  int ipu_image_convert_queue(struct ipu_image_convert_run *run);
>  
> @@ -155,6 +158,9 @@ void ipu_image_convert_abort(struct ipu_
>   * On successful return the caller can queue more run requests if needed, using
>   * the prepared context in run->ctx. The caller is responsible for unpreparing
>   * the context when no more conversion requests are needed.
> + *
> + * Returns: pointer to the created &struct ipu_image_convert_run that has
> + * been queued on success; an ERR_PTR(errno) on error.
>   */
>  struct ipu_image_convert_run *
>  ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,

-- 
~Randy



^ permalink raw reply

* [PATCH v2] spi: s3c64xx: fix all kernel-doc warnings
From: Randy Dunlap @ 2026-04-16 22:40 UTC (permalink / raw)
  To: linux-kernel
  Cc: Randy Dunlap, Krzysztof Kozlowski, Andi Shyti, Tudor Ambarus,
	linux-spi, linux-samsung-soc, linux-arm-kernel

Add kernel-doc for one struct member and use the correct function name
to eliminate kernel-doc warnings:

Warning: include/linux/platform_data/spi-s3c64xx.h:40 struct member
 'polling' not described in 's3c64xx_spi_info'
Warning: include/linux/platform_data/spi-s3c64xx.h:51 expecting prototype
 for s3c64xx_spi_set_platdata(). Prototype was for
 s3c64xx_spi0_set_platdata() instead

Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
v2: add tag; rebase & resend

Cc: Andi Shyti <andi.shyti@kernel.org>
Cc: Tudor Ambarus <tudor.ambarus@linaro.org>
Cc: linux-spi@vger.kernel.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org

 include/linux/platform_data/spi-s3c64xx.h |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- linux-next-20260415.orig/include/linux/platform_data/spi-s3c64xx.h
+++ linux-next-20260415/include/linux/platform_data/spi-s3c64xx.h
@@ -30,6 +30,7 @@ struct s3c64xx_spi_csinfo {
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
  * @num_cs: Number of CS this controller emulates.
  * @no_cs: Used when CS line is not connected.
+ * @polling: Using polling mode when %true (no 'dmas' property in devicetree)
  * @cfg_gpio: Configure pins for this SPI controller.
  */
 struct s3c64xx_spi_info {
@@ -41,7 +42,7 @@ struct s3c64xx_spi_info {
 };
 
 /**
- * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
+ * s3c64xx_spi0_set_platdata - SPI Controller configure callback by the board
  *				initialization code.
  * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
  * @num_cs: Number of elements in the 'cs' array.


^ permalink raw reply

* [GIT PULL 4/4] soc: ARM code changes for 7.1
From: Arnd Bergmann @ 2026-04-16 22:31 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: soc, linux-kernel, linux-arm-kernel
In-Reply-To: <c595dc8e-6367-4922-98ed-90bdd4c3c24f@app.fastmail.com>

The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:

  Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-arm-7.1

for you to fetch changes up to 3ef628c3f37f1dcef0da51e73ad6e458ec74bddb:

  Merge tag 'microchip-soc-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/arm (2026-04-04 17:34:56 +0200)

----------------------------------------------------------------
soc: ARM code changes for 7.1

These are again very minimal updates:

 - A workaround for firmware on Google Nexus 10
 - A fix for early debugging on OMAP1
 - A rework for Microchip SoC configuration
 - Cleanups on OMAP2 an R-Car-Gen2

----------------------------------------------------------------
Aaro Koskinen (1):
      ARM: OMAP1: Fix DEBUG_LL and earlyprintk on OMAP16XX

Alexandre Marquet (1):
      ARM: samsung: exynos5250: Allow CPU1 to boot

Arnd Bergmann (3):
      Merge tag 'samsung-soc-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/arm
      Merge tag 'renesas-arm-soc-for-v7.1-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/arm
      Merge tag 'omap-for-v7.1/soc-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap into soc/arm

Bartosz Golaszewski (1):
      arm64: Kconfig: provide a top-level switch for Microchip platforms

Geert Uytterhoeven (1):
      ARM: shmobile: rcar-gen2: Use of_phandle_args_equal() helper

Julian Braha (1):
      ARM: omap2: dead code cleanup in kconfig for ARCH_OMAP4

Krzysztof Kozlowski (1):
      Merge tag 'microchip-soc-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/arm

Randy Dunlap (1):
      ARM: omap: fix all kernel-doc warnings

Thorsten Blum (1):
      ARM: omap2: Replace scnprintf with strscpy in omap3_cpuinfo

 arch/arm/mach-exynos/firmware.c                    |  4 ++--
 arch/arm/mach-omap1/clock_data.c                   |  4 ++--
 arch/arm/mach-omap2/Kconfig                        |  1 -
 arch/arm/mach-omap2/id.c                           |  3 ++-
 arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c | 16 ++++------------
 arch/arm64/Kconfig.platforms                       | 10 ++++------
 arch/arm64/configs/defconfig                       |  1 +
 include/linux/platform_data/voltage-omap.h         |  4 ++--
 8 files changed, 17 insertions(+), 26 deletions(-)


^ permalink raw reply

* [GIT PULL 3/4] soc: defconfig updates for 7.1
From: Arnd Bergmann @ 2026-04-16 22:30 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: soc, linux-kernel, linux-arm-kernel
In-Reply-To: <c595dc8e-6367-4922-98ed-90bdd4c3c24f@app.fastmail.com>

The following changes since commit 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f:

  Linux 7.0-rc1 (2026-02-22 13:18:59 -0800)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-defconfig-7.1

for you to fetch changes up to 07e1a498ee9a9e715208c06b39edd8f7d22f3b50:

  Merge tag 'at91-defconfig-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/defconfig (2026-04-04 17:24:37 +0200)

----------------------------------------------------------------
soc: defconfig updates for 7.1

As usual, we enable a number of additional device drivers as loadable
modules, to support the added platforms. The largest change this time
is for OMAP2/3, which were not that well supported in the generic arm32
defconfig.

The Tegra SoC platforms are now enabled by default in Kconfig when
ARCH_TEGRA is enabled, which means the defconfig change is done at
the same time as the Kconfig change here.

----------------------------------------------------------------
Abel Vesa (1):
      arm64: defconfig: Enable Qualcomm Eliza basic resource providers

Ajay Kumar Nandam (1):
      arm64: defconfig: Enable Qualcomm WCD937x headphone codec as module

Andreas Kemnade (1):
      arm: multi_v7_defconfig: Enable more OMAP 3/4 related configs

Arnd Bergmann (5):
      Merge tag 'qcom-arm64-defconfig-for-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/defconfig
      Merge tag 'ti-k3-config-for-v7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux into soc/defconfig
      Merge tag 'omap-for-v7.1/defconfig-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap into soc/defconfig
      Merge tag 'tegra-for-7.1-arm-defconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/defconfig
      Merge tag 'tegra-for-7.1-arm64-defconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/defconfig

Aubin Constans (1):
      ARM: configs: at91: sama7: enable LVDS serializer support

Francesco Dolcini (1):
      arm64: defconfig: Enable configurations for Toradex Aquila AM69

Geert Uytterhoeven (1):
      ARM: shmobile: defconfig: Refresh for v7.0-rc1

Harshal Dev (1):
      arm64: defconfig: Enable QCOMTEE module for QTEE-enabled Qualcomm SoCs

Kathiravan Thirumoorthy (1):
      arm64: defconfig: enable IPQ5210 RDP504 base configs

Kory Maincent (TI) (1):
      ARM: multi_v7_defconfig: omap2plus_defconfig: Enable ITE IT66121 driver

Krzysztof Kozlowski (6):
      Merge tag 'renesas-arm-defconfig-for-v7.1-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/defconfig
      arm64: defconfig: Enable Qualcomm Eliza SoC display clock controller
      soc/tegra: Make ARCH_TEGRA_SOC_FOO defaults for NVIDIA Tegra
      ARM: tegra: defconfig: Drop redundant ARCH_TEGRA_foo_SOC
      arm64: tegra: defconfig: Drop redundant ARCH_TEGRA_foo_SOC
      Merge tag 'at91-defconfig-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/defconfig

Luca Weiss (2):
      arm64: defconfig: Enable S5KJN1 camera sensor
      arm64: defconfig: Enable Milos LPASS LPI pinctrl driver

Meghana Malladi (1):
      arm64: defconfig: Enable DP83TG720 PHY driver

Michael Walle (1):
      arm64: defconfig: remove SENSORS_SA67MCU

Neil Armstrong (1):
      arm64: defconfig: enable pci-pwrctrl-generic as module

Pankaj Patil (1):
      arm64: defconfig: Enable configs for Qualcomm Glymur SoC

Romain Sioen (1):
      ARM: configs: at91: sama7: enable config for atmel maxtouch

Ryan Wanner (1):
      ARM: configs: at91: sama7: enable DRM hlcdc support

Srinivas Kandagatla (1):
      arm64: defconfig: Enable configs for Arduino VENTUNO Q

Taniya Das (2):
      arm64: defconfig: Enable SM8750 clock controllers
      arm64: defconfig: Enable Kaanapali clock controllers

Thierry Reding (2):
      Merge branch 'for-7.1/soc' into for-7.1/arm/defconfig
      Merge branch 'for-7.1/soc' into for-7.1/arm64/defconfig

Thomas Zimmermann (1):
      arch/arm: Drop CONFIG_FIRMWARE_EDID from defconfig files

Vishnu Saini (1):
      arm64: defconfig: Enable Lontium LT8713sx driver

 arch/arm/configs/davinci_all_defconfig |  1 -
 arch/arm/configs/multi_v7_defconfig    | 32 ++++++++++++++++++++++++----
 arch/arm/configs/omap1_defconfig       |  1 -
 arch/arm/configs/omap2plus_defconfig   |  2 +-
 arch/arm/configs/pxa_defconfig         |  1 -
 arch/arm/configs/sama7_defconfig       | 10 +++++++++
 arch/arm/configs/shmobile_defconfig    | 11 +++++-----
 arch/arm/configs/tegra_defconfig       |  4 ----
 arch/arm64/configs/defconfig           | 39 +++++++++++++++++++++++++++-------
 drivers/soc/tegra/Kconfig              | 11 ++++++++++
 10 files changed, 86 insertions(+), 26 deletions(-)


^ permalink raw reply

* Re: [GIT PULL 2/4] soc: drivers for 7.1
From: Arnd Bergmann @ 2026-04-16 22:28 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: soc, linux-kernel, linux-arm-kernel
In-Reply-To: <c595dc8e-6367-4922-98ed-90bdd4c3c24f@app.fastmail.com>

The following changes since commit a0e0c2f8c5f32b675f58e25a9338283cedb5ad2b:

  reset: spacemit: k3: Decouple composite reset lines (2026-03-23 12:25:47 +0100)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git tags/soc-drivers-7.1

for you to fetch changes up to 33a20cdaf41d08a66581cc01a60c1a3d596ba9cd:

  Merge tag 'ffa-fix-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers (2026-04-11 10:48:50 +0200)

----------------------------------------------------------------
soc: drivers for 7.1

The driver updates again are all over the place with many minor fixes
going into platform specific code. The most notable changes are:

 - Support for Microchip pic64gx system controllers
 - Work on cleaning up devicetree bindings for SoC drivers, and
   converting them into the new format
 - Lots of smaller changes for Qualcomm SoC drivers, including support
   for a number of newly supported chips
 - reset controller API cleanups and a new driver for Cix Sky1
 - Reworks of the Tegra PMC and CBB drivers, along with a change
   to how individual Tegra SoCs get selected in Kconfig and
   BPMP firmware driver updates including a refresh of the ABI
   header to match the version used by firmware
 - STM32 updates to the firewall bus driver and support for
   the debug bus through OP-TEE
 - SCMI firmware driver improvements for reliability, in particular
   for dealing with broken firmware interrupts
 - Memory driver updates for Tegra, and a patch to remove the
   unused Baikal T1 driver

----------------------------------------------------------------
Abel Vesa (3):
      soc: qcom: socinfo: Add PM7550BA PMIC
      dt-bindings: firmware: qcom,scm: document Eliza SCM Firmware Interface
      soc: qcom: pd-mapper: Add support for Eliza

Aelin Reidel (2):
      dt-bindings: arm: qcom,ids: Add SoC IDs for SM7450 and SM7450P
      soc: qcom: socinfo: Add SoC IDs for SM7450 and SM7450P

Akhila YS (5):
      dt-bindings: arm: microchip,sama7g5-chipid : convert to DT schema
      dt-bindings: arm: atmel,at91sam9260-pit: convert to DT schema
      dt-bindings: arm: microchip,sam9x60-pit64b : convert to DT schema
      dt-bindings: arm: atmel,at91rm9200-st: convert to DT schema
      dt-bindings: arm: atmel,at91rm9200-sdramc: convert to DT schema

Alexander Stein (2):
      dt-bindings: arm: fsl: add bindings for TQMa8x
      MAINTAINERS: Add i.MX team to all arm NXP platforms

Alok Tiwari (2):
      soc: qcom: llcc: fix v1 SB syndrome register offset
      soc: qcom: aoss: compare against normalized cooling state

Andrew Davis (6):
      reset: ath79: Use devm_register_restart_handler()
      reset: intel: Use devm_register_restart_handler()
      reset: lpc18xx: Use devm_register_sys_off_handler()
      reset: ma35d1: Use devm_register_sys_off_handler()
      reset: npcm: Use devm_register_sys_off_handler()
      reset: sunplus: Use devm_register_sys_off_handler()

André Draszik (1):
      dt-bindings: firmware: google,gs101-acpm-ipc: add S2MPG11 secondary PMIC

Andy Shevchenko (2):
      memory: bt1-l2-ctl: Remove not-going-to-be-supported code for Baikal SoC
      dt-bindings: cache: bt1-l2-ctl: Remove unused bindings

Anjelique Melendez (3):
      dt-bindings: soc: qcom: qcom,pmic-glink: Add Glymur and Kaanapali compatibles
      soc: qcom: pmic_glink: Add charger PDR service information to client data
      soc: qcom: pmic_glink: Add support for Glymur and Kaanapali

Arnd Bergmann (14):
      Merge tag 'samsung-drivers-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into soc/drivers
      Merge tag 'memory-controller-drv-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers
      Merge tag 'scmi-updates-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers
      Merge tag 'stm32-bus-firewall-for-7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/atorgue/stm32 into soc/drivers
      Merge tag 'hisi-drivers-for-7.1' of https://github.com/hisilicon/linux-hisi into soc/drivers
      Merge tag 'tee-for-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into soc/drivers
      Merge tag 'optee-for-v7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jenswi/linux-tee into soc/drivers
      Merge tag 'renesas-drivers-for-v7.1-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/drivers
      Merge tag 'imx-soc-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux into soc/drivers
      Merge tag 'tegra-for-7.1-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/drivers
      Merge tag 'tegra-for-7.1-firmware' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/drivers
      Merge tag 'imx-bindings-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/frank.li/linux into soc/drivers
      Merge tag 'reset-for-v7.1' of https://git.pengutronix.de/git/pza/linux into soc/drivers
      Merge tag 'qcom-drivers-for-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

Bartosz Golaszewski (15):
      reset: gpio: remove unneeded OF-node put
      reset: gpio: add a devlink between reset-gpio and its consumer
      reset: gpio: simplify fallback device matching
      reset: gpio: remove unneeded auxiliary_set_drvdata()
      reset: warn on reset-gpio release
      reset: fold ida_alloc() into reset_create_gpio_aux_device()
      reset: use lock guards in reset core
      reset: handle removing supplier before consumers
      reset: protect struct reset_controller_dev with its own mutex
      reset: protect struct reset_control with its own mutex
      reset: convert of_reset_control_get_count() to using firmware nodes
      reset: convert the core API to using firmware nodes
      reset: convert reset core to using firmware nodes
      reset: gpio: make the driver fwnode-agnostic
      reset: don't overwrite fwnode_reset_n_cells

Biju Das (3):
      dt-bindings: soc: renesas: Document RZ/G3L SoC variants, SMARC SoM and Carrier-II EVK
      dt-bindings: soc: renesas: renesas,rzg2l-sysc: Document RZ/G3L SoC
      soc: renesas: rz-sysc: Add SoC identification for RZ/G3L SoC

Bjorn Andersson (3):
      Merge branch '20260309230346.3584252-2-daniel.lezcano@oss.qualcomm.com' into drivers-for-7.1
      Merge branch '20260125-iris-ubwc-v4-1-1ff30644ac81@oss.qualcomm.com' into drivers-for-7.1
      firmware: qcom: scm: Allow QSEECOM on Lenovo IdeaCentre Mini X

Chris Lew (2):
      soc: qcom: smp2p: Add irqchip state support
      soc: qcom: smp2p: Add support for smp2p v2

Ciprian Marian Costea (2):
      dt-bindings: interrupt-controller: fsl,irqsteer: add S32N79 support
      dt-bindings: arm: fsl: Add NXP S32N79 SoC and RDB board

Claudiu Beznea (1):
      reset: core: Drop unnecessary double quote

Clément Le Goffic (1):
      bus: firewall: move stm32_firewall header file in include folder

Conor Dooley (4):
      dt-bindings: soc: microchip: add compatible for the mss-top-sysreg on pic64gx
      gpio: mpfs: Add interrupt support
      dt-bindings: soc: microchip: document PolarFire SoC's gpio interrupt mux
      soc: microchip: add mpfs gpio interrupt mux driver

Daniel Lezcano (3):
      soc: qcom: qmi: Enumerate the service IDs of QMI
      soc: qcom: pdr: Use the unified QMI service ID instead of defining it locally
      samples: qmi: Use the unified QMI service ID instead of defining it locally

Dmitry Baryshkov (6):
      soc: qcom: ubwc: disable bank swizzling for Glymur platform
      soc: qcom: ocmem: make the core clock optional
      soc: qcom: ocmem: register reasons for probe deferrals
      soc: qcom: ocmem: return -EPROBE_DEFER is ocmem is not available
      soc: qcom: ubwc: add helper to get min_acc length
      soc: qcom: ubwc: add helpers to get programmable values

Ernest Van Hoecke (1):
      dt-bindings: arm: fsl: add Verdin iMX95

Florian Fainelli (1):
      memory: brcmstb_memc: Expand LPDDR4 check to cover for LPDDR5

Frank Li (1):
      dt-bindings: arm: lpc: add missed lpc43xx board

Gary Yang (2):
      dt-bindings: soc: cix: document the syscon on Sky1 SoC
      reset: add Sky1 soc reset support

Gatien Chevallier (8):
      bus: rifsc: fix RIF configuration check for peripherals
      dt-bindings: document access-controllers property for coresight peripherals
      dt-bindings: pinctrl: document access-controllers property for stm32 HDP
      dt-bindings: bus: document the stm32 debug bus
      bus: stm32_firewall: allow check on different firewall controllers
      bus: stm32_firewall: add stm32_firewall_get_grant_all_access() API
      drivers: bus: add the stm32 debug bus driver
      pinctrl: stm32: add firewall checks before probing the HDP driver

Geert Uytterhoeven (1):
      firmware: arm_scmi: Support loop control in quirk code snippets

Gopikrishna Garmidi (2):
      soc: qcom: ubwc: Add support for Mahua
      firmware: qcom: scm: Allow QSEECOM on Mahua CRD

Haoxiang Li (1):
      clk: spear: fix resource leak in clk_register_vco_pll()

Hrishabh Rajput (1):
      firmware: qcom: scm: Register gunyah watchdog device

Huisong Li (2):
      soc: hisilicon: kunpeng_hccs: Fix discard ‘const’ qualifier compiling warning
      soc: hisilicon: kunpeng_hccs: Remove unused input parameter

Jens Glathe (1):
      firmware: qcom: scm: allow QSEECOM on ASUS Vivobook X1P42100 variant

Jon Hunter (10):
      soc/tegra: pmc: Add kerneldoc for reboot notifier
      soc/tegra: pmc: Correct function names in kerneldoc
      soc/tegra: pmc: Add kerneldoc for wake-up variables
      soc/tegra: pmc: Remove unused AOWAKE definitions
      soc/tegra: pmc: Add support for SoC specific AOWAKE offsets
      soc/tegra: pmc: Add AOWAKE regs for Tegra264
      soc/tegra: pmc: Add Tegra264 wake events
      soc/tegra: pmc: Refactor IO pad voltage control
      soc/tegra: pmc: Rename has_impl_33v_pwr flag
      soc/tegra: pmc: Add IO pads for Tegra264

Josua Mayer (1):
      dt-bindings: arm: fsl: Add various solidrun i.MX8M boards

Kathiravan Thirumoorthy (4):
      dt-bindings: arm: qcom,ids: add SOC IDs for IPQ5210 family
      soc: qcom: socinfo: add SoC ID for IPQ5210 family
      dt-bindings: firmware: qcom,scm: Document ipq5210 SCM
      dt-bindings: firmware: qcom,scm: Document ipq9650 SCM

Ketan Patil (6):
      memory: tegra: Group error handling related registers
      memory: tegra: Group register and fields
      memory: tegra: Add support for multiple IRQs
      memory: tegra: Group SoC specific fields
      memory: tegra: Prepare for supporting multiple intmask registers
      memory: tegra: Add MC error logging support for Tegra264

Krzysztof Kozlowski (24):
      firmware: exynos-acpm: Use unsigned int for acpm_pmic_linux_errmap index
      firmware: exynos-acpm: Count number of commands in acpm_xfer
      firmware: exynos-acpm: Count acpm_xfer buffers with __counted_by_ptr
      firmware: exynos-acpm: Drop fake 'const' on handle pointer
      dt-bindings: arm: qcom,ids: Add SoC ID for CQ7790
      soc: qcom: socinfo: Add SoC ID for CQ7790
      memory: renesas-rpc-if: Simplify printing PTR_ERR with dev_err_probe
      memory: tegra-mc: Drop tegra_mc_setup_latency_allowance() return value
      memory: tegra-mc: Simplify printing PTR_ERR with dev_err_probe
      memory: tegra-mc: Use %pe format
      Merge tag 'renesas-drivers-for-v7.1-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/drivers
      Merge tag 'renesas-dt-bindings-for-v7.1-tag1' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel into soc/drivers
      firmware: qcom: uefisecapp: Simplify mutex with guard
      firmware: qcom: uefisecapp: Annotate acquiring locks for context tracking
      firmware: qcom: scom: Simplify mutex with guard
      soc/tegra: Make ARCH_TEGRA_SOC_FOO defaults for NVIDIA Tegra
      bus: stm32_firewall: Simplify with scoped for each OF child loop
      soc: qcom: ubwc: Remove redundant x1e80100_data
      soc: qcom: ubwc: Add configuration Eliza SoC
      Merge tag 'tegra-for-7.1-dt-bindings' of https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into soc/drivers
      Merge tag 'at91-soc-7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/at91/linux into soc/drivers
      Merge tag 'riscv-soc-drivers-for-v7.1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/conor/linux into soc/drivers
      Merge tag 'qcom-drivers-for-7.1-2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers
      Merge tag 'ffa-fix-7.1' of https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into soc/drivers

Lad Prabhakar (3):
      soc: renesas: r9a09g057-sys: Mark rzv2h_sys_init_data as __initconst
      soc: renesas: r9a09g047-sys: Mark rzg3e_sys_init_data as __initconst
      soc: renesas: r9a09g056-sys: Mark rzv2n_sys_init_data as __initconst

Le Qi (1):
      soc: qcom: pd-mapper: Add QCS615 power domain mappings

Lei wang (2):
      dt-bindings: arm: qcom,ids: Add SoC ID for SA8650P
      soc: qcom: socinfo: Add SoC ID for SA8650P

Liu Ying (1):
      dt-bindings: soc: imx93-media-blk-ctrl: Add PDFC subnode to schema and example

Luca Weiss (1):
      soc: qcom: pd-mapper: Add Milos compatible

Marek Vasut (2):
      dt-bindings: firmware: arm,scmi: Document arm,no-completion-irq property
      firmware: arm_scmi: Implement arm,no-completion-irq property

Markus Niebel (1):
      dt-bindings: arm: add bindings for TQMa95xxLA

Martin Schmiedel (1):
      dt-bindings: arm: fsl: add MBa93xxLA-MINI

Maud Spierings (1):
      dt-bindings: arm: fsl: Add GOcontroll Moduline IV/Mini

Mikko Perttunen (2):
      memory: tegra124-emc: Fix dll_change check
      memory: tegra30-emc: Fix dll_change check

Mukesh Ojha (1):
      firmware: qcom_scm: don't opencode kmemdup

Pankaj Patil (1):
      firmware: qcom: scm: Allow QSEECOM on Glymur CRD

Peng Fan (2):
      firmware: arm_scmi: Use round_up() for base protocol list size calculation
      dt-bindings: fsl: imx7ulp-smc1: Add #clock-cells property

Philipp Zabel (2):
      reset: core: Fix indentation
      Merge tag 'reset-fixes-for-v7.0-2' into reset/next

Pierre-Henry Moussay (2):
      dt-bindings: soc: microchip: mpfs-sys-controller: Add pic64gx compatibility
      soc: microchip: mpfs-sys-controller: add support for pic64gx

Randy Dunlap (1):
      tee: clean up tee_core.h kernel-doc

Richard Acayan (2):
      dt-bindings: cache: qcom,llcc: Add SDM670 compatible
      soc: qcom: llcc: Add configuration data for SDM670

Rosen Penev (2):
      reset: sti: kzalloc + kcalloc to kzalloc
      soc: qcom: wcnss: simplify allocation of req

Rouven Czerwinski (1):
      optee: simplify OP-TEE context match

Sebastian Ene (1):
      firmware: arm_ffa: Use the correct buffer size during RXTX_MAP

Shengjiu Wang (2):
      bus: imx-aipstz: set default value for opacr registers
      dt-bindings: arm: fsl: Add compatible for i.MX8MP audio board (version 2)

Sherry Sun (1):
      dt-bindings: arm: fsl: Add i.MX93 Wireless EVK board

Srinivas Kandagatla (1):
      soc: qcom: pd-mapper: Add support for Glymur and Mahua

Stefano Radaelli (2):
      dt-bindings: arm: fsl: add Variscite DART-MX95 Boards
      dt-bindings: arm: fsl: add Variscite DART-MX91 Boards

Sumit Gupta (5):
      soc/tegra: cbb: Add support for CBB fabrics in Tegra238
      soc/tegra: cbb: Set ERD on resume for err interrupt
      soc/tegra: cbb: Fix incorrect ARRAY_SIZE in fabric lookup tables
      soc/tegra: cbb: Fix cross-fabric target timeout lookup
      dt-bindings: arm: tegra: Add Tegra238 CBB compatible strings

Svyatoslav Ryhel (3):
      dt-bindings: display: tegra: Document Tegra20 HDMI port
      soc/tegra: pmc: Enable core domain support for Tegra114
      soc/tegra: common: Add Tegra114 support to devm_tegra_core_dev_init_opp_table

Thierry Reding (16):
      memory: tegra: Add support for DBB clock on Tegra264
      firmware: tegra: bpmp: Rename Tegra239 to Tegra238
      soc/tegra: Add Tegra238 Kconfig symbol
      soc/tegra: Update BPMP ABI header
      firmware: tegra: bpmp: Add tegra_bpmp_get_with_id() function
      dt-bindings: pci: Document the NVIDIA Tegra264 PCIe controller
      dt-bindings: phy: tegra-xusb: Document Type C support
      dt-bindings: clock: tegra124-dfll: Convert to json-schema
      dt-bindings: interrupt-controller: tegra: Fix reg entries
      dt-bindings: arm: tegra: Add missing compatible strings
      dt-bindings: phy: tegra: Document Tegra210 USB PHY
      dt-bindings: memory: Add Tegra210 memory controller bindings
      dt-bindings: memory: tegra210: Mark EMC as cooling device
      soc/tegra: bpmp: Use ENODEV instead of ENOTSUPP
      dt-bindings: arm: tegra: Document Jetson AGX Thor DevKit
      MAINTAINERS: Change email address for Thierry Reding

Thorsten Blum (1):
      bus: rifsc: Replace snprintf("%s") with strscpy

Tommaso Merciai (5):
      reset: rzv2h-usb2phy: Keep PHY clock enabled for entire device lifetime
      dt-bindings: reset: renesas,rzv2h-usb2phy: Add '#mux-state-cells' property
      dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/G3E USB2PHY reset
      reset: rzv2h-usb2phy: Convert to regmap API
      reset: rzv2h-usb2phy: Add support for VBUS mux controller registration

Unnathi Chalicheemala (2):
      soc: qcom: llcc: Add per-slice counter and common llcc slice descriptor
      soc: qcom: llcc: Use guards for mutex handling

Val Packett (1):
      firmware: qcom: scm: Allow QSEECOM on ECS LIVA QC710

Vladimir Zapolskiy (1):
      soc: qcom: pd-mapper: Simplify code using of_root to get root device tree node

Yanan Yang (1):
      dt-bindings: arm: fsl: Add FRDM-IMX91S board

Yijie Yang (1):
      firmware: qcom: scm: Allow QSEECOM on PURWA-IOT-EVK

 .../devicetree/bindings/arm/arm,coresight-cti.yaml |    3 +
 .../bindings/arm/arm,coresight-dynamic-funnel.yaml |    3 +
 .../devicetree/bindings/arm/arm,coresight-etm.yaml |    3 +
 .../devicetree/bindings/arm/arm,coresight-stm.yaml |    3 +
 .../devicetree/bindings/arm/arm,coresight-tmc.yaml |    3 +
 .../bindings/arm/arm,coresight-tpiu.yaml           |    3 +
 .../bindings/arm/atmel,at91rm9200-sdramc.yaml      |   66 +
 .../bindings/arm/atmel,at91rm9200-st.yaml          |   69 +
 .../bindings/arm/atmel,at91sam9260-pit.yaml        |   49 +
 .../devicetree/bindings/arm/atmel-sysregs.txt      |   48 -
 .../bindings/arm/freescale/fsl,imx7ulp-pm.yaml     |    5 +
 Documentation/devicetree/bindings/arm/fsl.yaml     |   86 +
 .../bindings/arm/microchip,sam9x60-pit64b.yaml     |   68 +
 .../bindings/arm/microchip,sama7g5-chipid.yaml     |   41 +
 .../devicetree/bindings/arm/nxp/lpc32xx.yaml       |   22 +
 Documentation/devicetree/bindings/arm/tegra.yaml   |   56 +-
 .../bindings/arm/tegra/nvidia,tegra234-cbb.yaml    |    4 +
 .../bindings/bus/st,stm32mp131-dbg-bus.yaml        |   76 +
 .../bindings/cache/baikal,bt1-l2-ctl.yaml          |   63 -
 .../devicetree/bindings/cache/qcom,llcc.yaml       |    2 +
 .../bindings/clock/nvidia,tegra124-dfll.txt        |  155 -
 .../bindings/clock/nvidia,tegra124-dfll.yaml       |  290 ++
 .../display/tegra/nvidia,tegra20-hdmi.yaml         |   13 +-
 .../devicetree/bindings/firmware/arm,scmi.yaml     |   10 +
 .../bindings/firmware/google,gs101-acpm-ipc.yaml   |   50 +-
 .../devicetree/bindings/firmware/qcom,scm.yaml     |    4 +
 .../interrupt-controller/fsl,irqsteer.yaml         |    4 +-
 .../interrupt-controller/nvidia,tegra20-ictlr.yaml |   23 +-
 .../memory-controllers/nvidia,tegra210-emc.yaml    |    6 +-
 .../memory-controllers/nvidia,tegra210-mc.yaml     |   77 +
 .../bindings/pci/nvidia,tegra264-pcie.yaml         |  149 +
 .../bindings/phy/nvidia,tegra194-xusb-padctl.yaml  |   39 +-
 .../bindings/phy/nvidia,tegra20-usb-phy.yaml       |    1 +
 .../devicetree/bindings/pinctrl/st,stm32-hdp.yaml  |    6 +
 .../reset/renesas,rzv2h-usb2phy-reset.yaml         |    9 +-
 .../bindings/soc/cix/cix,sky1-system-control.yaml  |   42 +
 .../bindings/soc/imx/fsl,imx93-media-blk-ctrl.yaml |   78 +
 .../soc/microchip/microchip,mpfs-irqmux.yaml       |  103 +
 .../microchip/microchip,mpfs-mss-top-sysreg.yaml   |   18 +-
 .../microchip/microchip,mpfs-sys-controller.yaml   |    4 +-
 .../bindings/soc/qcom/qcom,pmic-glink.yaml         |    2 +
 .../bindings/soc/renesas/renesas,rzg2l-sysc.yaml   |    1 +
 .../devicetree/bindings/soc/renesas/renesas.yaml   |   13 +
 Documentation/driver-api/reset.rst                 |    1 -
 MAINTAINERS                                        |   20 +-
 drivers/bus/Kconfig                                |   10 +
 drivers/bus/Makefile                               |    1 +
 drivers/bus/imx-aipstz.c                           |   15 +
 drivers/bus/stm32_dbg_bus.c                        |  250 ++
 drivers/bus/stm32_etzpc.c                          |    3 +-
 drivers/bus/stm32_firewall.c                       |   59 +-
 drivers/bus/stm32_rifsc.c                          |   61 +-
 drivers/clk/samsung/clk-acpm.c                     |    4 +-
 drivers/clk/spear/clk-vco-pll.c                    |    4 +-
 drivers/firmware/arm_ffa/driver.c                  |    2 +-
 drivers/firmware/arm_scmi/base.c                   |    4 +-
 drivers/firmware/arm_scmi/common.h                 |    4 +
 drivers/firmware/arm_scmi/driver.c                 |    4 +
 drivers/firmware/arm_scmi/quirks.h                 |    8 +-
 drivers/firmware/qcom/qcom_qseecom_uefisecapp.c    |    9 +-
 drivers/firmware/qcom/qcom_scm.c                   |   71 +-
 drivers/firmware/samsung/exynos-acpm-dvfs.c        |   13 +-
 drivers/firmware/samsung/exynos-acpm-dvfs.h        |    4 +-
 drivers/firmware/samsung/exynos-acpm-pmic.c        |   26 +-
 drivers/firmware/samsung/exynos-acpm-pmic.h        |   10 +-
 drivers/firmware/samsung/exynos-acpm.c             |   30 +-
 drivers/firmware/samsung/exynos-acpm.h             |   10 +-
 drivers/firmware/tegra/bpmp.c                      |   34 +
 drivers/gpio/Kconfig                               |    1 +
 drivers/gpio/gpio-mpfs.c                           |  122 +-
 drivers/memory/Kconfig                             |   11 -
 drivers/memory/Makefile                            |    1 -
 drivers/memory/brcmstb_memc.c                      |    8 +-
 drivers/memory/bt1-l2-ctl.c                        |  323 --
 drivers/memory/renesas-rpc-if.c                    |    8 +-
 drivers/memory/tegra/mc.c                          |  135 +-
 drivers/memory/tegra/mc.h                          |  153 +-
 drivers/memory/tegra/tegra114.c                    |   18 +-
 drivers/memory/tegra/tegra124-emc.c                |    2 +-
 drivers/memory/tegra/tegra124.c                    |   40 +-
 drivers/memory/tegra/tegra186-emc.c                |    8 +
 drivers/memory/tegra/tegra186.c                    |   22 +-
 drivers/memory/tegra/tegra194.c                    |   22 +-
 drivers/memory/tegra/tegra20.c                     |   31 +-
 drivers/memory/tegra/tegra210.c                    |   21 +-
 drivers/memory/tegra/tegra234.c                    |   22 +-
 drivers/memory/tegra/tegra264.c                    |  420 +-
 drivers/memory/tegra/tegra30-emc.c                 |    6 +-
 drivers/memory/tegra/tegra30.c                     |   18 +-
 drivers/mfd/sec-acpm.c                             |   10 +-
 drivers/pinctrl/stm32/pinctrl-stm32-hdp.c          |   14 +
 drivers/reset/Kconfig                              |    9 +
 drivers/reset/Makefile                             |    1 +
 drivers/reset/core.c                               |  505 ++-
 drivers/reset/reset-ath79.c                        |   12 +-
 drivers/reset/reset-gpio.c                         |   27 +-
 drivers/reset/reset-intel-gw.c                     |   11 +-
 drivers/reset/reset-lpc18xx.c                      |   12 +-
 drivers/reset/reset-ma35d1.c                       |   11 +-
 drivers/reset/reset-npcm.c                         |   12 +-
 drivers/reset/reset-rzv2h-usb2phy.c                |  197 +-
 drivers/reset/reset-sky1.c                         |  367 ++
 drivers/reset/reset-sunplus.c                      |   12 +-
 drivers/reset/sti/reset-syscfg.c                   |    9 +-
 drivers/soc/hisilicon/kunpeng_hccs.c               |    7 +-
 drivers/soc/microchip/Kconfig                      |   11 +
 drivers/soc/microchip/Makefile                     |    1 +
 drivers/soc/microchip/mpfs-irqmux.c                |  181 +
 drivers/soc/microchip/mpfs-sys-controller.c        |   74 +-
 drivers/soc/qcom/llcc-qcom.c                       |  188 +-
 drivers/soc/qcom/ocmem.c                           |   17 +-
 drivers/soc/qcom/pdr_interface.c                   |    4 +-
 drivers/soc/qcom/pdr_internal.h                    |    3 -
 drivers/soc/qcom/pmic_glink.c                      |   66 +-
 drivers/soc/qcom/qcom_aoss.c                       |    2 +-
 drivers/soc/qcom/qcom_pd_mapper.c                  |   33 +-
 drivers/soc/qcom/smp2p.c                           |  103 +-
 drivers/soc/qcom/socinfo.c                         |   11 +
 drivers/soc/qcom/ubwc_config.c                     |   31 +-
 drivers/soc/qcom/wcnss_ctrl.c                      |   17 +-
 drivers/soc/renesas/Kconfig                        |   12 +
 drivers/soc/renesas/Makefile                       |    1 +
 drivers/soc/renesas/r9a08g046-sysc.c               |   91 +
 drivers/soc/renesas/r9a09g047-sys.c                |    2 +-
 drivers/soc/renesas/r9a09g056-sys.c                |    2 +-
 drivers/soc/renesas/r9a09g057-sys.c                |    2 +-
 drivers/soc/renesas/rz-sysc.c                      |    3 +
 drivers/soc/renesas/rz-sysc.h                      |    1 +
 drivers/soc/tegra/Kconfig                          |   20 +
 drivers/soc/tegra/cbb/tegra234-cbb.c               |  169 +-
 drivers/soc/tegra/common.c                         |    5 +-
 drivers/soc/tegra/pmc.c                            |  664 +--
 drivers/tee/optee/device.c                         |    5 +-
 include/dt-bindings/arm/qcom,ids.h                 |   10 +
 .../dt-bindings/reset/cix,sky1-s5-system-control.h |  163 +
 .../dt-bindings/reset/cix,sky1-system-control.h    |   41 +
 {drivers => include/linux}/bus/stm32_firewall.h    |    0
 include/linux/bus/stm32_firewall_device.h          |   26 +
 .../linux/firmware/samsung/exynos-acpm-protocol.h  |   40 +-
 include/linux/reset-controller.h                   |   21 +-
 include/linux/reset.h                              |   43 +-
 include/linux/soc/qcom/llcc-qcom.h                 |    8 +-
 include/linux/soc/qcom/qmi.h                       |   12 +
 include/linux/soc/qcom/ubwc.h                      |   25 +
 include/linux/tee_core.h                           |   30 +-
 include/soc/tegra/bpmp-abi.h                       | 4605 ++++++++++++++++----
 include/soc/tegra/bpmp.h                           |   20 +-
 include/soc/tegra/mc.h                             |   40 +-
 samples/qmi/qmi_sample_client.c                    |    2 +-
 149 files changed, 9188 insertions(+), 2652 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91rm9200-sdramc.yaml
 create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91rm9200-st.yaml
 create mode 100644 Documentation/devicetree/bindings/arm/atmel,at91sam9260-pit.yaml
 delete mode 100644 Documentation/devicetree/bindings/arm/atmel-sysregs.txt
 create mode 100644 Documentation/devicetree/bindings/arm/microchip,sam9x60-pit64b.yaml
 create mode 100644 Documentation/devicetree/bindings/arm/microchip,sama7g5-chipid.yaml
 create mode 100644 Documentation/devicetree/bindings/bus/st,stm32mp131-dbg-bus.yaml
 delete mode 100644 Documentation/devicetree/bindings/cache/baikal,bt1-l2-ctl.yaml
 delete mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
 create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.yaml
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/nvidia,tegra210-mc.yaml
 create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra264-pcie.yaml
 create mode 100644 Documentation/devicetree/bindings/soc/cix/cix,sky1-system-control.yaml
 create mode 100644 Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-irqmux.yaml
 create mode 100644 drivers/bus/stm32_dbg_bus.c
 delete mode 100644 drivers/memory/bt1-l2-ctl.c
 create mode 100644 drivers/reset/reset-sky1.c
 create mode 100644 drivers/soc/microchip/mpfs-irqmux.c
 create mode 100644 drivers/soc/renesas/r9a08g046-sysc.c
 create mode 100644 include/dt-bindings/reset/cix,sky1-s5-system-control.h
 create mode 100644 include/dt-bindings/reset/cix,sky1-system-control.h
 rename {drivers => include/linux}/bus/stm32_firewall.h (100%)


^ permalink raw reply

* Re: [PATCH v2 2/4] KVM: arm64: sefltests: Add helpers for guest hypervisors
From: Wei-Lin Chang @ 2026-04-16 22:15 UTC (permalink / raw)
  To: Itaru Kitayama
  Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
	Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Catalin Marinas, Will Deacon, Paolo Bonzini,
	Shuah Khan
In-Reply-To: <ad68VjnGQ3trs7AN@sm-arm-grace07>

On Wed, Apr 15, 2026 at 07:14:46AM +0900, Itaru Kitayama wrote:
> On Sun, Apr 12, 2026 at 03:22:14PM +0100, Wei-Lin Chang wrote:
> > Add helpers so that guest hypervisors can run nested guests. SP_EL1
> > save/restore is added to allow nested guests to use a stack.
> > 
> > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > ---
> >  .../selftests/kvm/include/arm64/nested.h      | 17 +++++++
> >  tools/testing/selftests/kvm/lib/arm64/entry.S |  5 ++
> >  .../testing/selftests/kvm/lib/arm64/nested.c  | 46 +++++++++++++++++++
> >  3 files changed, 68 insertions(+)
> > 
> > diff --git a/tools/testing/selftests/kvm/include/arm64/nested.h b/tools/testing/selftests/kvm/include/arm64/nested.h
> > index 86d931facacb..7928ef89494a 100644
> > --- a/tools/testing/selftests/kvm/include/arm64/nested.h
> > +++ b/tools/testing/selftests/kvm/include/arm64/nested.h
> > @@ -21,8 +21,17 @@
> >  
> >  extern char hyp_vectors[];
> >  
> > +enum vcpu_sysreg {
> > +	__INVALID_SYSREG__,   /* 0 is reserved as an invalid value */
> > +
> > +	SP_EL1,
> > +
> > +	NR_SYS_REGS
> > +};
> > +
> >  struct cpu_context {
> >  	struct user_pt_regs regs;	/* sp = sp_el0 */
> > +	u64 sys_regs[NR_SYS_REGS];
> >  };
> >  
> >  struct vcpu {
> > @@ -37,9 +46,17 @@ struct hyp_data {
> >  	struct cpu_context hyp_context;
> >  };
> 
> I am not sure of these structs you introduced only for nested guest feature
> testing, as the KVM arm64 code they are quite complex and involved, 
> extracring part of those and add members as hello_nested or simliar
> tests evolve, then add test cases to me seems fragile. 
> But if you have strong reason to add these would you mind explaining a bit?

Sorry, I don't quite get all of your points. I understand your argument
being evolving these structs as time goes is fragile. For this didn't
KVM itself evolve like this?

As for having these structs, how can we make L1 a small hypervisor
without them?

Thanks,
Wei-Lin Chang

> 
> Thanks,
> Itaru.
> 
> >  
> > +void prepare_hyp(void);
> > +void init_vcpu(struct vcpu *vcpu, vm_paddr_t l2_pc, vm_paddr_t l2_stack_top);
> > +int run_l2(struct vcpu *vcpu, struct hyp_data *hyp_data);
> > +
> > +void do_hvc(void);
> >  u64 __guest_enter(struct vcpu *vcpu, struct cpu_context *hyp_context);
> >  void __hyp_exception(u64 type);
> >  
> > +void __sysreg_save_el1_state(struct cpu_context *ctxt);
> > +void __sysreg_restore_el1_state(struct cpu_context *ctxt);
> > +
> >  #endif /* !__ASSEMBLER__ */
> >  
> >  #endif /* SELFTEST_KVM_NESTED_H */
> > diff --git a/tools/testing/selftests/kvm/lib/arm64/entry.S b/tools/testing/selftests/kvm/lib/arm64/entry.S
> > index 33bedf5e7fb2..df3af3463c6c 100644
> > --- a/tools/testing/selftests/kvm/lib/arm64/entry.S
> > +++ b/tools/testing/selftests/kvm/lib/arm64/entry.S
> > @@ -3,6 +3,11 @@
> >   * adapted from arch/arm64/kvm/hyp/entry.S
> >   */
> >  
> > + .globl do_hvc
> > + do_hvc:
> > +	hvc	#0
> > +	ret
> > +
> >  /*
> >   * Manually define these for now
> >   */
> > diff --git a/tools/testing/selftests/kvm/lib/arm64/nested.c b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > index 06ddaab2436f..b30d20b101c4 100644
> > --- a/tools/testing/selftests/kvm/lib/arm64/nested.c
> > +++ b/tools/testing/selftests/kvm/lib/arm64/nested.c
> > @@ -4,7 +4,53 @@
> >   */
> >  
> >  #include "nested.h"
> > +#include "processor.h"
> >  #include "test_util.h"
> > +#include <asm/sysreg.h>
> > +
> > +void prepare_hyp(void)
> > +{
> > +	write_sysreg(HCR_EL2_E2H | HCR_EL2_RW, hcr_el2);
> > +	write_sysreg(hyp_vectors, vbar_el2);
> > +	isb();
> > +}
> > +
> > +void init_vcpu(struct vcpu *vcpu, vm_paddr_t l2_pc, vm_paddr_t l2_stack_top)
> > +{
> > +	memset(vcpu, 0, sizeof(*vcpu));
> > +	vcpu->context.regs.pc = l2_pc;
> > +	vcpu->context.regs.pstate = PSR_MODE_EL1h | PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT;
> > +	vcpu->context.sys_regs[SP_EL1] = l2_stack_top;
> > +}
> > +
> > +void __sysreg_save_el1_state(struct cpu_context *ctxt)
> > +{
> > +	ctxt->sys_regs[SP_EL1] = read_sysreg(sp_el1);
> > +}
> > +
> > +void __sysreg_restore_el1_state(struct cpu_context *ctxt)
> > +{
> > +	write_sysreg(ctxt->sys_regs[SP_EL1], sp_el1);
> > +}
> > +
> > +int run_l2(struct vcpu *vcpu, struct hyp_data *hyp_data)
> > +{
> > +	u64 ret;
> > +
> > +	__sysreg_restore_el1_state(&vcpu->context);
> > +
> > +	write_sysreg(vcpu->context.regs.pstate, spsr_el2);
> > +	write_sysreg(vcpu->context.regs.pc, elr_el2);
> > +
> > +	ret =  __guest_enter(vcpu, &hyp_data->hyp_context);
> > +
> > +	vcpu->context.regs.pc = read_sysreg(elr_el2);
> > +	vcpu->context.regs.pstate = read_sysreg(spsr_el2);
> > +
> > +	__sysreg_save_el1_state(&vcpu->context);
> > +
> > +	return ret;
> > +}
> >  
> >  void __hyp_exception(u64 type)
> >  {
> > -- 
> > 2.43.0
> > 


^ permalink raw reply

* [GIT PULL 0/4] soc branches for 7.1
From: Arnd Bergmann @ 2026-04-16 22:14 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: soc, linux-kernel, linux-arm-kernel

This is another larger set of changes from the soc tree after a rather
quiet 7.0 merge window. In total, we merged 88 branches with over
1000 non-merge changesets, in large parts due to massive devicetree
updates on both Qualcomm and NXP platforms. These include a total of
12 new SoCs, all of them part of an already supported chip family.

The most active contributors by number of patches were

     43 Krzysztof Kozlowski
     27 Frank Li
     26 Dmitry Baryshkov
     25 Alexander Stein
     23 Marek Vasut
     20 Thierry Reding
     18 Josua Mayer
     17 Stefano Radaelli
     17 Sherry Sun
     17 Fabio Estevam
     17 Bartosz Golaszewski
     17 Abel Vesa
     16 Luca Weiss
     16 Barnabás Czémán
     14 Konrad Dybcio
     13 Lad Prabhakar
     13 Gatien Chevallier
     12 Francesco Dolcini
     11 Svyatoslav Ryhel
     11 Rosen Penev
     11 Jon Hunter
     11 Christophe Parant

and this is the corresponding dirstat:

   0.8% Documentation/devicetree/bindings/arm/
   0.9% Documentation/devicetree/bindings/clock/
   0.3% Documentation/devicetree/bindings/soc/
   0.7% Documentation/devicetree/bindings/
   0.2% arch/arm/boot/dts/aspeed/
   0.3% arch/arm/boot/dts/broadcom/
   0.4% arch/arm/boot/dts/nvidia/
   2.7% arch/arm/boot/dts/nxp/imx/
   0.9% arch/arm/boot/dts/qcom/
   0.2% arch/arm/boot/dts/renesas/
   1.0% arch/arm/boot/dts/rockchip/
   0.4% arch/arm/boot/dts/samsung/
   2.1% arch/arm/boot/dts/st/
   1.1% arch/arm/boot/dts/ti/omap/
   0.2% arch/arm/
   0.3% arch/arm64/boot/dts/allwinner/
   0.9% arch/arm64/boot/dts/arm/
   0.2% arch/arm64/boot/dts/broadcom/
   0.3% arch/arm64/boot/dts/exynos/axis/
   0.5% arch/arm64/boot/dts/exynos/google/
   1.0% arch/arm64/boot/dts/exynos/
  17.4% arch/arm64/boot/dts/freescale/
   1.1% arch/arm64/boot/dts/microchip/
   0.6% arch/arm64/boot/dts/nvidia/
  37.2% arch/arm64/boot/dts/qcom/
   1.4% arch/arm64/boot/dts/renesas/
   2.1% arch/arm64/boot/dts/rockchip/
   0.3% arch/arm64/boot/dts/st/
   3.3% arch/arm64/boot/dts/ti/
   0.4% arch/arm64/boot/dts/
   1.5% arch/riscv/boot/dts/microchip/
   0.8% arch/riscv/boot/dts/spacemit/
   0.4% drivers/bus/
   0.3% drivers/firmware/
   1.1% drivers/memory/tegra/
   0.3% drivers/memory/
   1.8% drivers/reset/
   0.2% drivers/soc/microchip/
   0.5% drivers/soc/qcom/
   0.2% drivers/soc/tegra/cbb/
   1.3% drivers/soc/tegra/
   0.3% drivers/
   1.4% include/dt-bindings/clock/
   0.5% include/dt-bindings/reset/
   0.3% include/linux/
   7.4% include/soc/tegra/
 977 files changed, 90981 insertions(+), 15252 deletions(-)



^ permalink raw reply

* Re: [PATCH v2 3/4] KVM: arm64: sefltests: Add basic NV selftest
From: Wei-Lin Chang @ 2026-04-16 21:58 UTC (permalink / raw)
  To: Itaru Kitayama
  Cc: linux-arm-kernel, kvmarm, kvm, linux-kselftest, linux-kernel,
	Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Catalin Marinas, Will Deacon, Paolo Bonzini,
	Shuah Khan
In-Reply-To: <ad66HasXI2AkEjgK@sm-arm-grace07>

On Wed, Apr 15, 2026 at 07:05:17AM +0900, Itaru Kitayama wrote:
> On Tue, Apr 14, 2026 at 11:16:47AM +0100, Wei-Lin Chang wrote:
> > On Tue, Apr 14, 2026 at 06:31:22AM +0900, Itaru Kitayama wrote:
> > > On Mon, Apr 13, 2026 at 10:18:42AM +0100, Wei-Lin Chang wrote:
> > > > Hi Itaru,
> > > > 
> > > > On Mon, Apr 13, 2026 at 08:19:25AM +0900, Itaru Kitayama wrote:
> > > > > On Sun, Apr 12, 2026 at 03:22:15PM +0100, Wei-Lin Chang wrote:
> > > > > > This selftest simply starts an L1, which starts its own guest (L2). L2
> > > > > > runs without stage-1 and 2 translations, it calls an HVC to jump back
> > > > > > to L1.
> > > > > 
> > > > > How do you disable both the nested guest (L2)'s MMU and stage 2
> > > > > translations?
> > > > 
> > > > Guest stage-2 is disabled by not setting HCR_EL2.VM in prepare_hyp(),
> > > > and stage-1 is disabled by not writing to SCTLR_EL12 in init_vcpu(),
> > > > effectively using the default value set by L0. However since SCTLR_EL1
> > > > has many architecturally UNKNOWN bits (including SCTLR_EL1.M), it should
> > > > be better to write a value before running L2 I suppose...
> > > 
> > > Thanks. What do you think of using copy_el2_to_el1() macro in at.c, so we
> > > can prepare in guest_code() to manipulate the SCTLR_EL12 System register 
> > > with the sensible programmed values?
> > 
> > Yes, using copy_el2_to_el1() can give us an L2 stage-1 that is identical
> > to the L1's stage-1. But what I was considering was if guest stage-2 is
> > enabled (which we plan to implement), then those stage-1 page tables
> > will have to be mapped for L2, and its base address translated to L2IPA.
> > It's doable but seems like extra complexity when stage-1 is not so
> > interesting for KVM (except for AT?), it lets the guest do whatever it
> > likes and let the hardware do the translation.
> > 
> > Let me know if you have reasons to want stage-1 for L2, there could be
> > something I should consider but did not.
> 
> By keeping nested guest's MMU enabled, we can exercise the shadow stage
> 2 on the host. But I am fine with you starting nested guest's IPA and I
> hope Marc and Oliver approve this seris and merge upstream.

I think you have guest stage-1 and guest stage-2 confused. Whether the
nested guest's stage-1 MMU is enabled or not does not affect what KVM is
doing with the shadow page tables. Stage-1 MMU translates L2VA -> L2IPA.
Shadow page tables store the combined translation of L2IPA -> L1IPA
(stage-2 PTs L1 built for L2) and L1IPA -> host PA (stage-2 PTs host
built for L1).

Additionally, stage-2 not enabled for L2 does not mean shadow stage-2 is
not exercised, there is still a distince shadow stage-2 for it doing the
work, albeit simple (the stored mapping is the same as the canonical
stage-2).

All in all, if we want to make the shadow page tables more interesting,
what we should do is build a stage-2 for L2, and enable it in L1, not
just turn on L2's stage-1 MMU.

Thanks,
Wei-Lin Chang

> 
> Thanks,
> Itaru.
> 
> > 
> > Thanks,
> > Wei-Lin Chang
> > 
> > > 
> > > Itaru.
> > > 
> > > > 
> > > > Thanks,
> > > > Wei-Lin Chang
> > > > 
> > > > > 
> > > > > Itaru.
> > > > > 
> > > > > > 
> > > > > > Signed-off-by: Wei-Lin Chang <weilin.chang@arm.com>
> > > > > > ---
> > > > > >  tools/testing/selftests/kvm/Makefile.kvm      |   1 +
> > > > > >  .../selftests/kvm/arm64/hello_nested.c        | 103 ++++++++++++++++++
> > > > > >  2 files changed, 104 insertions(+)
> > > > > >  create mode 100644 tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > > 
> > > > > > diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
> > > > > > index 3dc3e39f7025..e8c108e0c487 100644
> > > > > > --- a/tools/testing/selftests/kvm/Makefile.kvm
> > > > > > +++ b/tools/testing/selftests/kvm/Makefile.kvm
> > > > > > @@ -168,6 +168,7 @@ TEST_GEN_PROGS_arm64 += arm64/arch_timer_edge_cases
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/at
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/debug-exceptions
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/hello_el2
> > > > > > +TEST_GEN_PROGS_arm64 += arm64/hello_nested
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/host_sve
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/hypercalls
> > > > > >  TEST_GEN_PROGS_arm64 += arm64/external_aborts
> > > > > > diff --git a/tools/testing/selftests/kvm/arm64/hello_nested.c b/tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > > new file mode 100644
> > > > > > index 000000000000..97387e4697b3
> > > > > > --- /dev/null
> > > > > > +++ b/tools/testing/selftests/kvm/arm64/hello_nested.c
> > > > > > @@ -0,0 +1,103 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0-only
> > > > > > +/*
> > > > > > + * hello_nested - Go from vEL2 to EL1 then back
> > > > > > + */
> > > > > > +
> > > > > > +#include "nested.h"
> > > > > > +#include "processor.h"
> > > > > > +#include "test_util.h"
> > > > > > +#include "ucall.h"
> > > > > > +
> > > > > > +#define XLATE2GPA	(0xABCD)
> > > > > > +#define L2STACKSZ	(0x100)
> > > > > > +
> > > > > > +/*
> > > > > > + * TPIDR_EL2 is used to store vcpu id, so save and restore it.
> > > > > > + */
> > > > > > +static vm_paddr_t ucall_translate_to_gpa(void *gva)
> > > > > > +{
> > > > > > +	vm_paddr_t gpa;
> > > > > > +	u64 vcpu_id = read_sysreg(tpidr_el2);
> > > > > > +
> > > > > > +	GUEST_SYNC2(XLATE2GPA, gva);
> > > > > > +
> > > > > > +	/* get the result from userspace */
> > > > > > +	gpa = read_sysreg(tpidr_el2);
> > > > > > +
> > > > > > +	write_sysreg(vcpu_id, tpidr_el2);
> > > > > > +
> > > > > > +	return gpa;
> > > > > > +}
> > > > > > +
> > > > > > +static void l2_guest_code(void)
> > > > > > +{
> > > > > > +	do_hvc();
> > > > > > +}
> > > > > > +
> > > > > > +static void guest_code(void)
> > > > > > +{
> > > > > > +	struct vcpu vcpu;
> > > > > > +	struct hyp_data hyp_data;
> > > > > > +	int ret;
> > > > > > +	vm_paddr_t l2_pc, l2_stack_top;
> > > > > > +	/* force 16-byte alignment for the stack pointer */
> > > > > > +	u8 l2_stack[L2STACKSZ] __attribute__((aligned(16)));
> > > > > > +
> > > > > > +	GUEST_ASSERT_EQ(get_current_el(), 2);
> > > > > > +	GUEST_PRINTF("vEL2 entry\n");
> > > > > > +
> > > > > > +	l2_pc = ucall_translate_to_gpa(l2_guest_code);
> > > > > > +	l2_stack_top = ucall_translate_to_gpa(&l2_stack[L2STACKSZ]);
> > > > > > +
> > > > > > +	init_vcpu(&vcpu, l2_pc, l2_stack_top);
> > > > > > +	prepare_hyp();
> > > > > > +
> > > > > > +	ret = run_l2(&vcpu, &hyp_data);
> > > > > > +	GUEST_ASSERT_EQ(ret, ARM_EXCEPTION_TRAP);
> > > > > > +	GUEST_DONE();
> > > > > > +}
> > > > > > +
> > > > > > +int main(void)
> > > > > > +{
> > > > > > +	struct kvm_vcpu_init init;
> > > > > > +	struct kvm_vcpu *vcpu;
> > > > > > +	struct kvm_vm *vm;
> > > > > > +	struct ucall uc;
> > > > > > +	vm_paddr_t gpa;
> > > > > > +
> > > > > > +	TEST_REQUIRE(kvm_check_cap(KVM_CAP_ARM_EL2));
> > > > > > +	vm = vm_create(1);
> > > > > > +
> > > > > > +	kvm_get_default_vcpu_target(vm, &init);
> > > > > > +	init.features[0] |= BIT(KVM_ARM_VCPU_HAS_EL2);
> > > > > > +	vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
> > > > > > +	kvm_arch_vm_finalize_vcpus(vm);
> > > > > > +
> > > > > > +	while (true) {
> > > > > > +		vcpu_run(vcpu);
> > > > > > +
> > > > > > +		switch (get_ucall(vcpu, &uc)) {
> > > > > > +		case UCALL_SYNC:
> > > > > > +			if (uc.args[0] == XLATE2GPA) {
> > > > > > +				gpa = addr_gva2gpa(vm, (vm_vaddr_t)uc.args[1]);
> > > > > > +				vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TPIDR_EL2), gpa);
> > > > > > +			}
> > > > > > +			break;
> > > > > > +		case UCALL_PRINTF:
> > > > > > +			pr_info("%s", uc.buffer);
> > > > > > +			break;
> > > > > > +		case UCALL_DONE:
> > > > > > +			pr_info("DONE!\n");
> > > > > > +			goto end;
> > > > > > +		case UCALL_ABORT:
> > > > > > +			REPORT_GUEST_ASSERT(uc);
> > > > > > +			fallthrough;
> > > > > > +		default:
> > > > > > +			TEST_FAIL("Unhandled ucall: %ld\n", uc.cmd);
> > > > > > +		}
> > > > > > +	}
> > > > > > +
> > > > > > +end:
> > > > > > +	kvm_vm_free(vm);
> > > > > > +	return 0;
> > > > > > +}
> > > > > > -- 
> > > > > > 2.43.0
> > > > > > 


^ permalink raw reply

* Re: [PATCH v4 1/8] ARM: zte: Add zx297520v3 platform support
From: Randy Dunlap @ 2026-04-16 21:17 UTC (permalink / raw)
  To: Stefan Dösinger, Jonathan Corbet, Shuah Khan, Russell King,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial
In-Reply-To: <20260416-send-v4-1-e19d02b944ec@gmail.com>



On 4/16/26 1:19 PM, Stefan Dösinger wrote:
> diff --git a/arch/arm/mach-zte/Kconfig b/arch/arm/mach-zte/Kconfig
> new file mode 100644
> index 000000000000..24699256863b
> --- /dev/null
> +++ b/arch/arm/mach-zte/Kconfig
> @@ -0,0 +1,24 @@
> +# SPDX-License-Identifier: GPL-2.0
> +menuconfig ARCH_ZTE
> +	bool "ZTE zx family"
> +	depends on ARCH_MULTI_V7
> +	help
> +	  Support for ZTE zx-based family of processors.
> +
> +if ARCH_ZTE
> +
> +config SOC_ZX297520V3
> +	default y if ARCH_ZTE
> +	bool "ZX297520v3"
> +	select ARM_GIC_V3
> +	select ARM_AMBA
> +	select HAVE_ARM_ARCH_TIMER
> +	select PM_GENERIC_DOMAINS if PM
> +	help
> +	  Support for ZTE zx297520v3 SoC. It a single core SoC used in cheap LTE to WiFi routers.

	                                  It is

> +	  These devices can be Identified by the occurrence of the string "zx297520v3" in the boot

	                       identified

> +	  output and /proc/cpuinfo of their stock firmware.
> +
> +	  Please read Documentation/arch/arm/zte/zx297520v3.rst on how to boot the kernel.

-- 
~Randy



^ permalink raw reply

* Re: [PATCH V13 02/12] PCI: host-generic: Add common helpers for parsing Root Port properties
From: Bjorn Helgaas @ 2026-04-16 20:39 UTC (permalink / raw)
  To: Sherry Sun
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
	lpieralisi, kwilczynski, mani, bhelgaas, hongxing.zhu, l.stach,
	imx, linux-pci, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260416111422.183860-3-sherry.sun@nxp.com>

On Thu, Apr 16, 2026 at 07:14:12PM +0800, Sherry Sun wrote:
> Introduce generic helper functions to parse Root Port device tree nodes
> and extract common properties like reset GPIOs. This allows multiple
> PCI host controller drivers to share the same parsing logic.
> 
> Define struct pci_host_port to hold common Root Port properties
> (currently only reset GPIO descriptor) and add
> pci_host_common_parse_ports() to parse Root Port nodes from device tree.

Are the Root Port and the RC the only possible places for 'reset' GPIO
descriptions in DT?  I think PERST# routing is outside the PCIe spec,
so it seems like a system could provide a PERST# GPIO routed to any
Switch Upstream Port or Endpoint (I assume a PERST# connected to a
switch would apply to both the upstream port and the downstream
ports).


^ permalink raw reply

* [PATCH v4 8/8] ARM: defconfig: Add a zx29 defconfig file
From: Stefan Dösinger @ 2026-04-16 20:19 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial, Stefan Dösinger
In-Reply-To: <20260416-send-v4-0-e19d02b944ec@gmail.com>

This enables existing drivers that already are (UART) or will be (USB,
GPIO) necessary to operate this board even if they aren't declared in
the DTS yet.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
 arch/arm/configs/zx29_defconfig | 90 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/arch/arm/configs/zx29_defconfig b/arch/arm/configs/zx29_defconfig
new file mode 100644
index 000000000000..dae2d86c7583
--- /dev/null
+++ b/arch/arm/configs/zx29_defconfig
@@ -0,0 +1,90 @@
+CONFIG_SYSVIPC=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MMU=y
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_ZTE=y
+CONFIG_SOC_ZX297520V3=y
+# FIXME: There is no PSCI on this board, but ARM_GIC_V3 depends on it
+CONFIG_ARM_PSCI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CMDLINE="console=ttyAMA1 earlyprintk root=/dev/ram rw"
+# CONFIG_SUSPEND is not set
+CONFIG_BINFMT_FLAT=y
+# CONFIG_UEVENT_HELPER is not set
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y       # FIXME: This is specific to my initrd. Remove before upstream
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_HID is not set
+CONFIG_PINCTRL=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_PINMUX=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_POWER_RESET=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_LEDS_GPIO=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_MTD=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_SPI_MASTER=y
+CONFIG_MMC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_PLTFM=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+CONFIG_MDIO_BUS=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_SRAM=y
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PRINTK_TIME=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_ZTE_ZX=y
+CONFIG_DEBUG_LL_INCLUDE="debug/pl01x.S"
+CONFIG_DEBUG_UART_PL01X=y
+CONFIG_DEBUG_UART_PHYS=0x01408000
+CONFIG_DEBUG_UART_VIRT=0xf4708000

-- 
2.52.0



^ permalink raw reply related

* [PATCH v4 7/8] ARM: dts: Declare UART1 on zx297520v3 boards
From: Stefan Dösinger @ 2026-04-16 20:19 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial, Stefan Dösinger
In-Reply-To: <20260416-send-v4-0-e19d02b944ec@gmail.com>

This is the UART that sends Uboot messages and is accessible via pins on
the boards I have seen so far. UART0 and UART2 exist as well in the SoC
and can be used with the right pinmux settings on some boards. They will
be added later.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

---

The reason why I add the serial1=uart1 alias is to keep console=ttyAMA1
stable regardless of the other enabled UARTs. UART0, as the name
implies, has a lower MMIO address, but uart1 is the one that usually has
the boot output and console.
---
 arch/arm/boot/dts/zte/zx297520v3.dtsi | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
index ecd07f3fb8b3..09fbb1d052e3 100644
--- a/arch/arm/boot/dts/zte/zx297520v3.dtsi
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -6,6 +6,10 @@ / {
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	aliases {
+		serial1 = &uart1;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -57,5 +61,23 @@ timer {
 			 */
 			arm,cpu-registers-not-fw-configured;
 		};
+
+		/* The UART clock defaults to 26 mhz. It will be replaced when the zx29 clock
+		 * framework is added.
+		 */
+		uartclk: uartclk: clock-26000000 {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <26000000>;
+		};
+
+		uart1: serial@1408000 {
+			compatible = "arm,pl011", "arm,primecell";
+			arm,primecell-periphid = <0x001feffe>;
+			reg = <0x01408000 0x1000>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk>;
+			clock-names = "apb_pclk";
+		};
 	};
 };

-- 
2.52.0



^ permalink raw reply related

* [PATCH v4 6/8] ARM: zte: Bring back zx29 UART support
From: Stefan Dösinger @ 2026-04-16 20:19 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial, Stefan Dösinger
In-Reply-To: <20260416-send-v4-0-e19d02b944ec@gmail.com>

This is based on code removed in commit 89d4f98ae90d ("ARM: remove zte
zx platform"). I did not bring back the zx29-uart .compatible as the
arm,primecell-periphid does the job.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
 drivers/tty/serial/amba-pl011.c | 37 +++++++++++++++++++++++++++++++++++++
 include/linux/amba/bus.h        |  6 ++++++
 2 files changed, 43 insertions(+)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 7f17d288c807..858a0edd3e3b 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -216,6 +216,38 @@ static struct vendor_data vendor_st = {
 	.get_fifosize		= get_fifosize_st,
 };
 
+static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = {
+	[REG_DR] = ZX_UART011_DR,
+	[REG_FR] = ZX_UART011_FR,
+	[REG_LCRH_RX] = ZX_UART011_LCRH,
+	[REG_LCRH_TX] = ZX_UART011_LCRH,
+	[REG_IBRD] = ZX_UART011_IBRD,
+	[REG_FBRD] = ZX_UART011_FBRD,
+	[REG_CR] = ZX_UART011_CR,
+	[REG_IFLS] = ZX_UART011_IFLS,
+	[REG_IMSC] = ZX_UART011_IMSC,
+	[REG_RIS] = ZX_UART011_RIS,
+	[REG_MIS] = ZX_UART011_MIS,
+	[REG_ICR] = ZX_UART011_ICR,
+	[REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static unsigned int get_fifosize_zte(struct amba_device *dev)
+{
+	return 16;
+}
+
+static struct vendor_data vendor_zte = {
+	.reg_offset		= pl011_zte_offsets,
+	.access_32b		= true,
+	.ifls			= UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8,
+	.fr_busy		= ZX_UART01x_FR_BUSY,
+	.fr_dsr			= ZX_UART01x_FR_DSR,
+	.fr_cts			= ZX_UART01x_FR_CTS,
+	.fr_ri			= ZX_UART011_FR_RI,
+	.get_fifosize		= get_fifosize_zte,
+};
+
 /* Deals with DMA transactions */
 
 struct pl011_dmabuf {
@@ -3081,6 +3113,11 @@ static const struct amba_id pl011_ids[] = {
 		.mask	= 0x00ffffff,
 		.data	= &vendor_st,
 	},
+	{
+		.id	= AMBA_LINUX_ID(0x00, 0x1, 0xffe),
+		.mask	= 0x00ffffff,
+		.data	= &vendor_zte,
+	},
 	{ 0, 0 },
 };
 
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 9946276aff73..854c962d70f5 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -103,8 +103,14 @@ enum amba_vendor {
 	AMBA_VENDOR_ST = 0x80,
 	AMBA_VENDOR_QCOM = 0x51,
 	AMBA_VENDOR_LSI = 0xb6,
+	AMBA_VENDOR_LINUX = 0xfe,	/* This value is not official */
 };
 
+/* This is used to generate pseudo-ID for AMBA device */
+#define AMBA_LINUX_ID(conf, rev, part) \
+	(((conf) & 0xff) << 24 | ((rev) & 0xf) << 20 | \
+	AMBA_VENDOR_LINUX << 12 | ((part) & 0xfff))
+
 extern const struct bus_type amba_bustype;
 
 #define to_amba_device(d)	container_of_const(d, struct amba_device, dev)

-- 
2.52.0



^ permalink raw reply related

* [PATCH v4 5/8] ARM: dts: Add an armv7 timer for zx297520v3
From: Stefan Dösinger @ 2026-04-16 20:19 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial, Stefan Dösinger
In-Reply-To: <20260416-send-v4-0-e19d02b944ec@gmail.com>

The stock kernel does not use this timer, but it seems to work fine. The
board has other board-specific timers that would need a driver and I see
no reason to bother with them since the arm standard timer works.

The caveat is the non-standard GIC setup needed to handle the timer's
level-low PPI. This is the responsibility of the boot loader and
documented in Documentation/arch/arm/zte/zx297520v3.rst.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>
---
 arch/arm/boot/dts/zte/zx297520v3.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/zte/zx297520v3.dtsi b/arch/arm/boot/dts/zte/zx297520v3.dtsi
index d6c71d52b26c..ecd07f3fb8b3 100644
--- a/arch/arm/boot/dts/zte/zx297520v3.dtsi
+++ b/arch/arm/boot/dts/zte/zx297520v3.dtsi
@@ -24,6 +24,15 @@ soc {
 		interrupt-parent = <&gic>;
 		ranges;
 
+		/* The GIC has a non-standard way of configuring ints between level-low/level
+		 * high or rising edge/falling edge at 0xf2202070 and onwards. See AP_INT_MODE_BASE
+		 * and AP_PPI_MODE_REG in the ZTE kernel, although the offsets in the kernel source
+		 * seem wrong.
+		 *
+		 * Everything defaults to active-high/rising edge, but the timer is active-low. We
+		 * currently rely on the boot loader to change timer IRQs to active-low for us for
+		 * now.
+		 */
 		gic: interrupt-controller@f2000000 {
 			compatible = "arm,gic-v3";
 			interrupt-controller;
@@ -33,5 +42,20 @@ gic: interrupt-controller@f2000000 {
 			reg = <0xf2000000 0x10000>,
 			      <0xf2040000 0x20000>;
 		};
+
+		timer {
+			compatible = "arm,armv7-timer";
+			interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+				<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+				<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+				<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+			clock-frequency = <26000000>;
+			interrupt-parent = <&gic>;
+			/* I don't think uboot sets CNTVOFF and the stock kernel doesn't use the
+			 * arm timer at all. Since this is a single CPU system I don't think it
+			 * really matters that the offset is random though.
+			 */
+			arm,cpu-registers-not-fw-configured;
+		};
 	};
 };

-- 
2.52.0



^ permalink raw reply related

* [PATCH v4 4/8] ARM: zte: Add support for zx29 low level debug
From: Stefan Dösinger @ 2026-04-16 20:19 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Russell King, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Arnd Bergmann,
	Krzysztof Kozlowski, Alexandre Belloni, Linus Walleij,
	Drew Fustini, Greg Kroah-Hartman, Jiri Slaby
  Cc: linux-doc, linux-kernel, linux-arm-kernel, devicetree, soc,
	linux-serial, Stefan Dösinger
In-Reply-To: <20260416-send-v4-0-e19d02b944ec@gmail.com>

This is based on the removed zx29 code. A separate (more complicated)
patch will re-add the register map to the pl011 serial driver.

Signed-off-by: Stefan Dösinger <stefandoesinger@gmail.com>

---

I am unsure about the virtual address. It doesn't seem to matter, as
long as it is a valid address. This address is based on the old removed
code. Is there a rule-of-thumb physical to virtual mapping I can use to
give a sensible default value?
---
 arch/arm/Kconfig.debug         | 12 ++++++++++++
 arch/arm/include/debug/pl01x.S |  7 +++++++
 2 files changed, 19 insertions(+)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 366f162e147d..98d8a5a60048 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -1331,6 +1331,16 @@ choice
 		  This option selects UART0 on VIA/Wondermedia System-on-a-chip
 		  devices, including VT8500, WM8505, WM8650 and WM8850.
 
+	config DEBUG_ZTE_ZX
+		bool "Kernel low-level debugging via zx29 UART"
+		select DEBUG_UART_PL01X
+		depends on ARCH_ZTE
+		help
+		  Say Y here if you are enabling ZTE zx297520v3 SOC and need
+		  debug UART support. This UART is a PL011 with different
+		  register addresses. The UART for boot messages on zx29 boards
+		  is usually UART1 and is operating at 921600 8N1.
+
 	config DEBUG_ZYNQ_UART0
 		bool "Kernel low-level debugging on Xilinx Zynq using UART0"
 		depends on ARCH_ZYNQ
@@ -1545,6 +1555,7 @@ config DEBUG_UART_8250
 
 config DEBUG_UART_PHYS
 	hex "Physical base address of debug UART"
+	default 0x01408000 if DEBUG_ZTE_ZX
 	default 0x01c28000 if DEBUG_SUNXI_UART0
 	default 0x01c28400 if DEBUG_SUNXI_UART1
 	default 0x01d0c000 if DEBUG_DAVINCI_DA8XX_UART1
@@ -1701,6 +1712,7 @@ config DEBUG_UART_VIRT
 	default 0xf31004c0 if DEBUG_MESON_UARTAO
 	default 0xf4090000 if DEBUG_LPC32XX
 	default 0xf4200000 if DEBUG_GEMINI
+	default 0xf4708000 if DEBUG_ZTE_ZX
 	default 0xf6200000 if DEBUG_PXA_UART1
 	default 0xf7000000 if DEBUG_SUN9I_UART0
 	default 0xf7000000 if DEBUG_S3C64XX_UART && DEBUG_S3C_UART0
diff --git a/arch/arm/include/debug/pl01x.S b/arch/arm/include/debug/pl01x.S
index c7e02d0628bf..0c7bfa4c10db 100644
--- a/arch/arm/include/debug/pl01x.S
+++ b/arch/arm/include/debug/pl01x.S
@@ -8,6 +8,13 @@
 */
 #include <linux/amba/serial.h>
 
+#ifdef CONFIG_DEBUG_ZTE_ZX
+#undef UART01x_DR
+#undef UART01x_FR
+#define UART01x_DR     0x04
+#define UART01x_FR     0x14
+#endif
+
 #ifdef CONFIG_DEBUG_UART_PHYS
 		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =CONFIG_DEBUG_UART_PHYS

-- 
2.52.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox