mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'gpio-fixes-for-v7.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: - fix a memory leak in gpio-sloppy-logic-analyzer - fix a regression in GPIO hog handling for hogs without direction specified - extend the critical section in IRQ handling in gpio-pca953x to cover the reads from the direction register - disable the interrupt on errors when restoring context in gpio-pca953x - apply the initial value when setting direction in gpio-by-pinctrl - use raw spinlock for the register lock in gpio-pch to address locking context issues * tag 'gpio-fixes-for-v7.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: pch: use raw_spinlock_t for the register lock gpio: pca953x: fix cache_only and IRQ state on restore_context() failure gpio: gpio-by-pinctrl: Apply initial value in direction output wrapper gpio: pca953x: fix pca953x_irq_bus_sync_unlock regmap lock gpiolib: tolerate gpio-hogs lacking a hogging state gpio: sloppy-logic-analyzer: Fix memory leak in gpio_la_poll_probe()
This commit is contained in:
@@ -27,12 +27,6 @@ static int pin_control_gpio_get_direction(struct gpio_chip *gc, unsigned int off
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int pin_control_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset, int val)
|
||||
{
|
||||
return pinctrl_gpio_direction_output(chip, offset);
|
||||
}
|
||||
|
||||
static int pin_control_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
unsigned long config;
|
||||
@@ -55,6 +49,18 @@ static int pin_control_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
return pinctrl_gpio_set_config(chip, offset, config);
|
||||
}
|
||||
|
||||
static int pin_control_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset, int val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_gpio_direction_output(chip, offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return pin_control_gpio_set(chip, offset, val);
|
||||
}
|
||||
|
||||
static int pin_control_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
@@ -604,20 +604,28 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
|
||||
static int pca953x_gpio_direction_input_unlocked(struct gpio_chip *gc,
|
||||
unsigned int off)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off);
|
||||
u8 bit = pca953x_get_bit_mask(chip, off);
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
if (PCA_CHIP_TYPE(chip->driver_data) == TCA6418_TYPE)
|
||||
return regmap_update_bits(chip->regmap, dirreg, bit, 0);
|
||||
|
||||
return regmap_update_bits(chip->regmap, dirreg, bit, bit);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
return pca953x_gpio_direction_input_unlocked(gc, off);
|
||||
}
|
||||
|
||||
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned off, int val)
|
||||
{
|
||||
@@ -855,9 +863,10 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
||||
DECLARE_BITMAP(reg_direction, MAX_LINE);
|
||||
int level;
|
||||
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
if (chip->driver_data & PCA_PCAL) {
|
||||
DECLARE_BITMAP(latched_inputs, MAX_LINE);
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
/* Enable latch on edge-triggered interrupt-enabled inputs */
|
||||
bitmap_or(latched_inputs, chip->irq_trig_fall, chip->irq_trig_raise, gc->ngpio);
|
||||
@@ -879,7 +888,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
||||
|
||||
/* Look for any newly setup interrupt */
|
||||
for_each_andnot_bit(level, irq_mask, reg_direction, gc->ngpio)
|
||||
pca953x_gpio_direction_input(&chip->gpio_chip, level);
|
||||
pca953x_gpio_direction_input_unlocked(&chip->gpio_chip, level);
|
||||
|
||||
mutex_unlock(&chip->irq_lock);
|
||||
}
|
||||
@@ -1369,9 +1378,20 @@ static int pca953x_restore_context(struct pca953x_chip *chip)
|
||||
regcache_mark_dirty(chip->regmap);
|
||||
ret = pca953x_regcache_sync(chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
return regcache_sync(chip->regmap);
|
||||
ret = regcache_sync(chip->regmap);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (chip->client->irq > 0)
|
||||
disable_irq(chip->client->irq);
|
||||
regcache_cache_only(chip->regmap, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pca953x_save_context(struct pca953x_chip *chip)
|
||||
|
||||
+14
-14
@@ -96,7 +96,7 @@ struct pch_gpio {
|
||||
struct pch_gpio_reg_data pch_gpio_reg;
|
||||
int irq_base;
|
||||
enum pch_type_t ioh;
|
||||
spinlock_t spinlock;
|
||||
raw_spinlock_t spinlock;
|
||||
};
|
||||
|
||||
static int pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
|
||||
@@ -105,7 +105,7 @@ static int pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
|
||||
struct pch_gpio *chip = gpiochip_get_data(gpio);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
reg_val = ioread32(&chip->reg->po);
|
||||
if (val)
|
||||
reg_val |= BIT(nr);
|
||||
@@ -113,7 +113,7 @@ static int pch_gpio_set(struct gpio_chip *gpio, unsigned int nr, int val)
|
||||
reg_val &= ~BIT(nr);
|
||||
|
||||
iowrite32(reg_val, &chip->reg->po);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -133,7 +133,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
|
||||
u32 reg_val;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
|
||||
reg_val = ioread32(&chip->reg->po);
|
||||
if (val)
|
||||
@@ -147,7 +147,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned int nr,
|
||||
pm |= BIT(nr);
|
||||
iowrite32(pm, &chip->reg->pm);
|
||||
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -158,12 +158,12 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned int nr)
|
||||
u32 pm;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
pm = ioread32(&chip->reg->pm);
|
||||
pm &= BIT(gpio_pins[chip->ioh]) - 1;
|
||||
pm &= ~BIT(nr);
|
||||
iowrite32(pm, &chip->reg->pm);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -265,7 +265,7 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
|
||||
/* Set interrupt mode */
|
||||
im = ioread32(im_reg) & ~(PCH_IM_MASK << (im_pos * 4));
|
||||
@@ -277,7 +277,7 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
|
||||
else if (type & IRQ_TYPE_EDGE_BOTH)
|
||||
irq_set_handler_locked(d, handle_edge_irq);
|
||||
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
|
||||
chip->ioh = id->driver_data;
|
||||
chip->reg = chip->base;
|
||||
pci_set_drvdata(pdev, chip);
|
||||
spin_lock_init(&chip->spinlock);
|
||||
raw_spin_lock_init(&chip->spinlock);
|
||||
pch_gpio_setup(chip);
|
||||
|
||||
ret = devm_gpiochip_add_data(dev, &chip->gpio, chip);
|
||||
@@ -407,9 +407,9 @@ static int pch_gpio_suspend(struct device *dev)
|
||||
struct pch_gpio *chip = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
pch_gpio_save_reg_conf(chip);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -419,11 +419,11 @@ static int pch_gpio_resume(struct device *dev)
|
||||
struct pch_gpio *chip = dev_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&chip->spinlock, flags);
|
||||
raw_spin_lock_irqsave(&chip->spinlock, flags);
|
||||
iowrite32(0x01, &chip->reg->reset);
|
||||
iowrite32(0x00, &chip->reg->reset);
|
||||
pch_gpio_restore_reg_conf(chip);
|
||||
spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
raw_spin_unlock_irqrestore(&chip->spinlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -160,6 +160,13 @@ static int fops_buf_size_get(void *data, u64 *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fops_buf_release(void *data)
|
||||
{
|
||||
struct gpio_la_poll_priv *priv = data;
|
||||
|
||||
vfree(priv->blob.data);
|
||||
}
|
||||
|
||||
static int fops_buf_size_set(void *data, u64 val)
|
||||
{
|
||||
struct gpio_la_poll_priv *priv = data;
|
||||
@@ -238,6 +245,9 @@ static int gpio_la_poll_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
fops_buf_size_set(priv, GPIO_LA_DEFAULT_BUF_SIZE);
|
||||
ret = devm_add_action_or_reset(dev, fops_buf_release, priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->descs = devm_gpiod_get_array(dev, "probe", GPIOD_IN);
|
||||
if (IS_ERR(priv->descs))
|
||||
|
||||
@@ -999,14 +999,17 @@ int gpiochip_add_hog(struct gpio_chip *gc, struct fwnode_handle *fwnode)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fwnode_property_present(fwnode, "input"))
|
||||
if (fwnode_property_present(fwnode, "input")) {
|
||||
dflags |= GPIOD_IN;
|
||||
else if (fwnode_property_present(fwnode, "output-low"))
|
||||
} else if (fwnode_property_present(fwnode, "output-low")) {
|
||||
dflags |= GPIOD_OUT_LOW;
|
||||
else if (fwnode_property_present(fwnode, "output-high"))
|
||||
} else if (fwnode_property_present(fwnode, "output-high")) {
|
||||
dflags |= GPIOD_OUT_HIGH;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
gpiochip_warn(gc, "%pfwP: no hogging state specified, bailing out\n",
|
||||
fwnode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwnode_property_read_string(fwnode, "line-name", &name);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user