Re: [PATCH v6 08/25] iommu: exynos: refactor function parameters to simplify code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

On 2015-05-10 15:27, Cho KyongHo wrote:
On Mon, 04 May 2015 10:16:03 +0200 Marek Szyprowski <m.szyprowski@xxxxxxxxxxx> wrote:

This patch simplifies the code by:
- refactoring function parameters from struct device pointer to direct
   pointer to struct sysmmu drvdata
- moving list_head enteries from struct exynos_iommu_owner directly to
   struct sysmmu_drvdata

Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
---
  drivers/iommu/exynos-iommu.c | 93 ++++++++++++++++++++++----------------------
  1 file changed, 46 insertions(+), 47 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index c307c400613c..0c23b69022cd 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -186,8 +186,6 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
/* attached to dev.archdata.iommu of the master device */
  struct exynos_iommu_owner {
-	struct list_head client; /* entry of exynos_iommu_domain.clients */
-	struct device *dev;
  	struct device *sysmmu;
  };
@@ -209,6 +207,7 @@ struct sysmmu_drvdata {
  	int activations;
  	spinlock_t lock;
  	struct iommu_domain *domain;
+	struct list_head domain_node;
  	phys_addr_t pgtable;
  	int version;
  };
@@ -514,12 +513,10 @@ static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  		__raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
  }
-static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
+static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
  					    sysmmu_iova_t iova)
  {
  	unsigned long flags;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data = dev_get_drvdata(owner->sysmmu);
if (!IS_ERR(data->clk_master))
  		clk_enable(data->clk_master);
@@ -533,14 +530,10 @@ static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
  		clk_disable(data->clk_master);
  }
-static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
-					size_t size)
+static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
+					sysmmu_iova_t iova, size_t size)
  {
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
  	unsigned long flags;
-	struct sysmmu_drvdata *data;
-
-	data = dev_get_drvdata(owner->sysmmu);
spin_lock_irqsave(&data->lock, flags);
  	if (is_sysmmu_active(data)) {
@@ -570,8 +563,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
  		if (!IS_ERR(data->clk_master))
  			clk_disable(data->clk_master);
  	} else {
-		dev_dbg(dev, "disabled. Skipping TLB invalidation @ %#x\n",
-			iova);
+		dev_dbg(data->master,
+			"disabled. Skipping TLB invalidation @ %#x\n", iova);
  	}
  	spin_unlock_irqrestore(&data->lock, flags);
  }
