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

Commit ef445934 authored by Andy Gross's avatar Andy Gross Committed by Greg Kroah-Hartman
Browse files

staging: omapdrm: Fix error paths during dmm init



Failures during the dmm probe can cause the kernel to crash.  Moved
the spinlock to a global and moved list initializations immediately
after the allocation of the dmm private structure.

Signed-off-by: default avatarAndy Gross <andy.gross@ti.com>
Reviewed-by: default avatarRob Clark <rob.clark@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 39535037
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -181,7 +181,6 @@ struct dmm {


	/* allocation list and lock */
	/* allocation list and lock */
	struct list_head alloc_head;
	struct list_head alloc_head;
	spinlock_t list_lock;
};
};


#endif
#endif
+24 −20
Original line number Original line Diff line number Diff line
@@ -40,6 +40,9 @@
static struct tcm *containers[TILFMT_NFORMATS];
static struct tcm *containers[TILFMT_NFORMATS];
static struct dmm *omap_dmm;
static struct dmm *omap_dmm;


/* global spinlock for protecting lists */
static DEFINE_SPINLOCK(list_lock);

/* Geometry table */
/* Geometry table */
#define GEOM(xshift, yshift, bytes_per_pixel) { \
#define GEOM(xshift, yshift, bytes_per_pixel) { \
		.x_shft = (xshift), \
		.x_shft = (xshift), \
@@ -147,13 +150,13 @@ static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
	down(&dmm->engine_sem);
	down(&dmm->engine_sem);


	/* grab an idle engine */
	/* grab an idle engine */
	spin_lock(&dmm->list_lock);
	spin_lock(&list_lock);
	if (!list_empty(&dmm->idle_head)) {
	if (!list_empty(&dmm->idle_head)) {
		engine = list_entry(dmm->idle_head.next, struct refill_engine,
		engine = list_entry(dmm->idle_head.next, struct refill_engine,
					idle_node);
					idle_node);
		list_del(&engine->idle_node);
		list_del(&engine->idle_node);
	}
	}
	spin_unlock(&dmm->list_lock);
	spin_unlock(&list_lock);


	BUG_ON(!engine);
	BUG_ON(!engine);


@@ -256,9 +259,9 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
	}
	}


cleanup:
cleanup:
	spin_lock(&dmm->list_lock);
	spin_lock(&list_lock);
	list_add(&engine->idle_node, &dmm->idle_head);
	list_add(&engine->idle_node, &dmm->idle_head);
	spin_unlock(&dmm->list_lock);
	spin_unlock(&list_lock);


	up(&omap_dmm->engine_sem);
	up(&omap_dmm->engine_sem);
	return ret;
	return ret;
@@ -351,9 +354,9 @@ struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
	}
	}


	/* add to allocation list */
	/* add to allocation list */
	spin_lock(&omap_dmm->list_lock);
	spin_lock(&list_lock);
	list_add(&block->alloc_node, &omap_dmm->alloc_head);
	list_add(&block->alloc_node, &omap_dmm->alloc_head);
	spin_unlock(&omap_dmm->list_lock);
	spin_unlock(&list_lock);


	return block;
	return block;
}
}
@@ -374,9 +377,9 @@ struct tiler_block *tiler_reserve_1d(size_t size)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);
	}
	}


	spin_lock(&omap_dmm->list_lock);
	spin_lock(&list_lock);
	list_add(&block->alloc_node, &omap_dmm->alloc_head);
	list_add(&block->alloc_node, &omap_dmm->alloc_head);
	spin_unlock(&omap_dmm->list_lock);
	spin_unlock(&list_lock);


	return block;
	return block;
}
}
@@ -389,9 +392,9 @@ int tiler_release(struct tiler_block *block)
	if (block->area.tcm)
	if (block->area.tcm)
		dev_err(omap_dmm->dev, "failed to release block\n");
		dev_err(omap_dmm->dev, "failed to release block\n");


	spin_lock(&omap_dmm->list_lock);
	spin_lock(&list_lock);
	list_del(&block->alloc_node);
	list_del(&block->alloc_node);
	spin_unlock(&omap_dmm->list_lock);
	spin_unlock(&list_lock);


	kfree(block);
	kfree(block);
	return ret;
	return ret;
