From e73ebd6840d2874a05ba9d52996c3f2fcf9c3b50 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 31 Jan 2015 15:20:58 +0000 Subject: [PATCH 01/15] Fix build with "device iscsi" in kernel config. Sponsored by: The FreeBSD Foundation --- sys/conf/files | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/conf/files b/sys/conf/files index 38f96a29e4b4..97bbe5914762 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1520,6 +1520,7 @@ ipw_monitor.fw optional ipwmonitorfw | ipwfw \ no-obj no-implicit-rule \ clean "ipw_monitor.fw" dev/iscsi/icl.c optional iscsi | ctl +dev/iscsi/icl_conn_if.m optional iscsi | ctl dev/iscsi/icl_proxy.c optional iscsi | ctl dev/iscsi/icl_soft.c optional iscsi | ctl dev/iscsi/iscsi.c optional iscsi scbus From a6ad7194e02aec7e01cdd2be796aa45b4e8b9abc Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 31 Jan 2015 15:21:54 +0000 Subject: [PATCH 02/15] Drop unneeded include. Sponsored by: The FreeBSD Foundation --- sys/dev/iscsi/icl_wrappers.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/iscsi/icl_wrappers.h b/sys/dev/iscsi/icl_wrappers.h index 374213970462..22cf0a6e2214 100644 --- a/sys/dev/iscsi/icl_wrappers.h +++ b/sys/dev/iscsi/icl_wrappers.h @@ -38,7 +38,6 @@ #define ICL_WRAPPERS_H #include -#include #include #include From 872d2d9276daf0ce92e66a0ab8826a0d472fb3c1 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 31 Jan 2015 15:22:45 +0000 Subject: [PATCH 03/15] Use proper module name in MODULE_VERSION(). Sponsored by: The FreeBSD Foundation --- sys/dev/iscsi/icl_soft.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c index 9b6c695eb7c3..b0c2d40861e9 100644 --- a/sys/dev/iscsi/icl_soft.c +++ b/sys/dev/iscsi/icl_soft.c @@ -1534,4 +1534,4 @@ moduledata_t icl_soft_data = { DECLARE_MODULE(icl_soft, icl_soft_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_DEPEND(icl_soft, icl, 1, 1, 1); -MODULE_VERSION(icl, 1); +MODULE_VERSION(icl_soft, 1); From 484f578134f8f0e87706ad7e92445a8b208daa6d Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Sat, 31 Jan 2015 15:41:01 +0000 Subject: [PATCH 04/15] Prevent access to an uninitialized variable The "-h" option may access an uninitialized value. Prevent it by properly initializing the value. CID: 1006559 --- bin/ps/ps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ps/ps.c b/bin/ps/ps.c index 9d14a72c9a60..449367cd4f1b 100644 --- a/bin/ps/ps.c +++ b/bin/ps/ps.c @@ -178,7 +178,7 @@ main(int argc, char *argv[]) KINFO *kinfo = NULL, *next_KINFO; KINFO_STR *ks; struct varent *vent; - struct winsize ws; + struct winsize ws = { .ws_row = 0 }; const char *nlistf, *memf, *fmtstr, *str; char *cols; int all, ch, elem, flag, _fmt, i, lineno, linelen, left; From 2b8b8321e3141dd7fa92381bfbb7aa001d13e31b Mon Sep 17 00:00:00 2001 From: Luiz Otavio O Souza Date: Sat, 31 Jan 2015 15:50:19 +0000 Subject: [PATCH 05/15] Implement a new method to retrieve the gpiobus reference from a GPIO controller. The gpiobus is responsible to keep track of the used pins and serialize the access to pins. Some of these features are important to devices that do not descend directly from gpiobus and as such cannot make use of its features (one classic example is gpioc that is attached to the GPIO controller and could not, until now, make use of the gpiobus locking). --- sys/dev/gpio/gpio_if.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/dev/gpio/gpio_if.m b/sys/dev/gpio/gpio_if.m index adc119e3d924..6306f336221a 100644 --- a/sys/dev/gpio/gpio_if.m +++ b/sys/dev/gpio/gpio_if.m @@ -32,6 +32,13 @@ INTERFACE gpio; CODE { + static device_t + gpio_default_get_bus(void) + { + + return (NULL); + } + static int gpio_default_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, pcell_t *gpios, uint32_t *pin, @@ -55,6 +62,13 @@ HEADER { #include }; +# +# Return the gpiobus device reference +# +METHOD device_t get_bus { + device_t dev; +} DEFAULT gpio_default_get_bus; + # # Get maximum pin number # From d3b6650ba68c44e3a488aac17bbe56d0cd0e870d Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Sat, 31 Jan 2015 16:26:21 +0000 Subject: [PATCH 06/15] Upstream fixes for issues found with afl (Issue #417). - Fix length checking. Check both the captured length and the on-the-wire length (the latter *should* be greater than or equal to the former, but that's not guaranteed). Add some additional length checks, so neither caplen nor length underflow. If we stop dissecting because the packet is too short, return 1, not 0, as we've "dissected" what we can; 0 means "this is LLC+SNAP with an OUI of 0 and an unknown Ethertype". commit: 743bcecdc92f88b118ec7aac4f68b606601205cc - Clean up length checks. Check only the amount of length that matters at any given point; yes, this means we do multiple checks, but so it goes. We don't need to check for LLC+SNAP - llc_print() does that for us. We do, however, need to check to make sure we can safely skip the Fore header. commit: 5c65e7532fa16308e01299988852b0dc5b027559 --- print-atm.c | 15 ++++++++++++++- print-llc.c | 15 +++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/print-atm.c b/print-atm.c index 2531880b40ef..9361065937b2 100644 --- a/print-atm.c +++ b/print-atm.c @@ -165,7 +165,7 @@ atm_if_print(netdissect_options *ndo, uint32_t llchdr; u_int hdrlen = 0; - if (caplen < 8) { + if (caplen < 1 || length < 1) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } @@ -178,6 +178,15 @@ atm_if_print(netdissect_options *ndo, return hdrlen; } + /* + * Must have at least a DSAP, an SSAP, and the first byte of the + * control field. + */ + if (caplen < 3 || length < 3) { + ND_PRINT((ndo, "%s", tstr)); + return (caplen); + } + /* * Extract the presumed LLC header into a variable, for quick * testing. @@ -205,6 +214,10 @@ atm_if_print(netdissect_options *ndo, * packets? If so, could it be changed to use a * new DLT_IEEE802_6 value if we added it? */ + if (caplen < 20 || length < 20) { + ND_PRINT((ndo, "%s", tstr)); + return (caplen); + } if (ndo->ndo_eflag) ND_PRINT((ndo, "%08x%08x %08x%08x ", EXTRACT_32BITS(p), diff --git a/print-llc.c b/print-llc.c index e78378d05b5a..e8a3314c5c79 100644 --- a/print-llc.c +++ b/print-llc.c @@ -151,10 +151,10 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, *extracted_ethertype = 0; - if (caplen < 3) { + if (caplen < 3 || length < 3) { ND_PRINT((ndo, "[|llc]")); ND_DEFAULTPRINT((u_char *)p, caplen); - return(0); + return (1); } dsap_field = *p; @@ -177,10 +177,10 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, * The control field in I and S frames is * 2 bytes... */ - if (caplen < 4) { + if (caplen < 4 || length < 4) { ND_PRINT((ndo, "[|llc]")); ND_DEFAULTPRINT((u_char *)p, caplen); - return(0); + return (1); } /* @@ -240,6 +240,11 @@ llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, if (ssap == LLCSAP_IP && dsap == LLCSAP_IP && control == LLC_UI) { + if (caplen < 4 || length < 4) { + ND_PRINT((ndo, "[|llc]")); + ND_DEFAULTPRINT((u_char *)p, caplen); + return (1); + } ip_print(ndo, p+4, length-4); return (1); } @@ -368,6 +373,8 @@ snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, register int ret; ND_TCHECK2(*p, 5); + if (caplen < 5 || length < 5) + goto trunc; orgcode = EXTRACT_24BITS(p); et = EXTRACT_16BITS(p + 3); From b90eeb5fb43e1cca60ae0d26e793dc09113de336 Mon Sep 17 00:00:00 2001 From: Jilles Tjoelker Date: Sat, 31 Jan 2015 16:39:26 +0000 Subject: [PATCH 07/15] Ensure #include is sufficient for using SEM_VALUE_MAX. Discussed with: pluknet --- include/semaphore.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/semaphore.h b/include/semaphore.h index 218de995392e..c42a8d230ec2 100644 --- a/include/semaphore.h +++ b/include/semaphore.h @@ -36,6 +36,8 @@ #include #include +#include + struct _sem { __uint32_t _magic; struct _usem2 _kern; From 922a3152f636363056f64dc7210c3e5fca03dc93 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 31 Jan 2015 18:39:32 +0000 Subject: [PATCH 08/15] Correctness improvements for removing FDT excluded memory areas. --- sys/powerpc/ofw/ofw_machdep.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c index 50f9d9e86532..05af09436797 100644 --- a/sys/powerpc/ofw/ofw_machdep.c +++ b/sys/powerpc/ofw/ofw_machdep.c @@ -259,16 +259,14 @@ excise_fdt_reserved(struct mem_region *avail, int asz) if (fdtmap[j].address + fdtmap[j].size < avail[i].mr_start + avail[i].mr_size) { avail[asz].mr_start = - roundup2(fdtmap[j].address + - fdtmap[j].size, PAGE_SIZE); + fdtmap[j].address + fdtmap[j].size; avail[asz].mr_size = avail[i].mr_start + avail[i].mr_size - avail[asz].mr_start; asz++; } - avail[i].mr_size = - rounddown2(fdtmap[j].address, PAGE_MASK) - + avail[i].mr_size = fdtmap[j].address - avail[i].mr_start; } @@ -282,8 +280,10 @@ excise_fdt_reserved(struct mem_region *avail, int asz) avail[i].mr_start && fdtmap[j].address + fdtmap[j].size < avail[i].mr_start + avail[i].mr_size) { + avail[i].mr_size += avail[i].mr_start; avail[i].mr_start = - roundup2(fdtmap[j].address + fdtmap[j].size, PAGE_MASK); + fdtmap[j].address + fdtmap[j].size; + avail[i].mr_size -= avail[i].mr_start; } } } From b717bfa3ceee9be4bef3cdb2ebdda90e341ac949 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 31 Jan 2015 18:42:51 +0000 Subject: [PATCH 09/15] Add code to support loading relocatable kernels at offsets that are not zero. --- sys/boot/common/load_elf.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 6ab2ba4b135e..7b2c8e716aba 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -193,8 +193,9 @@ __elfN(loadfile_raw)(char *filename, u_int64_t dest, /* * Calculate destination address based on kernel entrypoint */ - dest = (ehdr->e_entry & ~PAGE_MASK); - if (dest == 0) { + if (ehdr->e_type == ET_EXEC) + dest = (ehdr->e_entry & ~PAGE_MASK); + if ((ehdr->e_entry & ~PAGE_MASK) == 0) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); err = EPERM; goto oerr; @@ -315,7 +316,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) ret = 0; firstaddr = lastaddr = 0; ehdr = ef->ehdr; - if (ef->kernel) { + if (ehdr->e_type == ET_EXEC) { #if defined(__i386__) || defined(__amd64__) #if __ELF_WORD_SIZE == 64 off = - (off & 0xffffffffff000000ull);/* x86_64 relocates after locore */ @@ -369,10 +370,12 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) #else off = 0; /* other archs use direct mapped kernels */ #endif - __elfN(relocation_offset) = off; } ef->off = off; + if (ef->kernel) + __elfN(relocation_offset) = off; + if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n"); goto out; @@ -729,7 +732,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest) if (err != 0) goto out; - if (ef.ehdr->e_type == ET_EXEC) { + if (ef.kernel == 1 || ef.ehdr->e_type == ET_EXEC) { ef.kernel = 1; } else if (ef.ehdr->e_type != ET_DYN) { err = EFTYPE; From 8535fe7d28f97372c6add4012a84970706c82182 Mon Sep 17 00:00:00 2001 From: Ian Lepore Date: Sat, 31 Jan 2015 18:57:45 +0000 Subject: [PATCH 10/15] Fix whitespace glitch from prior comit. --- sys/dev/fdt/fdt_clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/fdt/fdt_clock.c b/sys/dev/fdt/fdt_clock.c index 88c2ac4c63d8..bebc6ea16daa 100644 --- a/sys/dev/fdt/fdt_clock.c +++ b/sys/dev/fdt/fdt_clock.c @@ -150,7 +150,7 @@ fdt_clock_register_provider(device_t provider) { OF_device_register_xref( - OF_xref_from_node(ofw_bus_get_node(provider)), provider); + OF_xref_from_node(ofw_bus_get_node(provider)), provider); } void From 0fa225054816dd11afab4f819a3833d2ee6f2cd1 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 31 Jan 2015 19:16:51 +0000 Subject: [PATCH 11/15] Build the powerpc64 kernel as a position-independent executable. At startup, it processes its own ELF relocations and can be loaded and run in place at any physical/virtual address. NB: This requires an updated loader to boot! Relnotes: yes --- UPDATING | 5 +++++ sys/conf/Makefile.powerpc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/UPDATING b/UPDATING index c4e7ee8c4c67..6d1988e99040 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20150131: + The powerpc64 kernel has been changed to a position-independent + executable. This can only be booted with a new version of loader(8), + so make sure to update both world and kernel before rebooting. + 20150118: Clang and llvm have been upgraded to 3.5.1 release. This is a bugfix only release, no new features have been added. Please see the 20141231 diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc index 015efc60ae9c..e2d51577158e 100644 --- a/sys/conf/Makefile.powerpc +++ b/sys/conf/Makefile.powerpc @@ -37,6 +37,11 @@ INCLUDES+= -I$S/contrib/libfdt CFLAGS+= -msoft-float -Wa,-many +.if ${MACHINE_ARCH} == "powerpc64" +CFLAGS+= -fPIC +LDFLAGS+= -pie +.endif + .if !empty(DDB_ENABLED) CFLAGS+= -fno-omit-frame-pointer .endif From 79215b4a3ddebcb7f81400259561970873716898 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 31 Jan 2015 19:18:09 +0000 Subject: [PATCH 12/15] Add FDT reservations for memory areas used by OPAL or RTAS runtime firmware. This allows a kexec'ed kernel to boot multiuser under PHYP. --- sys/boot/powerpc/kboot/kbootfdt.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/sys/boot/powerpc/kboot/kbootfdt.c b/sys/boot/powerpc/kboot/kbootfdt.c index 2c10d52e44ff..5ab3c3da43c9 100644 --- a/sys/boot/powerpc/kboot/kbootfdt.c +++ b/sys/boot/powerpc/kboot/kbootfdt.c @@ -110,12 +110,32 @@ fdt_linux_fixups(void *fdtp) */ offset = fdt_path_offset(fdtp, "/memory@0"); - if (offset > 0) { + if (offset > 0) fdt_delprop(fdtp, offset, "available"); - /* - * XXX: add real available properties to reflect RTAS, etc. - * reservations? - */ + + /* + * Add reservations for OPAL and RTAS state if present + */ + + offset = fdt_path_offset(fdtp, "/ibm,opal"); + if (offset > 0) { + uint64_t *base, *size; + base = fdt_getprop(fdtp, offset, "opal-base-address", + &len); + size = fdt_getprop(fdtp, offset, "opal-runtime-size", + &len); + if (base != NULL && size != NULL) + fdt_add_mem_rsv(fdtp, fdt64_to_cpu(*base), + fdt64_to_cpu(*size)); + } + offset = fdt_path_offset(fdtp, "/rtas"); + if (offset > 0) { + uint32_t *base, *size; + base = fdt_getprop(fdtp, offset, "linux,rtas-base", &len); + size = fdt_getprop(fdtp, offset, "rtas-size", &len); + if (base != NULL && size != NULL) + fdt_add_mem_rsv(fdtp, fdt32_to_cpu(*base), + fdt32_to_cpu(*size)); } /* From 7836352b50ed9a6eb4dd72604e7cb42472a91484 Mon Sep 17 00:00:00 2001 From: Luiz Otavio O Souza Date: Sat, 31 Jan 2015 19:32:14 +0000 Subject: [PATCH 13/15] Implement GPIO_GET_BUS() method for all GPIO drivers. Add helper routines to deal with attach and detach of gpiobus and gpioc devices that are common to all drivers. --- sys/arm/allwinner/a10_gpio.c | 22 ++++++++++++++++----- sys/arm/altera/socfpga/socfpga_gpio.c | 23 +++++++++++++++++++--- sys/arm/broadcom/bcm2835/bcm2835_gpio.c | 22 ++++++++++++++++----- sys/arm/freescale/imx/imx_gpio.c | 26 ++++++++++++++++++++----- sys/arm/freescale/vybrid/vf_gpio.c | 24 ++++++++++++++++++++--- sys/arm/lpc/lpc_gpio.c | 23 +++++++++++++++++++--- sys/arm/rockchip/rk30xx_gpio.c | 25 +++++++++++++++++------- sys/arm/samsung/exynos/exynos5_pad.c | 22 +++++++++++++++++---- sys/arm/ti/ti_gpio.c | 25 ++++++++++++++++++------ sys/arm/ti/ti_gpio.h | 1 + sys/arm/xilinx/zy7_gpio.c | 23 ++++++++++++++++++---- sys/arm/xscale/ixp425/avila_gpio.c | 23 ++++++++++++++++++---- sys/arm/xscale/ixp425/cambria_gpio.c | 26 ++++++++++++++++++++----- sys/dev/gpio/gpiobus.c | 24 +++++++++++++++++++++++ sys/dev/gpio/gpiobusvar.h | 2 ++ sys/mips/atheros/ar71xx_gpio.c | 24 +++++++++++++++++++---- sys/mips/atheros/ar71xx_gpiovar.h | 1 + sys/mips/cavium/octeon_gpio.c | 25 +++++++++++++++++++----- sys/mips/cavium/octeon_gpiovar.h | 1 + sys/mips/rt305x/rt305x_gpio.c | 25 +++++++++++++++++++----- sys/mips/rt305x/rt305x_gpiovar.h | 1 + 21 files changed, 320 insertions(+), 68 deletions(-) diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c index 12d69890a500..906b2c4b3758 100644 --- a/sys/arm/allwinner/a10_gpio.c +++ b/sys/arm/allwinner/a10_gpio.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -75,6 +76,7 @@ __FBSDID("$FreeBSD$"); struct a10_gpio_softc { device_t sc_dev; + device_t sc_busdev; struct mtx sc_mtx; struct resource * sc_mem_res; struct resource * sc_irq_res; @@ -217,6 +219,16 @@ a10_gpio_pin_configure(struct a10_gpio_softc *sc, struct gpio_pin *pin, A10_GPIO_UNLOCK(sc); } +static device_t +a10_gpio_get_bus(device_t dev) +{ + struct a10_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int a10_gpio_pin_max(device_t dev, int *maxpin) { @@ -458,13 +470,12 @@ a10_gpio_attach(device_t dev) sc->sc_gpio_pins[i].gp_flags = a10_gpio_func_flag(func); } sc->sc_gpio_npins = i; - - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - a10_gpio_sc = sc; + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) + goto fail; - return (bus_generic_attach(dev)); + return (0); fail: if (sc->sc_irq_res) @@ -490,6 +501,7 @@ static device_method_t a10_gpio_methods[] = { DEVMETHOD(device_detach, a10_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, a10_gpio_get_bus), DEVMETHOD(gpio_pin_max, a10_gpio_pin_max), DEVMETHOD(gpio_pin_getname, a10_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, a10_gpio_pin_getflags), diff --git a/sys/arm/altera/socfpga/socfpga_gpio.c b/sys/arm/altera/socfpga/socfpga_gpio.c index 1a50c7c33bfb..7cec0c18ff86 100644 --- a/sys/arm/altera/socfpga/socfpga_gpio.c +++ b/sys/arm/altera/socfpga/socfpga_gpio.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -107,6 +108,7 @@ enum port_no { /* * GPIO interface */ +static device_t socfpga_gpio_get_bus(device_t); static int socfpga_gpio_pin_max(device_t, int *); static int socfpga_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); static int socfpga_gpio_pin_getname(device_t, uint32_t, char *); @@ -122,6 +124,7 @@ struct socfpga_gpio_softc { bus_space_handle_t bsh; device_t dev; + device_t busdev; struct mtx sc_mtx; int gpio_npins; struct gpio_pin gpio_pins[NR_GPIO_MAX]; @@ -196,11 +199,24 @@ socfpga_gpio_attach(device_t dev) snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "socfpga_gpio%d.%d", device_get_unit(dev), i); } + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + bus_release_resources(dev, socfpga_gpio_spec, sc->res); + mtx_destroy(&sc->sc_mtx); + return (ENXIO); + } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + return (0); +} - return (bus_generic_attach(dev)); +static device_t +socfpga_gpio_get_bus(device_t dev) +{ + struct socfpga_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); } static int @@ -415,6 +431,7 @@ static device_method_t socfpga_gpio_methods[] = { DEVMETHOD(device_attach, socfpga_gpio_attach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, socfpga_gpio_get_bus), DEVMETHOD(gpio_pin_max, socfpga_gpio_pin_max), DEVMETHOD(gpio_pin_getname, socfpga_gpio_pin_getname), DEVMETHOD(gpio_pin_getcaps, socfpga_gpio_pin_getcaps), diff --git a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c index 43a1ddc5e390..2a3cebd99299 100644 --- a/sys/arm/broadcom/bcm2835/bcm2835_gpio.c +++ b/sys/arm/broadcom/bcm2835/bcm2835_gpio.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -83,6 +84,7 @@ struct bcm_gpio_sysctl { struct bcm_gpio_softc { device_t sc_dev; + device_t sc_busdev; struct mtx sc_mtx; struct resource * sc_res[BCM_GPIO_IRQS + 1]; bus_space_tag_t sc_bst; @@ -317,6 +319,16 @@ bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin, BCM_GPIO_UNLOCK(sc); } +static device_t +bcm_gpio_get_bus(device_t dev) +{ + struct bcm_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int bcm_gpio_pin_max(device_t dev, int *maxpin) { @@ -709,13 +721,12 @@ bcm_gpio_attach(device_t dev) i++; } sc->sc_gpio_npins = i; - bcm_gpio_sysctl_init(sc); + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) + goto fail; - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); fail: bus_release_resources(dev, bcm_gpio_res_spec, sc->sc_res); @@ -746,6 +757,7 @@ static device_method_t bcm_gpio_methods[] = { DEVMETHOD(device_detach, bcm_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, bcm_gpio_get_bus), DEVMETHOD(gpio_pin_max, bcm_gpio_pin_max), DEVMETHOD(gpio_pin_getname, bcm_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, bcm_gpio_pin_getflags), diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c index 911c9bbbf748..e70b710a6c1e 100644 --- a/sys/arm/freescale/imx/imx_gpio.c +++ b/sys/arm/freescale/imx/imx_gpio.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -92,6 +93,7 @@ __FBSDID("$FreeBSD$"); struct imx51_gpio_softc { device_t dev; + device_t sc_busdev; struct mtx sc_mtx; struct resource *sc_res[11]; /* 1 x mem, 2 x IRQ, 8 x IRQ */ void *gpio_ih[11]; /* 1 ptr is not a big waste */ @@ -145,6 +147,7 @@ static int imx51_gpio_intr(void *); /* * GPIO interface */ +static device_t imx51_gpio_get_bus(device_t); static int imx51_gpio_pin_max(device_t, int *); static int imx51_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); static int imx51_gpio_pin_getflags(device_t, uint32_t, uint32_t *); @@ -179,6 +182,16 @@ imx51_gpio_pin_configure(struct imx51_gpio_softc *sc, struct gpio_pin *pin, GPIO_UNLOCK(sc); } +static device_t +imx51_gpio_get_bus(device_t dev) +{ + struct imx51_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int imx51_gpio_pin_max(device_t dev, int *maxpin) { @@ -427,11 +440,13 @@ imx51_gpio_attach(device_t dev) snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "imx_gpio%d.%d", device_get_unit(dev), i); } + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) { + imx51_gpio_detach(dev); + return (ENXIO); + } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); } static int @@ -444,7 +459,7 @@ imx51_gpio_detach(device_t dev) KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); - bus_generic_detach(dev); + gpiobus_detach_bus(dev); for (irq = 1; irq <= sc->sc_l_irq; irq ++) { if (sc->gpio_ih[irq]) bus_teardown_intr(dev, sc->sc_res[irq], sc->gpio_ih[irq]); @@ -462,6 +477,7 @@ static device_method_t imx51_gpio_methods[] = { DEVMETHOD(device_detach, imx51_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, imx51_gpio_get_bus), DEVMETHOD(gpio_pin_max, imx51_gpio_pin_max), DEVMETHOD(gpio_pin_getname, imx51_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, imx51_gpio_pin_getflags), diff --git a/sys/arm/freescale/vybrid/vf_gpio.c b/sys/arm/freescale/vybrid/vf_gpio.c index 1fcf32903d09..4f458a180b8c 100644 --- a/sys/arm/freescale/vybrid/vf_gpio.c +++ b/sys/arm/freescale/vybrid/vf_gpio.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -74,6 +75,7 @@ __FBSDID("$FreeBSD$"); /* * GPIO interface */ +static device_t vf_gpio_get_bus(device_t); static int vf_gpio_pin_max(device_t, int *); static int vf_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); static int vf_gpio_pin_getname(device_t, uint32_t, char *); @@ -88,6 +90,7 @@ struct vf_gpio_softc { bus_space_tag_t bst; bus_space_handle_t bsh; + device_t sc_busdev; struct mtx sc_mtx; int gpio_npins; struct gpio_pin gpio_pins[NGPIO]; @@ -147,10 +150,24 @@ vf_gpio_attach(device_t dev) "vf_gpio%d.%d", device_get_unit(dev), i); } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) { + bus_release_resources(dev, vf_gpio_spec, sc->res); + mtx_destroy(&sc->sc_mtx); + return (ENXIO); + } - return (bus_generic_attach(dev)); + return (0); +} + +static device_t +vf_gpio_get_bus(device_t dev) +{ + struct vf_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); } static int @@ -348,6 +365,7 @@ static device_method_t vf_gpio_methods[] = { DEVMETHOD(device_attach, vf_gpio_attach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, vf_gpio_get_bus), DEVMETHOD(gpio_pin_max, vf_gpio_pin_max), DEVMETHOD(gpio_pin_getname, vf_gpio_pin_getname), DEVMETHOD(gpio_pin_getcaps, vf_gpio_pin_getcaps), diff --git a/sys/arm/lpc/lpc_gpio.c b/sys/arm/lpc/lpc_gpio.c index d9536a7012e1..88f37b6cbf57 100644 --- a/sys/arm/lpc/lpc_gpio.c +++ b/sys/arm/lpc/lpc_gpio.c @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$"); struct lpc_gpio_softc { device_t lg_dev; + device_t lg_busdev; struct resource * lg_res; bus_space_tag_t lg_bst; bus_space_handle_t lg_bsh; @@ -135,6 +137,7 @@ static int lpc_gpio_probe(device_t); static int lpc_gpio_attach(device_t); static int lpc_gpio_detach(device_t); +static device_t lpc_gpio_get_bus(device_t); static int lpc_gpio_pin_max(device_t, int *); static int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *); static int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *); @@ -192,10 +195,13 @@ lpc_gpio_attach(device_t dev) lpc_gpio_sc = sc; - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->lg_busdev = gpiobus_attach_bus(dev); + if (sc->lg_busdev == NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->lg_res); + return (ENXIO); + } - return (bus_generic_attach(dev)); + return (0); } static int @@ -204,6 +210,16 @@ lpc_gpio_detach(device_t dev) return (EBUSY); } +static device_t +lpc_gpio_get_bus(device_t dev) +{ + struct lpc_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->lg_busdev); +} + static int lpc_gpio_pin_max(device_t dev, int *npins) { @@ -527,6 +543,7 @@ static device_method_t lpc_gpio_methods[] = { DEVMETHOD(device_detach, lpc_gpio_detach), /* GPIO interface */ + DEVMETHOD(gpio_get_bus, lpc_gpio_get_bus), DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max), DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps), DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags), diff --git a/sys/arm/rockchip/rk30xx_gpio.c b/sys/arm/rockchip/rk30xx_gpio.c index 0728dbf09891..ce20c1c7e067 100644 --- a/sys/arm/rockchip/rk30xx_gpio.c +++ b/sys/arm/rockchip/rk30xx_gpio.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -73,6 +74,7 @@ __FBSDID("$FreeBSD$"); struct rk30_gpio_softc { device_t sc_dev; + device_t sc_busdev; struct mtx sc_mtx; struct resource * sc_mem_res; struct resource * sc_irq_res; @@ -210,6 +212,16 @@ rk30_gpio_pin_configure(struct rk30_gpio_softc *sc, struct gpio_pin *pin, RK30_GPIO_UNLOCK(sc); } +static device_t +rk30_gpio_get_bus(device_t dev) +{ + struct rk30_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int rk30_gpio_pin_max(device_t dev, int *maxpin) { @@ -449,15 +461,13 @@ rk30_gpio_attach(device_t dev) sc->sc_gpio_pins[i].gp_flags = rk30_gpio_get_function(sc, i); } sc->sc_gpio_npins = i; - - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - rk30_gpio_sc = sc; - rk30_gpio_init(); - - return (bus_generic_attach(dev)); + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) + goto fail; + + return (0); fail: if (sc->sc_irq_res) @@ -483,6 +493,7 @@ static device_method_t rk30_gpio_methods[] = { DEVMETHOD(device_detach, rk30_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, rk30_gpio_get_bus), DEVMETHOD(gpio_pin_max, rk30_gpio_pin_max), DEVMETHOD(gpio_pin_getname, rk30_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, rk30_gpio_pin_getflags), diff --git a/sys/arm/samsung/exynos/exynos5_pad.c b/sys/arm/samsung/exynos/exynos5_pad.c index 0e58bf56299e..19fa583ced5a 100644 --- a/sys/arm/samsung/exynos/exynos5_pad.c +++ b/sys/arm/samsung/exynos/exynos5_pad.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -82,6 +83,7 @@ __FBSDID("$FreeBSD$"); /* * GPIO interface */ +static device_t pad_get_bus(device_t); static int pad_pin_max(device_t, int *); static int pad_pin_getcaps(device_t, uint32_t, uint32_t *); static int pad_pin_getname(device_t, uint32_t, char *); @@ -111,6 +113,7 @@ struct pad_softc { struct gpio_pin gpio_pins[MAX_NGPIO]; void *gpio_ih[MAX_PORTS]; device_t dev; + device_t busdev; int model; struct resource_spec *pad_spec; struct gpio_bank *gpio_map; @@ -558,11 +561,11 @@ pad_attach(device_t dev) snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "pad%d.%d", device_get_unit(dev), i); } + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) + goto fail; - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); fail: for (i = 0; i < sc->nports; i++) { @@ -576,6 +579,16 @@ pad_attach(device_t dev) return (ENXIO); } +static device_t +pad_get_bus(device_t dev) +{ + struct pad_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} + static int pad_pin_max(device_t dev, int *maxpin) { @@ -817,6 +830,7 @@ static device_method_t pad_methods[] = { DEVMETHOD(device_attach, pad_attach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, pad_get_bus), DEVMETHOD(gpio_pin_max, pad_pin_max), DEVMETHOD(gpio_pin_getname, pad_pin_getname), DEVMETHOD(gpio_pin_getcaps, pad_pin_getcaps), diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c index 8874ff35046e..63680c647157 100644 --- a/sys/arm/ti/ti_gpio.c +++ b/sys/arm/ti/ti_gpio.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -309,6 +310,16 @@ ti_gpio_intr_status(struct ti_gpio_softc *sc, unsigned int bank) return (reg); } +static device_t +ti_gpio_get_bus(device_t dev) +{ + struct ti_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + /** * ti_gpio_pin_max - Returns the maximum number of GPIO pins * @dev: gpio device handle @@ -815,12 +826,13 @@ ti_gpio_attach(device_t dev) } } } + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) { + ti_gpio_detach(dev); + return (ENXIO); + } - /* Finish of the probe call */ - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); } /** @@ -849,7 +861,7 @@ ti_gpio_detach(device_t dev) if (sc->sc_mem_res[i] != NULL) ti_gpio_intr_clr(sc, i, 0xffffffff); } - bus_generic_detach(dev); + gpiobus_detach_bus(dev); if (sc->sc_events) free(sc->sc_events, M_DEVBUF); if (sc->sc_irq_polarity) @@ -1065,6 +1077,7 @@ static device_method_t ti_gpio_methods[] = { DEVMETHOD(device_detach, ti_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, ti_gpio_get_bus), DEVMETHOD(gpio_pin_max, ti_gpio_pin_max), DEVMETHOD(gpio_pin_getname, ti_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, ti_gpio_pin_getflags), diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h index 763fc8ae792d..a2c0bfbafc4e 100644 --- a/sys/arm/ti/ti_gpio.h +++ b/sys/arm/ti/ti_gpio.h @@ -46,6 +46,7 @@ */ struct ti_gpio_softc { device_t sc_dev; + device_t sc_busdev; /* Interrupt trigger type and level. */ enum intr_trigger *sc_irq_trigger; diff --git a/sys/arm/xilinx/zy7_gpio.c b/sys/arm/xilinx/zy7_gpio.c index 0b888126f62d..25d22f87e4dd 100644 --- a/sys/arm/xilinx/zy7_gpio.c +++ b/sys/arm/xilinx/zy7_gpio.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -88,6 +89,7 @@ __FBSDID("$FreeBSD$"); struct zy7_gpio_softc { device_t dev; + device_t busdev; struct mtx sc_mtx; struct resource *mem_res; /* Memory resource */ }; @@ -113,6 +115,15 @@ struct zy7_gpio_softc { #define ZY7_GPIO_INT_POLARITY(b) (0x0220+0x40*(b)) /* int polarity */ #define ZY7_GPIO_INT_ANY(b) (0x0224+0x40*(b)) /* any edge */ +static device_t +zy7_gpio_get_bus(device_t dev) +{ + struct zy7_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} static int zy7_gpio_pin_max(device_t dev, int *maxpin) @@ -329,10 +340,13 @@ zy7_gpio_attach(device_t dev) /* Completely reset. */ zy7_gpio_hw_reset(sc); - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + zy7_gpio_detach(dev); + return (ENOMEM); + } - return (bus_generic_attach(dev)); + return (0); } static int @@ -340,7 +354,7 @@ zy7_gpio_detach(device_t dev) { struct zy7_gpio_softc *sc = device_get_softc(dev); - bus_generic_detach(dev); + gpiobus_detach_bus(dev); if (sc->mem_res != NULL) { /* Release memory resource. */ @@ -360,6 +374,7 @@ static device_method_t zy7_gpio_methods[] = { DEVMETHOD(device_detach, zy7_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, zy7_gpio_get_bus), DEVMETHOD(gpio_pin_max, zy7_gpio_pin_max), DEVMETHOD(gpio_pin_getname, zy7_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, zy7_gpio_pin_getflags), diff --git a/sys/arm/xscale/ixp425/avila_gpio.c b/sys/arm/xscale/ixp425/avila_gpio.c index 6d92e0871659..d14d9c280388 100644 --- a/sys/arm/xscale/ixp425/avila_gpio.c +++ b/sys/arm/xscale/ixp425/avila_gpio.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "gpio_if.h" @@ -60,6 +61,7 @@ __FBSDID("$FreeBSD$"); struct avila_gpio_softc { device_t sc_dev; + device_t sc_busdev; bus_space_tag_t sc_iot; bus_space_handle_t sc_gpio_ioh; uint32_t sc_valid; @@ -116,6 +118,7 @@ static int avila_gpio_detach(device_t dev); /* * GPIO interface */ +static device_t avila_gpio_get_bus(device_t); static int avila_gpio_pin_max(device_t dev, int *maxpin); static int avila_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); static int avila_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t @@ -162,6 +165,16 @@ avila_gpio_pin_configure(struct avila_gpio_softc *sc, struct gpio_pin *pin, } } +static device_t +avila_gpio_get_bus(device_t dev) +{ + struct avila_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int avila_gpio_pin_max(device_t dev, int *maxpin) { @@ -310,10 +323,11 @@ avila_gpio_attach(device_t dev) sc->sc_valid |= 1 << p->pin; } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) + return (ENXIO); - return (bus_generic_attach(dev)); + return (0); #undef N } @@ -321,7 +335,7 @@ static int avila_gpio_detach(device_t dev) { - bus_generic_detach(dev); + gpiobus_detach_bus(dev); return(0); } @@ -332,6 +346,7 @@ static device_method_t gpio_avila_methods[] = { DEVMETHOD(device_detach, avila_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, avila_gpio_get_bus), DEVMETHOD(gpio_pin_max, avila_gpio_pin_max), DEVMETHOD(gpio_pin_getname, avila_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, avila_gpio_pin_getflags), diff --git a/sys/arm/xscale/ixp425/cambria_gpio.c b/sys/arm/xscale/ixp425/cambria_gpio.c index 16c3489c5263..aa3947b4525a 100644 --- a/sys/arm/xscale/ixp425/cambria_gpio.c +++ b/sys/arm/xscale/ixp425/cambria_gpio.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$"); #define GPIO_PINS 5 struct cambria_gpio_softc { device_t sc_dev; + device_t sc_busdev; bus_space_tag_t sc_iot; bus_space_handle_t sc_gpio_ioh; struct mtx sc_mtx; @@ -119,6 +121,7 @@ static int cambria_gpio_detach(device_t dev); /* * GPIO interface */ +static device_t cambria_gpio_get_bus(device_t); static int cambria_gpio_pin_max(device_t dev, int *maxpin); static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t @@ -261,6 +264,16 @@ cambria_gpio_write(struct cambria_gpio_softc *sc) return (0); } +static device_t +cambria_gpio_get_bus(device_t dev) +{ + struct cambria_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->sc_busdev); +} + static int cambria_gpio_pin_max(device_t dev, int *maxpin) { @@ -438,10 +451,13 @@ cambria_gpio_attach(device_t dev) cambria_gpio_pin_setflags(dev, pin, p->flags); } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->sc_busdev = gpiobus_attach_bus(dev); + if (sc->sc_busdev == NULL) { + mtx_destroy(&sc->sc_mtx); + return (ENXIO); + } - return (bus_generic_attach(dev)); + return (0); } static int @@ -451,8 +467,7 @@ cambria_gpio_detach(device_t dev) KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized")); - bus_generic_detach(dev); - + gpiobus_detach_bus(dev); mtx_destroy(&sc->sc_mtx); return(0); @@ -464,6 +479,7 @@ static device_method_t cambria_gpio_methods[] = { DEVMETHOD(device_detach, cambria_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, cambria_gpio_get_bus), DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max), DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags), diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index efff2c0b5f59..9579fe2512e0 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -131,6 +131,30 @@ gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) strlcat(buf, tmp, buflen); } +device_t +gpiobus_attach_bus(device_t dev) +{ + device_t busdev; + + busdev = device_add_child(dev, "gpiobus", -1); + if (busdev == NULL) + return (NULL); + if (device_add_child(dev, "gpioc", -1) == NULL) { + device_delete_child(dev, busdev); + return (NULL); + } + bus_generic_attach(dev); + + return (busdev); +} + +int +gpiobus_detach_bus(device_t dev) +{ + + return (bus_generic_detach(dev)); +} + int gpiobus_init_softc(device_t dev) { diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h index a1c2be0461ba..5ea4040f0f38 100644 --- a/sys/dev/gpio/gpiobusvar.h +++ b/sys/dev/gpio/gpiobusvar.h @@ -95,6 +95,8 @@ gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells, device_t ofw_gpiobus_add_fdt_child(device_t, phandle_t); #endif int gpio_check_flags(uint32_t, uint32_t); +device_t gpiobus_attach_bus(device_t); +int gpiobus_detach_bus(device_t); int gpiobus_init_softc(device_t); extern driver_t gpiobus_driver; diff --git a/sys/mips/atheros/ar71xx_gpio.c b/sys/mips/atheros/ar71xx_gpio.c index b48e4a6de21b..a029b59271ec 100644 --- a/sys/mips/atheros/ar71xx_gpio.c +++ b/sys/mips/atheros/ar71xx_gpio.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "gpio_if.h" @@ -79,6 +80,7 @@ static void ar71xx_gpio_intr(void *arg); /* * GPIO interface */ +static device_t ar71xx_gpio_get_bus(device_t); static int ar71xx_gpio_pin_max(device_t dev, int *maxpin); static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t @@ -135,6 +137,16 @@ ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, } } +static device_t +ar71xx_gpio_get_bus(device_t dev) +{ + struct ar71xx_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} + static int ar71xx_gpio_pin_max(device_t dev, int *maxpin) { @@ -433,10 +445,13 @@ ar71xx_gpio_attach(device_t dev) ar71xx_gpio_pin_set(dev, j, 1); } } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + ar71xx_gpio_detach(dev); + return (ENXIO); + } - return (bus_generic_attach(dev)); + return (0); } static int @@ -446,7 +461,7 @@ ar71xx_gpio_detach(device_t dev) KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); - bus_generic_detach(dev); + gpiobus_detach_bus(dev); if (sc->gpio_ih) bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); if (sc->gpio_irq_res) @@ -468,6 +483,7 @@ static device_method_t ar71xx_gpio_methods[] = { DEVMETHOD(device_detach, ar71xx_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, ar71xx_gpio_get_bus), DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max), DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags), diff --git a/sys/mips/atheros/ar71xx_gpiovar.h b/sys/mips/atheros/ar71xx_gpiovar.h index 32337ccea87a..47b6e64f41d0 100644 --- a/sys/mips/atheros/ar71xx_gpiovar.h +++ b/sys/mips/atheros/ar71xx_gpiovar.h @@ -57,6 +57,7 @@ struct ar71xx_gpio_softc { device_t dev; + device_t busdev; struct mtx gpio_mtx; struct resource *gpio_mem_res; int gpio_mem_rid; diff --git a/sys/mips/cavium/octeon_gpio.c b/sys/mips/cavium/octeon_gpio.c index 1053976c508f..58aea5ad936e 100644 --- a/sys/mips/cavium/octeon_gpio.c +++ b/sys/mips/cavium/octeon_gpio.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include "gpio_if.h" @@ -90,6 +91,7 @@ static void octeon_gpio_intr(void *arg); /* * GPIO interface */ +static device_t octeon_gpio_get_bus(device_t); static int octeon_gpio_pin_max(device_t dev, int *maxpin); static int octeon_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); static int octeon_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t @@ -134,6 +136,16 @@ octeon_gpio_pin_configure(struct octeon_gpio_softc *sc, struct gpio_pin *pin, GPIO_UNLOCK(sc); } +static device_t +octeon_gpio_get_bus(device_t dev) +{ + struct octeon_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} + static int octeon_gpio_pin_max(device_t dev, int *maxpin) { @@ -434,11 +446,13 @@ octeon_gpio_attach(device_t dev) gpio_cfgx.s.int_en, gpio_cfgx.s.int_type ? "rising edge" : "level"); } } + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + octeon_gpio_detach(dev); + return (ENXIO); + } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); } static int @@ -457,7 +471,7 @@ octeon_gpio_detach(device_t dev) bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid[i], sc->gpio_irq_res[i]); } - bus_generic_detach(dev); + gpiobus_detach_bus(dev); mtx_destroy(&sc->gpio_mtx); return(0); @@ -470,6 +484,7 @@ static device_method_t octeon_gpio_methods[] = { DEVMETHOD(device_detach, octeon_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, octeon_gpio_get_bus), DEVMETHOD(gpio_pin_max, octeon_gpio_pin_max), DEVMETHOD(gpio_pin_getname, octeon_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, octeon_gpio_pin_getflags), diff --git a/sys/mips/cavium/octeon_gpiovar.h b/sys/mips/cavium/octeon_gpiovar.h index a9b814fefb8d..4cf007d3be64 100644 --- a/sys/mips/cavium/octeon_gpiovar.h +++ b/sys/mips/cavium/octeon_gpiovar.h @@ -43,6 +43,7 @@ struct octeon_gpio_softc { device_t dev; + device_t busdev; struct mtx gpio_mtx; struct resource *gpio_irq_res[OCTEON_GPIO_IRQS]; int gpio_irq_rid[OCTEON_GPIO_IRQS]; diff --git a/sys/mips/rt305x/rt305x_gpio.c b/sys/mips/rt305x/rt305x_gpio.c index bf03bd149fcd..1ce02d75f809 100644 --- a/sys/mips/rt305x/rt305x_gpio.c +++ b/sys/mips/rt305x/rt305x_gpio.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "gpio_if.h" @@ -84,6 +85,7 @@ void rt305x_set_int_status(device_t, uint32_t); /* * GPIO interface */ +static device_t rt305x_gpio_get_bus(device_t); static int rt305x_gpio_pin_max(device_t dev, int *maxpin); static int rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); static int rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t @@ -157,6 +159,16 @@ rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, struct gpio_pin *pin, GPIO_UNLOCK(sc); } +static device_t +rt305x_gpio_get_bus(device_t dev) +{ + struct rt305x_gpio_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} + static int rt305x_gpio_pin_max(device_t dev, int *maxpin) { @@ -501,11 +513,13 @@ rt305x_gpio_attach(device_t dev) device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); } #endif + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + rt305x_gpio_detach(dev); + return (ENXIO); + } - device_add_child(dev, "gpioc", -1); - device_add_child(dev, "gpiobus", -1); - - return (bus_generic_attach(dev)); + return (0); } static int @@ -515,7 +529,7 @@ rt305x_gpio_detach(device_t dev) KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); - bus_generic_detach(dev); + gpiobus_detach_bus(dev); if (sc->gpio_ih) bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); if (sc->gpio_irq_res) @@ -589,6 +603,7 @@ static device_method_t rt305x_gpio_methods[] = { DEVMETHOD(device_detach, rt305x_gpio_detach), /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, rt305x_gpio_get_bus), DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max), DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname), DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags), diff --git a/sys/mips/rt305x/rt305x_gpiovar.h b/sys/mips/rt305x/rt305x_gpiovar.h index 85cd6f6429da..d486838e8d22 100644 --- a/sys/mips/rt305x/rt305x_gpiovar.h +++ b/sys/mips/rt305x/rt305x_gpiovar.h @@ -30,6 +30,7 @@ struct rt305x_gpio_softc { device_t dev; + device_t busdev; struct mtx gpio_mtx; struct resource *gpio_mem_res; int gpio_mem_rid; From 878eae988b9cfe8cd81dd87d33ed86d8bb077988 Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 31 Jan 2015 19:42:08 +0000 Subject: [PATCH 14/15] Relocate kernel to high address space (a static + 64 MB for now) to avoid conflicts with the Linux host kernel. This lets you kexec an unmodified GENERIC64. --- sys/boot/powerpc/kboot/conf.c | 4 ---- sys/boot/powerpc/kboot/kerneltramp.S | 2 +- sys/boot/powerpc/kboot/main.c | 18 ++++++++++++++++++ sys/boot/powerpc/kboot/ppc64_elf_freebsd.c | 15 ++++++++++----- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/sys/boot/powerpc/kboot/conf.c b/sys/boot/powerpc/kboot/conf.c index 5338ced11ad9..104dd93ca2fb 100644 --- a/sys/boot/powerpc/kboot/conf.c +++ b/sys/boot/powerpc/kboot/conf.c @@ -115,7 +115,3 @@ struct console *consoles[] = { NULL }; -/* - * reloc - our load address - */ -vm_offset_t reloc = RELOC; diff --git a/sys/boot/powerpc/kboot/kerneltramp.S b/sys/boot/powerpc/kboot/kerneltramp.S index 58b10b0f41d8..a394c9554f30 100644 --- a/sys/boot/powerpc/kboot/kerneltramp.S +++ b/sys/boot/powerpc/kboot/kerneltramp.S @@ -9,6 +9,7 @@ * to the absolute address 0x60. Here we implement a loop waiting on the release * of a lock by the kernel at 0x40. * + * $FreeBSD$ */ #include @@ -39,7 +40,6 @@ CNAME(kerneltramp): mflr %r8 mtlr %r9 lwz %r3,0(%r8) - ld %r3,0(%r3) /* Resolve function descriptor */ mtctr %r3 lwz %r3,4(%r8) lwz %r4,8(%r8) diff --git a/sys/boot/powerpc/kboot/main.c b/sys/boot/powerpc/kboot/main.c index 21898331b948..ec5ba6b651a2 100644 --- a/sys/boot/powerpc/kboot/main.c +++ b/sys/boot/powerpc/kboot/main.c @@ -48,6 +48,7 @@ ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len); int kboot_autoload(void); +uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr); int kboot_setcurrdev(struct env_var *ev, int flags, const void *value); extern int command_fdt_internal(int argc, char *argv[]); @@ -116,6 +117,7 @@ main(int argc, const char **argv) archsw.arch_copyout = kboot_copyout; archsw.arch_readin = kboot_readin; archsw.arch_autoload = kboot_autoload; + archsw.arch_loadaddr = kboot_loadaddr; printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); @@ -282,6 +284,22 @@ kboot_autoload(void) return (0); } +uint64_t +kboot_loadaddr(u_int type, void *data, uint64_t addr) +{ + /* + * Need to stay out of the way of Linux. /chosen/linux,kernel-end does + * a better job here, but use a fixed offset for now. + */ + + if (type == LOAD_ELF) + addr = roundup(addr, PAGE_SIZE); + else + addr += 64*1024*1024; /* Stay out of the way of Linux */ + + return (addr); +} + void _start(int argc, const char **argv, char **env) { diff --git a/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c b/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c index 2cb8017106e2..3ee5e78507eb 100644 --- a/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c +++ b/sys/boot/powerpc/kboot/ppc64_elf_freebsd.c @@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$"); #include "host_syscall.h" extern char end[]; -extern vm_offset_t reloc; /* From /conf.c */ extern void *kerneltramp; extern size_t szkerneltramp; extern int nkexec_segments; @@ -68,17 +67,22 @@ ppc64_elf_exec(struct preloaded_file *fp) Elf_Ehdr *e; int error; uint32_t *trampoline; - vm_offset_t trampolinebase = 96*1024*1024; /* XXX */ + uint64_t entry; + vm_offset_t trampolinebase; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; + + /* Figure out where to put it */ + trampolinebase = archsw.arch_loadaddr(LOAD_RAW, NULL, 0); - /* Handle function descriptor */ + /* Set up interesting values in function descriptor */ trampoline = malloc(szkerneltramp); memcpy(trampoline, &kerneltramp, szkerneltramp); - trampoline[2] = e->e_entry; + archsw.arch_copyout(e->e_entry + elf64_relocation_offset, &entry, 8); + trampoline[2] = entry + elf64_relocation_offset; trampoline[4] = 0; /* Phys. mem offset */ trampoline[5] = 0; /* OF entry point */ @@ -88,7 +92,8 @@ ppc64_elf_exec(struct preloaded_file *fp) trampoline[3] = dtb; trampoline[6] = mdp; trampoline[7] = sizeof(mdp); - printf("Kernel entry at %#jx ...\n", e->e_entry); + printf("Kernel entry at %#jx (%#x) ...\n", e->e_entry, trampoline[2]); + printf("DTB at %#x, mdp at %#x\n", dtb, mdp); dev_cleanup(); From 8e35ef81cc6aae36cd63a4243cf891c94e95ba4c Mon Sep 17 00:00:00 2001 From: Andrew Turner Date: Sat, 31 Jan 2015 19:55:12 +0000 Subject: [PATCH 15/15] Stop using load-multiple with lr and pc. This has been deprecated in ARMv7 and clang 3.6 warns about it. As this is used in libc and we build it with -Werror this warning becomes an error stopping the build. --- sys/arm/include/profile.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sys/arm/include/profile.h b/sys/arm/include/profile.h index c465ba655ee6..a28f33e90d3b 100644 --- a/sys/arm/include/profile.h +++ b/sys/arm/include/profile.h @@ -86,7 +86,12 @@ typedef u_long fptrdiff_t; /* \ * Restore registers that were trashed during mcount \ */ \ - __asm__("ldmfd sp!, {r0-r3, lr, pc}"); + __asm__("ldmfd sp!, {r0-r3, lr}"); \ + /* \ + * Return to the caller. Loading lr and pc in one instruction \ + * is deprecated on ARMv7 so we need this on it's own. \ + */ \ + __asm__("ldmfd sp!, {pc}"); void bintr(void); void btrap(void); void eintr(void);