Skip to contentSkip to conversation

PATCH: Fixed missing increase of count variable for devicetree path in driver probing

DISCUSSION Linus Walleij 1 participant 1 message May 27, 2014 1 message not in the archive GPIO

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

I have tentatively applied this patch because it looks correct, on future postings, please include the linux-gpio mailing list, Alexandre Courbot and Lars Poeschel.

Yours,
Linus Walleij

Quoted 50 lines · Michael Stickel

Fixed missing increase of count variable for devicetree path in driver probing.

The gpio-mcp23s08 driver has two paths for getting the platform registration information. One for the classic platform initialization and one for openfirmware devicetree based initialization. The devicetree based path is missing the increase of the count variable, which results in the count variable to become negative in the later use, where it is decreased. The count variable is used as an index into a vector. This results in accessing invalid memory space and can result in an exception.

Tested this with an AM3352 SoC with two mcp23s17 on two chip selects as well as on a shared chip select.

--- linux-3.14-rc8/drivers/gpio/gpio-mcp23s08.c 2014-03-25
03:31:17.000000000 +0100
+++
/work/ms/daimler-mm-b-bringup/build_xxsnet2/out/work/xxsnet2-poky-linux-gnueabi/linux/3.14-rc8-3/linux-3.14-rc8/drivers/gpio/gpio-mcp23s08.c

2014-05-26 09:44:25.083824057 +0200
(quoted diff) +10 -2
@@ -895,8 +895,13 @@ static int mcp23s08_probe(struct spi_dev
                        return -ENODEV;
                }
 
-               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
+               for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
                        pullups[addr] = 0;
+                       if (spi_present_mask & (1 << addr))
+                               chips++;
+               }
+               if (!chips)
+                       return -ENODEV;
        } else {
                type = spi_get_device_id(spi)->driver_data;
                pdata = dev_get_platdata(&spi->dev);
@@ -935,6 +940,10 @@ static int mcp23s08_probe(struct spi_dev
                if (!(spi_present_mask & (1 << addr)))
                        continue;
                chips--;
+               if (chips < 0) {
+                       dev_err(&spi->dev, "FATAL: invalid negative chip id\n");
+                       goto fail;
+               }
                data->mcp[addr] = &data->chip[chips];
                status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
                                            0x40 | (addr << 1), type, base,
--

Michael Stickel