@@ -479,13 +482,13 @@ static int omap_dmm_remove(struct platform_device *dev)


	if (omap_dmm) {
	if (omap_dmm) {
		/* free all area regions */
		/* free all area regions */
		spin_lock(&omap_dmm->list_lock);
		spin_lock(&list_lock);
		list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
		list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
					alloc_node) {
					alloc_node) {
			list_del(&block->alloc_node);
			list_del(&block->alloc_node);
			kfree(block);
			kfree(block);
		}
		}
		spin_unlock(&omap_dmm->list_lock);
		spin_unlock(&list_lock);


		for (i = 0; i < omap_dmm->num_lut; i++)
		for (i = 0; i < omap_dmm->num_lut; i++)
			if (omap_dmm->tcm && omap_dmm->tcm[i])
			if (omap_dmm->tcm && omap_dmm->tcm[i])
@@ -503,7 +506,7 @@ static int omap_dmm_remove(struct platform_device *dev)


		vfree(omap_dmm->lut);
		vfree(omap_dmm->lut);


		if (omap_dmm->irq != -1)
		if (omap_dmm->irq > 0)
			free_irq(omap_dmm->irq, omap_dmm);
			free_irq(omap_dmm->irq, omap_dmm);


		iounmap(omap_dmm->base);
		iounmap(omap_dmm->base);
@@ -527,6 +530,10 @@ static int omap_dmm_probe(struct platform_device *dev)
		goto fail;
		goto fail;
	}
	}


	/* initialize lists */
	INIT_LIST_HEAD(&omap_dmm->alloc_head);
	INIT_LIST_HEAD(&omap_dmm->idle_head);

	/* lookup hwmod data - base address and irq */
	/* lookup hwmod data - base address and irq */
	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
	if (!mem) {
	if (!mem) {
@@ -629,7 +636,6 @@ static int omap_dmm_probe(struct platform_device *dev)
	}
	}


	sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines);
	sema_init(&omap_dmm->engine_sem, omap_dmm->num_engines);
	INIT_LIST_HEAD(&omap_dmm->idle_head);
	for (i = 0; i < omap_dmm->num_engines; i++) {
	for (i = 0; i < omap_dmm->num_engines; i++) {
		omap_dmm->engines[i].id = i;
		omap_dmm->engines[i].id = i;
		omap_dmm->engines[i].dmm = omap_dmm;
		omap_dmm->engines[i].dmm = omap_dmm;
@@ -672,9 +678,6 @@ static int omap_dmm_probe(struct platform_device *dev)
	containers[TILFMT_32BIT] = omap_dmm->tcm[0];
	containers[TILFMT_32BIT] = omap_dmm->tcm[0];
	containers[TILFMT_PAGE] = omap_dmm->tcm[0];
	containers[TILFMT_PAGE] = omap_dmm->tcm[0];


	INIT_LIST_HEAD(&omap_dmm->alloc_head);
	spin_lock_init(&omap_dmm->list_lock);

	area = (struct tcm_area) {
	area = (struct tcm_area) {
		.is2d = true,
		.is2d = true,
		.tcm = NULL,
		.tcm = NULL,
@@ -697,7 +700,8 @@ static int omap_dmm_probe(struct platform_device *dev)
	return 0;
	return 0;


fail:
fail:
	omap_dmm_remove(dev);
	if (omap_dmm_remove(dev))
		dev_err(&dev->dev, "cleanup failed\n");
	return ret;
	return ret;
}
}


@@ -810,7 +814,7 @@ int tiler_map_show(struct seq_file *s, void *arg)
		map[i] = global_map + i * (w_adj + 1);
		map[i] = global_map + i * (w_adj + 1);
		map[i][w_adj] = 0;
		map[i][w_adj] = 0;
	}
	}
	spin_lock_irqsave(&omap_dmm->list_lock, flags);
	spin_lock_irqsave(&list_lock, flags);


	list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
	list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
		if (block->fmt != TILFMT_PAGE) {
		if (block->fmt != TILFMT_PAGE) {
@@ -836,7 +840,7 @@ int tiler_map_show(struct seq_file *s, void *arg)
		}
		}
	}
	}


	spin_unlock_irqrestore(&omap_dmm->list_lock, flags);
	spin_unlock_irqrestore(&list_lock, flags);


	if (s) {
	if (s) {
		seq_printf(s, "BEGIN DMM TILER MAP\n");
		seq_printf(s, "BEGIN DMM TILER MAP\n");