Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b92c1db authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: add a function to get MID/PID/BID info"

parents 58b0fd18 fc09f706
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -276,4 +276,8 @@ enum arm_smmu_s2cr_privcfg {
#define ACTLR_QCOM_NSH_SHIFT		30
#define ACTLR_QCOM_NSH			1

#define FSYNR1_BID			GENMASK(15, 13)
#define FSYNR1_PID			GENMASK(12, 8)
#define FSYNR1_MID			GENMASK(7, 0)

#endif /* _ARM_SMMU_REGS_H */
+51 −2
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@
#include "iommu-logger.h"
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/bitfield.h>

/*
 * Apparently, some Qualcomm arm64 platforms which appear to expose their SMMU
@@ -156,7 +157,6 @@ struct arm_smmu_impl_def_reg {
	u32 value;
};


/*
 * attach_count
 *	The SMR and S2CR registers are only programmed when the number of
@@ -1981,6 +1981,46 @@ static phys_addr_t arm_smmu_verify_fault(struct iommu_domain *domain,
	return (phys_stimu == 0 ? phys_stimu_post_tlbiall : phys_stimu);
}

int iommu_get_fault_ids(struct iommu_domain *domain,
			struct iommu_fault_ids *f_ids)
{
	struct arm_smmu_domain *smmu_domain;
	struct arm_smmu_cfg *cfg;
	struct arm_smmu_device *smmu;
	void __iomem *cb_base;
	u32 fsr, fsynr1;
	int ret;

	if (!domain || !f_ids)
		return -EINVAL;

	smmu_domain = to_smmu_domain(domain);
	cfg = &smmu_domain->cfg;
	smmu = smmu_domain->smmu;

	ret = arm_smmu_power_on(smmu->pwr);
	if (ret)
		return ret;

	cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
	fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);

	if (!(fsr & FSR_FAULT)) {
		arm_smmu_power_off(smmu->pwr);
		return -EINVAL;
	}

	fsynr1 = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR1);
	arm_smmu_power_off(smmu->pwr);

	f_ids->bid = FIELD_GET(FSYNR1_BID, fsynr1);
	f_ids->pid = FIELD_GET(FSYNR1_PID, fsynr1);
	f_ids->mid = FIELD_GET(FSYNR1_MID, fsynr1);

	return 0;
}
EXPORT_SYMBOL(iommu_get_fault_ids);

static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
{
	int flags, ret, tmp;
@@ -2042,6 +2082,11 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
		dev_dbg(smmu->dev,
			"Context fault handled by client: iova=0x%08lx, cb=%d, fsr=0x%x, fsynr0=0x%x, fsynr1=0x%x\n",
			iova, cfg->cbndx, fsr, fsynr0, fsynr1);
		dev_dbg(smmu->dev,
			"Client info: BID=0x%x, PID=0x%x, MID=0x%x\n",
			FIELD_GET(FSYNR1_BID, fsynr1),
			FIELD_GET(FSYNR1_PID, fsynr1),
			FIELD_GET(FSYNR1_MID, fsynr1));
		dev_dbg(smmu->dev,
			"soft iova-to-phys=%pa\n", &phys_soft);
		ret = IRQ_HANDLED;
@@ -2056,7 +2101,11 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
			dev_err(smmu->dev,
				"Unhandled context fault: iova=0x%08lx, cb=%d, fsr=0x%x, fsynr0=0x%x, fsynr1=0x%x\n",
				iova, cfg->cbndx, fsr, fsynr0, fsynr1);

			dev_err(smmu->dev,
				"Client info: BID=0x%x, PID=0x%x, MID=0x%x\n",
				FIELD_GET(FSYNR1_BID, fsynr1),
				FIELD_GET(FSYNR1_PID, fsynr1),
				FIELD_GET(FSYNR1_MID, fsynr1));

			dev_err(smmu->dev,
				"soft iova-to-phys=%pa\n", &phys_soft);
+13 −1
Original line number Diff line number Diff line
@@ -65,6 +65,12 @@ struct notifier_block;
typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
			struct device *, unsigned long, int, void *);

struct iommu_fault_ids {
	u32 bid;
	u32 pid;
	u32 mid;
};

struct iommu_domain_geometry {
	dma_addr_t aperture_start; /* First address that can be mapped    */
	dma_addr_t aperture_end;   /* Last address that can be mapped     */
@@ -385,7 +391,8 @@ extern bool iommu_is_iova_coherent(struct iommu_domain *domain,
				dma_addr_t iova);
extern void iommu_set_fault_handler(struct iommu_domain *domain,
			iommu_fault_handler_t handler, void *token);

extern int iommu_get_fault_ids(struct iommu_domain *domain,
				struct iommu_fault_ids *f_ids);
extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev);
@@ -631,6 +638,11 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
				iommu_fault_handler_t handler, void *token)
{
}
static inline int iommu_get_fault_ids(struct iommu_domain *domain,
				struct iommu_fault_ids *f_ids)
{
	return -EINVAL;
}

static inline void iommu_get_resv_regions(struct device *dev,
					struct list_head *list)