Commit 659eaa00 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:

 - Concurrent register updates in the Qualcomm LPASS pin controller gets
   a proper lock.

 - revert a mutex fix that was causing problems: contention on the mutex
   or something of the sort lead to probe reordering and MMC block
   devices start to register in a different order, which unsuspecting
   userspace is not ready to handle

* tag 'pinctrl-v6.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  Revert "pinctrl: avoid unsafe code pattern in find_pinctrl()"
  pinctrl: qcom: lpass-lpi: fix concurrent register updates
parents f6176471 62140a1e
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -1022,20 +1022,17 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev,

static struct pinctrl *find_pinctrl(struct device *dev)
{
	struct pinctrl *entry, *p = NULL;
	struct pinctrl *p;

	mutex_lock(&pinctrl_list_mutex);

	list_for_each_entry(entry, &pinctrl_list, node) {
		if (entry->dev == dev) {
			p = entry;
			kref_get(&p->users);
			break;
		}
	list_for_each_entry(p, &pinctrl_list, node)
		if (p->dev == dev) {
			mutex_unlock(&pinctrl_list_mutex);
			return p;
		}

	mutex_unlock(&pinctrl_list_mutex);
	return p;
	return NULL;
}

static void pinctrl_free(struct pinctrl *p, bool inlist);
@@ -1143,6 +1140,7 @@ struct pinctrl *pinctrl_get(struct device *dev)
	p = find_pinctrl(dev);
	if (p) {
		dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
		kref_get(&p->users);
		return p;
	}

+11 −6
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ struct lpi_pinctrl {
	char __iomem *tlmm_base;
	char __iomem *slew_base;
	struct clk_bulk_data clks[MAX_LPI_NUM_CLKS];
	struct mutex slew_access_lock;
	/* Protects from concurrent register updates */
	struct mutex lock;
	DECLARE_BITMAP(ever_gpio, MAX_NR_GPIO);
	const struct lpi_pinctrl_variant_data *data;
};
@@ -103,6 +104,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
	if (WARN_ON(i == g->nfuncs))
		return -EINVAL;

	mutex_lock(&pctrl->lock);
	val = lpi_gpio_read(pctrl, pin, LPI_GPIO_CFG_REG);

	/*
@@ -128,6 +130,7 @@ static int lpi_gpio_set_mux(struct pinctrl_dev *pctldev, unsigned int function,

	u32p_replace_bits(&val, i, LPI_GPIO_FUNCTION_MASK);
	lpi_gpio_write(pctrl, pin, LPI_GPIO_CFG_REG, val);
	mutex_unlock(&pctrl->lock);

	return 0;
}
@@ -233,14 +236,14 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group,
			if (slew_offset == LPI_NO_SLEW)
				break;

			mutex_lock(&pctrl->slew_access_lock);
			mutex_lock(&pctrl->lock);

			sval = ioread32(pctrl->slew_base + LPI_SLEW_RATE_CTL_REG);
			sval &= ~(LPI_SLEW_RATE_MASK << slew_offset);
			sval |= arg << slew_offset;
			iowrite32(sval, pctrl->slew_base + LPI_SLEW_RATE_CTL_REG);

			mutex_unlock(&pctrl->slew_access_lock);
			mutex_unlock(&pctrl->lock);
			break;
		default:
			return -EINVAL;
@@ -256,6 +259,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group,
		lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val);
	}

	mutex_lock(&pctrl->lock);
	val = lpi_gpio_read(pctrl, group, LPI_GPIO_CFG_REG);

	u32p_replace_bits(&val, pullup, LPI_GPIO_PULL_MASK);
@@ -264,6 +268,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group,
	u32p_replace_bits(&val, output_enabled, LPI_GPIO_OE_MASK);

	lpi_gpio_write(pctrl, group, LPI_GPIO_CFG_REG, val);
	mutex_unlock(&pctrl->lock);

	return 0;
}
@@ -461,7 +466,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev)
	pctrl->chip.label = dev_name(dev);
	pctrl->chip.can_sleep = false;

	mutex_init(&pctrl->slew_access_lock);
	mutex_init(&pctrl->lock);

	pctrl->ctrl = devm_pinctrl_register(dev, &pctrl->desc, pctrl);
	if (IS_ERR(pctrl->ctrl)) {
@@ -483,7 +488,7 @@ int lpi_pinctrl_probe(struct platform_device *pdev)
	return 0;

err_pinctrl:
	mutex_destroy(&pctrl->slew_access_lock);
	mutex_destroy(&pctrl->lock);
	clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks);

	return ret;
@@ -495,7 +500,7 @@ int lpi_pinctrl_remove(struct platform_device *pdev)
	struct lpi_pinctrl *pctrl = platform_get_drvdata(pdev);
	int i;

	mutex_destroy(&pctrl->slew_access_lock);
	mutex_destroy(&pctrl->lock);
	clk_bulk_disable_unprepare(MAX_LPI_NUM_CLKS, pctrl->clks);

	for (i = 0; i < pctrl->data->npins; i++)