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:
commit
0dc17d142c
|
@ -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++) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue