Date: Fri, 22 May 2020 12:05:01 +0000 (UTC) From: Andriy Gapon <avg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r361372 - stable/12/sys/dev/gpio Message-ID: <202005221205.04MC51rY034050@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avg Date: Fri May 22 12:05:01 2020 New Revision: 361372 URL: https://svnweb.freebsd.org/changeset/base/361372 Log: MFC r360779: gpioiic_attach: fix a NULL pointer crash on hints-based systems The attach method uses GPIO_GET_BUS() to get a "newbus" device that provides a pin. But on hints-based systems a GPIO controller driver might not be fully initialized yet and it does not know gpiobus hanging off it. Thus, GPIO_GET_BUS() cannot be called yet. The reason is that controller drivers typically create a child gpiobus using gpiobus_attach_bus() and that leads to the following call chain: gpiobus_attach_bus() -> gpiobus_attach() -> bus_generic_attach(gpiobus) -> gpioiic_attach(). So, gpioiic_attach() is called before gpiobus_attach_bus() returns. I observed this bug with nctgpio driver on amd64. I think that the problem was introduced in r355276. The fix is to avoid calling GPIO_GET_BUS() from the attach method. Instead, we know that on hints-based systems only the parent gpiobus can provide the pins. Nothing is changed for FDT-based systems. Modified: stable/12/sys/dev/gpio/gpioiic.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/dev/gpio/gpioiic.c ============================================================================== --- stable/12/sys/dev/gpio/gpioiic.c Fri May 22 12:03:17 2020 (r361371) +++ stable/12/sys/dev/gpio/gpioiic.c Fri May 22 12:05:01 2020 (r361372) @@ -303,10 +303,20 @@ gpioiic_attach(device_t dev) return (ENXIO); } - /* Say what we came up with for pin config. */ + /* + * Say what we came up with for pin config. + * NB: in the !FDT case the controller driver might not be set up enough + * for GPIO_GET_BUS() to work. Also, our parent is the only gpiobus + * that can provide our pins. + */ device_printf(dev, "SCL pin: %s:%d, SDA pin: %s:%d\n", +#ifdef FDT device_get_nameunit(GPIO_GET_BUS(sc->sclpin->dev)), sc->sclpin->pin, device_get_nameunit(GPIO_GET_BUS(sc->sdapin->dev)), sc->sdapin->pin); +#else + device_get_nameunit(device_get_parent(dev)), sc->sclpin->pin, + device_get_nameunit(device_get_parent(dev)), sc->sdapin->pin); +#endif /* Add the bitbang driver as our only child; it will add iicbus. */ device_add_child(sc->dev, "iicbb", -1);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202005221205.04MC51rY034050>