Yet more GPIO fixes for the v3.19 series:

- Two fixes stabilizing that which was never stable before:
   removal of GPIO chips, now let's stop leaking memory.
 - Make sure OMAP IRQs are usable when the irqchip API
   is used orthogonally to the gpiochip API.
 - Provide a default GPIO base for the mcp23s08 driver.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJUz3/TAAoJEEEQszewGV1zzdUQAJPsvO4e6BhH0rw6eP5z/2Nx
 HOnH0Vi5SpZYgiXw55I3kKcCjaaQ0FCyFo9yrbU0dGnptUFolbauQBHIQD1buzzG
 1rielj4juyHdJrtxAta1zMofmGAL9hIbay63ljN2fbLDnVLAbH+zOygj6viFYhvV
 KMliEQ0tvYg4rm8mcJeJYWKzqk3wrGsTi67RTH6kUEbaaI1BhyF42Mkms8e+JGmz
 XugB1EbczgfwQ64I5Amcdn4adKCfXnh17rBlsHZs8x8Jb2B/xDkwOlCPZguqD/4d
 tURZNAppK3MKXBsWAAcmHfif543jIxWVhhdZfMiuwhTpphxc/7UpkFERjZW+cVr3
 atw6hr0FXGdcokNJ4AWY3lyGsW/lWWQakYjQMYrZ78EW6WhfRxcqpxmb1KzRdhPt
 Gc6eit3wt/3apHPOXo+0dcD4Cusyb+5wE7517ypJ39qauQ87MPAebe09NQfP4e/u
 vwdgMsCHETZ4TpOQ7Pt4Xfqkpvpha0vYu23L9iYabVZJsrF7UNopJgeIJt/rTZwX
 n0zhzlCdiNplKrnYUcHQ5b77O8/oG1Hx6fRKYGfXKe9V4FgV2nl5ry4c/w0Qo/KW
 4dmrRxWJT8u6MAvquXswkMoVdak2mPbVsoG7tT1jz146jhlUYqMSAD3P12EqqWuH
 NfiFlPoSxzz88kINxDqJ
 =7hSD
 -----END PGP SIGNATURE-----

Merge tag 'gpio-v3.19-5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull gpio fixes from Linus Walleij:
 "Yet more GPIO fixes for the v3.19 series.

  There is a high bug-spot activity in GPIO this merge window, much due
  to Johan Hovolds spearheading into actually exercising the removal
  path for GPIO chips, something that was never really exercised before.

  The other two fixes are augmenting erroneous behaviours in two
  specific drivers for minor systems.

  Summary from signed tag:

   - Two fixes stabilizing that which was never stable before: removal
     of GPIO chips, now let's stop leaking memory.
   - Make sure OMAP IRQs are usable when the irqchip API is used
     orthogonally to the gpiochip API.
   - Provide a default GPIO base for the mcp23s08 driver"

* tag 'gpio-v3.19-5' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: sysfs: fix memory leak in gpiod_sysfs_set_active_low
  gpio: sysfs: fix memory leak in gpiod_export_link
  gpio: mcp23s08: handle default gpio base
  gpio: omap: Fix bad device access with setup_irq()
This commit is contained in:
Linus Torvalds 2015-02-03 11:26:54 -08:00
commit 0dc17d142c
3 changed files with 45 additions and 14 deletions

View File

@ -801,9 +801,11 @@ static int mcp230xx_probe(struct i2c_client *client,
client->irq = irq_of_parse_and_map(client->dev.of_node, 0);
} else {
pdata = dev_get_platdata(&client->dev);
if (!pdata || !gpio_is_valid(pdata->base)) {
dev_dbg(&client->dev, "invalid platform data\n");
return -EINVAL;
if (!pdata) {
pdata = devm_kzalloc(&client->dev,
sizeof(struct mcp23s08_platform_data),
GFP_KERNEL);
pdata->base = -1;
}
}
@ -924,10 +926,11 @@ static int mcp23s08_probe(struct spi_device *spi)
} else {
type = spi_get_device_id(spi)->driver_data;
pdata = dev_get_platdata(&spi->dev);
if (!pdata || !gpio_is_valid(pdata->base)) {
dev_dbg(&spi->dev,
"invalid or missing platform data\n");
return -EINVAL;
if (!pdata) {
pdata = devm_kzalloc(&spi->dev,
sizeof(struct mcp23s08_platform_data),
GFP_KERNEL);
pdata->base = -1;
}
for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {

View File

@ -88,6 +88,8 @@ struct gpio_bank {
#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
#define LINE_USED(line, offset) (line & (BIT(offset)))
static void omap_gpio_unmask_irq(struct irq_data *d);
static int omap_irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
{
return bank->chip.base + gpio_irq;
@ -477,6 +479,16 @@ static int omap_gpio_is_input(struct gpio_bank *bank, int mask)
return readl_relaxed(reg) & mask;
}
static void omap_gpio_init_irq(struct gpio_bank *bank, unsigned gpio,
unsigned offset)
{
if (!LINE_USED(bank->mod_usage, offset)) {
omap_enable_gpio_module(bank, offset);
omap_set_gpio_direction(bank, offset, 1);
}
bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));
}
static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
@ -506,15 +518,11 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
spin_lock_irqsave(&bank->lock, flags);
offset = GPIO_INDEX(bank, gpio);
retval = omap_set_gpio_triggering(bank, offset, type);
if (!LINE_USED(bank->mod_usage, offset)) {
omap_enable_gpio_module(bank, offset);
omap_set_gpio_direction(bank, offset, 1);
} else if (!omap_gpio_is_input(bank, BIT(offset))) {
omap_gpio_init_irq(bank, gpio, offset);
if (!omap_gpio_is_input(bank, BIT(offset))) {
spin_unlock_irqrestore(&bank->lock, flags);
return -EINVAL;
}
bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));
spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
@ -792,6 +800,24 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
pm_runtime_put(bank->dev);
}
static unsigned int omap_gpio_irq_startup(struct irq_data *d)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
unsigned int gpio = omap_irq_to_gpio(bank, d->hwirq);
unsigned long flags;
unsigned offset = GPIO_INDEX(bank, gpio);
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
spin_lock_irqsave(&bank->lock, flags);
omap_gpio_init_irq(bank, gpio, offset);
spin_unlock_irqrestore(&bank->lock, flags);
omap_gpio_unmask_irq(d);
return 0;
}
static void omap_gpio_irq_shutdown(struct irq_data *d)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
@ -1181,6 +1207,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
if (!irqc)
return -ENOMEM;
irqc->irq_startup = omap_gpio_irq_startup,
irqc->irq_shutdown = omap_gpio_irq_shutdown,
irqc->irq_ack = omap_gpio_ack_irq,
irqc->irq_mask = omap_gpio_mask_irq,

View File

@ -648,6 +648,7 @@ int gpiod_export_link(struct device *dev, const char *name,
if (tdev != NULL) {
status = sysfs_create_link(&dev->kobj, &tdev->kobj,
name);
put_device(tdev);
} else {
status = -ENODEV;
}
@ -695,7 +696,7 @@ int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
}
status = sysfs_set_active_low(desc, dev, value);
put_device(dev);
unlock:
mutex_unlock(&sysfs_lock);