@@ -711,7 +704,7 @@ err_pgtable:
  static void exynos_iommu_domain_free(struct iommu_domain *domain)
  {
  	struct exynos_iommu_domain *priv = to_exynos_domain(domain);
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
  	unsigned long flags;
  	int i;
@@ -719,14 +712,12 @@ static void exynos_iommu_domain_free(struct iommu_domain *domain) spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(owner, &priv->clients, client) {
-		while (!exynos_sysmmu_disable(owner->dev))
-			; /* until System MMU is actually disabled */
+	list_for_each_entry(data, &priv->clients, domain_node) {
Use list_for_each_entry_safe() or you will get panic.

Right.


+		if (__sysmmu_disable(data))
+			data->master = NULL;
+		list_del_init(&data->domain_node);
  	}
- while (!list_empty(&priv->clients))
-		list_del_init(priv->clients.next);
-
  	spin_unlock_irqrestore(&priv->lock, flags);
for (i = 0; i < NUM_LV1ENTRIES; i++)
@@ -744,20 +735,26 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
  {
  	struct exynos_iommu_owner *owner = dev->archdata.iommu;
  	struct exynos_iommu_domain *priv = to_exynos_domain(domain);
+	struct sysmmu_drvdata *data;
  	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
  	unsigned long flags;
-	int ret;
+	int ret = -ENODEV;
- spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return -ENODEV;
- ret = __exynos_sysmmu_enable(dev, pagetable, domain);
-	if (ret == 0) {
-		list_add_tail(&owner->client, &priv->clients);
-		owner->domain = domain;
+	data = dev_get_drvdata(owner->sysmmu);
+	if (data) {
Is there a case that a probed System MMU without driver data?

It is better to have one more safety check than to debug strange issues later in
the future.


+		ret = __sysmmu_enable(data, pagetable, domain);
+		if (ret >= 0) {
+			data->master = dev;
+
+			spin_lock_irqsave(&priv->lock, flags);
+			list_add_tail(&data->domain_node, &priv->clients);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
  	}
- spin_unlock_irqrestore(&priv->lock, flags);
-
  	if (ret < 0) {
  		dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
  					__func__, &pagetable);
@@ -773,26 +770,29 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
  static void exynos_iommu_detach_device(struct iommu_domain *domain,
  				    struct device *dev)
  {
-	struct exynos_iommu_owner *owner;
  	struct exynos_iommu_domain *priv = to_exynos_domain(domain);
  	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	struct sysmmu_drvdata *data;
  	unsigned long flags;
+	bool found = false;
- spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return;
- list_for_each_entry(owner, &priv->clients, client) {
-		if (owner == dev->archdata.iommu) {
-			if (exynos_sysmmu_disable(dev)) {
-				list_del_init(&owner->client);
-				owner->domain = NULL;
+	spin_lock_irqsave(&priv->lock, flags);
+	list_for_each_entry(data, &priv->clients, domain_node) {
+		if (data->master == dev) {
+			if (__sysmmu_disable(data)) {
+				data->master = NULL;
+				list_del_init(&data->domain_node);
  			}
+			found = true;
  			break;
  		}
  	}
-
  	spin_unlock_irqrestore(&priv->lock, flags);
- if (owner == dev->archdata.iommu)
+	if (found)
  		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
  					__func__, &pagetable);
  	else
@@ -839,12 +839,11 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
  		 * not currently mapped.
  		 */
  		if (need_flush_flpd_cache) {
-			struct exynos_iommu_owner *owner;
+			struct sysmmu_drvdata *data;
spin_lock(&priv->lock);
-			list_for_each_entry(owner, &priv->clients, client)
-				sysmmu_tlb_invalidate_flpdcache(
-							owner->dev, iova);
+			list_for_each_entry(data, &priv->clients, domain_node)
+				sysmmu_tlb_invalidate_flpdcache(data, iova);
  			spin_unlock(&priv->lock);
  		}
  	}
@@ -879,13 +878,13 @@ static int lv1set_section(struct exynos_iommu_domain *priv,
spin_lock(&priv->lock);
  	if (lv1ent_page_zero(sent)) {
-		struct exynos_iommu_owner *owner;
+		struct sysmmu_drvdata *data;
  		/*
  		 * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
  		 * entry by speculative prefetch of SLPD which has no mapping.
  		 */
-		list_for_each_entry(owner, &priv->clients, client)
-			sysmmu_tlb_invalidate_flpdcache(owner->dev, iova);
+		list_for_each_entry(data, &priv->clients, domain_node)
+			sysmmu_tlb_invalidate_flpdcache(data, iova);
  	}
  	spin_unlock(&priv->lock);
@@ -990,13 +989,13 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
  static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
  						sysmmu_iova_t iova, size_t size)
  {
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
  	unsigned long flags;
spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(owner, &priv->clients, client)
-		sysmmu_tlb_invalidate_entry(owner->dev, iova, size);
+	list_for_each_entry(data, &priv->clients, domain_node)
+		sysmmu_tlb_invalidate_entry(data, iova, size);
spin_unlock_irqrestore(&priv->lock, flags);
  }
--
1.9.2



Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux SoC Development]     [Linux Rockchip Development]     [Linux USB Development]     [Video for Linux]     [Linux Audio Users]     [Linux SCSI]     [Yosemite News]

  Powered by Linux