Commit dfd7f2c1 authored by Eddie James's avatar Eddie James Committed by Greg Kroah-Hartman
Browse files

fsi: Aspeed: Add mutex to protect HW access



There is nothing to prevent multiple commands being executed
simultaneously. Add a mutex to prevent this.

Fixes: 606397d6 ("fsi: Add ast2600 master driver")
Reviewed-by: default avatarJoel Stanley <joel@jms.id.au>
Reviewed-by: default avatarMilton Miller <miltonm@us.ibm.com>
Signed-off-by: default avatarEddie James <eajames@linux.ibm.com>
Signed-off-by: default avatarJoel Stanley <joel@jms.id.au>
Link: https://lore.kernel.org/r/20201120004929.185239-1-joel@jms.id.au


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fe34761d
Loading
Loading
Loading
Loading
+29 −16
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -19,6 +20,7 @@

struct fsi_master_aspeed {
	struct fsi_master	master;
	struct mutex		lock;	/* protect HW access */
	struct device		*dev;
	void __iomem		*base;
	struct clk		*clk;
@@ -254,6 +256,8 @@ static int aspeed_master_read(struct fsi_master *master, int link,
	addr |= id << 21;
	addr += link * FSI_HUB_LINK_SIZE;

	mutex_lock(&aspeed->lock);

	switch (size) {
	case 1:
		ret = opb_readb(aspeed, fsi_base + addr, val);
@@ -265,14 +269,14 @@ static int aspeed_master_read(struct fsi_master *master, int link,
		ret = opb_readl(aspeed, fsi_base + addr, val);
		break;
	default:
		return -EINVAL;
		ret = -EINVAL;
		goto done;
	}

	ret = check_errors(aspeed, ret);
	if (ret)
done:
	mutex_unlock(&aspeed->lock);
	return ret;

	return 0;
}

static int aspeed_master_write(struct fsi_master *master, int link,
@@ -287,6 +291,8 @@ static int aspeed_master_write(struct fsi_master *master, int link,
	addr |= id << 21;
	addr += link * FSI_HUB_LINK_SIZE;

	mutex_lock(&aspeed->lock);

	switch (size) {
	case 1:
		ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val);
@@ -298,14 +304,14 @@ static int aspeed_master_write(struct fsi_master *master, int link,
		ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val);
		break;
	default:
		return -EINVAL;
		ret = -EINVAL;
		goto done;
	}

	ret = check_errors(aspeed, ret);
	if (ret)
done:
	mutex_unlock(&aspeed->lock);
	return ret;

	return 0;
}

static int aspeed_master_link_enable(struct fsi_master *master, int link,
@@ -320,17 +326,21 @@ static int aspeed_master_link_enable(struct fsi_master *master, int link,

	reg = cpu_to_be32(0x80000000 >> bit);

	if (!enable)
		return opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx),
				  reg);
	mutex_lock(&aspeed->lock);

	if (!enable) {
		ret = opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx), reg);
		goto done;
	}

	ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
	if (ret)
		return ret;
		goto done;

	mdelay(FSI_LINK_ENABLE_SETUP_TIME);

	return 0;
done:
	mutex_unlock(&aspeed->lock);
	return ret;
}

static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id)
@@ -431,9 +441,11 @@ static ssize_t cfam_reset_store(struct device *dev, struct device_attribute *att
{
	struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev);

	mutex_lock(&aspeed->lock);
	gpiod_set_value(aspeed->cfam_reset_gpio, 1);
	usleep_range(900, 1000);
	gpiod_set_value(aspeed->cfam_reset_gpio, 0);
	mutex_unlock(&aspeed->lock);

	return count;
}
@@ -597,6 +609,7 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)

	dev_set_drvdata(&pdev->dev, aspeed);

	mutex_init(&aspeed->lock);
	aspeed_master_init(aspeed);

	rc = fsi_master_register(&aspeed->master);