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

Commit 06efe0e5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pin control fixes from Linus Walleij:
 "Here is a (hopefully final) slew of pin control fixes for the v3.19
  series.  The deadlock fix is kind of serious and tagged for stable,
  the rest is business as usual.

   - Fix two deadlocks around the pin control mutexes, a long-standing
     issue that manifest itself in plug/unplug of pin controllers.
     (Tagged for stable.)

   - Handle an error path with zero functions in the Qualcomm pin
     controller.

   - Drop a bogus second GPIO chip added in the Lantiq driver.

   - Fix sudden IRQ loss on Rockchip pin controllers.

   - Register the GIT tree in MAINTAINERS"

* tag 'pinctrl-v3.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl:
  pinctrl: MAINTAINERS: add git tree reference
  pinctrl: qcom: Don't iterate past end of function array
  pinctrl: lantiq: remove bogus of_gpio_chip_add
  pinctrl: Fix two deadlocks
  pinctrl: rockchip: Avoid losing interrupts when supporting both edges
parents eef8f4c2 dbe752a3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7410,6 +7410,7 @@ F: drivers/crypto/picoxcell*
PIN CONTROL SUBSYSTEM
M:	Linus Walleij <linus.walleij@linaro.org>
L:	linux-gpio@vger.kernel.org
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git
S:	Maintained
F:	drivers/pinctrl/
F:	include/linux/pinctrl/
+3 −2
Original line number Diff line number Diff line
@@ -1801,14 +1801,15 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
	if (pctldev == NULL)
		return;

	mutex_lock(&pinctrldev_list_mutex);
	mutex_lock(&pctldev->mutex);

	pinctrl_remove_device_debugfs(pctldev);
	mutex_unlock(&pctldev->mutex);

	if (!IS_ERR(pctldev->p))
		pinctrl_put(pctldev->p);

	mutex_lock(&pinctrldev_list_mutex);
	mutex_lock(&pctldev->mutex);
	/* TODO: check that no pinmuxes are still active? */
	list_del(&pctldev->node);
	/* Destroy descriptor tree */
+20 −25
Original line number Diff line number Diff line
@@ -1398,10 +1398,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
{
	struct irq_chip *chip = irq_get_chip(irq);
	struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
	u32 polarity = 0, data = 0;
	u32 pend;
	bool edge_changed = false;
	unsigned long flags;

	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);

@@ -1409,12 +1406,6 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)

	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);

	if (bank->toggle_edge_mode) {
		polarity = readl_relaxed(bank->reg_base +
					 GPIO_INT_POLARITY);
		data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
	}

	while (pend) {
		unsigned int virq;

@@ -1434,27 +1425,31 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
		 * needs manual intervention.
		 */
		if (bank->toggle_edge_mode & BIT(irq)) {
			u32 data, data_old, polarity;
			unsigned long flags;

			data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT);
			do {
				spin_lock_irqsave(&bank->slock, flags);

				polarity = readl_relaxed(bank->reg_base +
							 GPIO_INT_POLARITY);
				if (data & BIT(irq))
					polarity &= ~BIT(irq);
				else
					polarity |= BIT(irq);
				writel(polarity,
				       bank->reg_base + GPIO_INT_POLARITY);

			edge_changed = true;
		}
				spin_unlock_irqrestore(&bank->slock, flags);

		generic_handle_irq(virq);
				data_old = data;
				data = readl_relaxed(bank->reg_base +
						     GPIO_EXT_PORT);
			} while ((data & BIT(irq)) != (data_old & BIT(irq)));
		}

	if (bank->toggle_edge_mode && edge_changed) {
		/* Interrupt params should only be set with ints disabled */
		spin_lock_irqsave(&bank->slock, flags);

		data = readl_relaxed(bank->reg_base + GPIO_INTEN);
		writel_relaxed(0, bank->reg_base + GPIO_INTEN);
		writel(polarity, bank->reg_base + GPIO_INT_POLARITY);
		writel(data, bank->reg_base + GPIO_INTEN);

		spin_unlock_irqrestore(&bank->slock, flags);
		generic_handle_irq(virq);
	}

	chained_irq_exit(chip, desc);
+0 −2
Original line number Diff line number Diff line
@@ -798,10 +798,8 @@ static int pinmux_xway_probe(struct platform_device *pdev)

	/* load the gpio chip */
	xway_chip.dev = &pdev->dev;
	of_gpiochip_add(&xway_chip);
	ret = gpiochip_add(&xway_chip);
	if (ret) {
		of_gpiochip_remove(&xway_chip);
		dev_err(&pdev->dev, "Failed to register gpio chip\n");
		return ret;
	}
+2 −2
Original line number Diff line number Diff line
@@ -865,10 +865,10 @@ static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,

static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl)
{
	int i = 0;
	int i;
	const struct msm_function *func = pctrl->soc->functions;

	for (; i <= pctrl->soc->nfunctions; i++)
	for (i = 0; i < pctrl->soc->nfunctions; i++)
		if (!strcmp(func[i].name, "ps_hold")) {
			pctrl->restart_nb.notifier_call = msm_ps_hold_restart;
			pctrl->restart_nb.priority = 128;