Module Name: src Committed By: riastradh Date: Tue Apr 1 17:48:52 UTC 2014
Modified Files: src/sys/dev/ic: apple_smc.c apple_smc.h apple_smc_fan.c apple_smc_temp.c apple_smcvar.h Log Message: Rework Apple SMC device attachment goo again. Less bookkeeping at the expense of iteration over all devices when rescanning applesmc. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/dev/ic/apple_smc.c \ src/sys/dev/ic/apple_smc.h src/sys/dev/ic/apple_smc_fan.c \ src/sys/dev/ic/apple_smc_temp.c src/sys/dev/ic/apple_smcvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/apple_smc.c diff -u src/sys/dev/ic/apple_smc.c:1.2 src/sys/dev/ic/apple_smc.c:1.3 --- src/sys/dev/ic/apple_smc.c:1.2 Tue Apr 1 17:48:39 2014 +++ src/sys/dev/ic/apple_smc.c Tue Apr 1 17:48:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_smc.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $ */ +/* $NetBSD: apple_smc.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $ */ /* * Apple System Management Controller @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: apple_smc.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apple_smc.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -43,7 +43,6 @@ __KERNEL_RCSID(0, "$NetBSD: apple_smc.c, #include <sys/kmem.h> #include <sys/module.h> #include <sys/mutex.h> -#include <sys/rbtree.h> #include <sys/rwlock.h> #if 0 /* XXX sysctl */ #include <sys/sysctl.h> @@ -54,13 +53,10 @@ __KERNEL_RCSID(0, "$NetBSD: apple_smc.c, #include <dev/ic/apple_smcreg.h> #include <dev/ic/apple_smcvar.h> +/* Must match the config(5) name. */ #define APPLE_SMC_BUS "applesmcbus" -static int apple_smc_dev_compare_nodes(void *, const void *, - const void *); -static int apple_smc_dev_compare_key(void *, const void *, const void *); -static int apple_smc_init(void); -static int apple_smc_fini(void); +static int apple_smc_search(device_t, cfdata_t, const int *, void *); static uint8_t apple_smc_bus_read_1(struct apple_smc_tag *, bus_size_t); static void apple_smc_bus_write_1(struct apple_smc_tag *, bus_size_t, uint8_t); @@ -75,156 +71,17 @@ static int apple_smc_input(struct apple_ static int apple_smc_output(struct apple_smc_tag *, uint8_t, const char *, const void *, uint8_t); -struct apple_smc_dev { - char asd_name[APPLE_SMC_DEVICE_NAME_SIZE]; - rb_node_t asd_node; - device_t asd_dev[]; -}; - -static int -apple_smc_dev_compare_nodes(void *context __unused, const void *va, - const void *vb) -{ - const struct apple_smc_dev *const a = va; - const struct apple_smc_dev *const b = vb; - - return strncmp(a->asd_name, b->asd_name, APPLE_SMC_DEVICE_NAME_SIZE); -} - -static int -apple_smc_dev_compare_key(void *context __unused, const void *vn, - const void *vk) -{ - const struct apple_smc_dev *const dev = vn; - const char *const key = vk; - - return strncmp(dev->asd_name, key, APPLE_SMC_DEVICE_NAME_SIZE); -} - -static krwlock_t apple_smc_registered_devices_lock; -static rb_tree_t apple_smc_registered_devices; -static unsigned int apple_smc_n_registered_devices; - -static const rb_tree_ops_t apple_smc_dev_tree_ops = { - .rbto_compare_nodes = &apple_smc_dev_compare_nodes, - .rbto_compare_key = &apple_smc_dev_compare_key, - .rbto_node_offset = offsetof(struct apple_smc_dev, asd_node), -}; - -static int -apple_smc_init(void) -{ - - rw_init(&apple_smc_registered_devices_lock); - rb_tree_init(&apple_smc_registered_devices, &apple_smc_dev_tree_ops); - apple_smc_n_registered_devices = 0; - - /* Success! */ - return 0; -} - -static int -apple_smc_fini(void) -{ - - /* Refuse to unload if there remain any registered devices. */ - if (apple_smc_n_registered_devices) - return EBUSY; - - /* The tree should be empty in this case. */ - KASSERT(rb_tree_iterate(&apple_smc_registered_devices, NULL, - RB_DIR_RIGHT) == NULL); - -#if 0 /* XXX no rb_tree_destroy */ - rb_tree_destroy(&apple_smc_registered_devices); -#endif - rw_destroy(&apple_smc_registered_devices_lock); - - /* Success! */ - return 0; -} - -int -apple_smc_register_device(const char name[APPLE_SMC_DEVICE_NAME_SIZE]) -{ - int error; - - /* Paranoia about null termination. */ - KASSERT(name[strnlen(name, (sizeof(name) - 1))] == '\0'); - - /* Make a new record for the registration. */ - struct apple_smc_dev *const dev = - kmem_alloc(offsetof(struct apple_smc_dev, asd_dev[0]), KM_SLEEP); - (void)strlcpy(dev->asd_name, name, sizeof(dev->asd_name)); - - rw_enter(&apple_smc_registered_devices_lock, RW_WRITER); - - /* Fail if there are too many. We really oughtn't get here. */ - if (apple_smc_n_registered_devices == UINT_MAX) { - error = ENOMEM; - goto out; - } - - /* Fail if the name is already registered. */ - struct apple_smc_dev *const collision = - rb_tree_insert_node(&apple_smc_registered_devices, dev); - if (collision != dev) { - kmem_free(dev, offsetof(struct apple_smc_dev, asd_dev[0])); - error = EEXIST; - goto out; - } - - /* Success! */ - apple_smc_n_registered_devices++; - error = 0; - -out: - rw_exit(&apple_smc_registered_devices_lock); - return error; -} - -void -apple_smc_unregister_device(const char name[APPLE_SMC_DEVICE_NAME_SIZE]) -{ - - KASSERT(name[strnlen(name, (sizeof(name) - 1))] == '\0'); - - rw_enter(&apple_smc_registered_devices_lock, RW_WRITER); - - /* Find the node. */ - struct apple_smc_dev *const dev = - rb_tree_find_node(&apple_smc_registered_devices, name); - if (dev == NULL) { - printf("%s: device was never registered: %s\n", __func__, - name); - goto out; - } - - /* If we found one, this ought to be at least 1. */ - KASSERT(apple_smc_n_registered_devices > 0); - - /* Remove it, but wait until unlocked to free it (paranoia). */ - rb_tree_remove_node(&apple_smc_registered_devices, dev); - apple_smc_n_registered_devices--; - -out: - rw_exit(&apple_smc_registered_devices_lock); - if (dev != NULL) - kmem_free(dev, offsetof(struct apple_smc_dev, asd_dev[0])); -} - void apple_smc_attach(struct apple_smc_tag *smc) { mutex_init(&smc->smc_lock, MUTEX_DEFAULT, IPL_NONE); - rb_tree_init(&smc->smc_devices, &apple_smc_dev_tree_ops); #if 0 /* XXX sysctl */ apple_smc_sysctl_setup(smc); #endif - (void)apple_smc_rescan(smc, NULL, NULL); + (void)apple_smc_rescan(smc, APPLE_SMC_BUS, NULL); } int @@ -245,105 +102,58 @@ apple_smc_detach(struct apple_smc_tag *s int apple_smc_rescan(struct apple_smc_tag *smc, const char *ifattr, - const int *locators __unused) + const int *locators) { - struct apple_smc_attach_args asa; - struct apple_smc_dev *registered, *attached; - device_t child; - if (!ifattr_match(ifattr, APPLE_SMC_BUS)) - return 0; + (void)config_search_loc(&apple_smc_search, smc->smc_dev, APPLE_SMC_BUS, + locators, smc); + return 0; +} - (void)memset(&asa, 0, sizeof asa); - asa.asa_smc = smc; -#if 0 /* XXX sysctl */ - asa.asa_sysctlnode = smc->smc_sysctlnode; -#endif +static int +apple_smc_search(device_t parent, cfdata_t cf, const int *locators, void *aux) +{ + struct apple_smc_tag *const smc = aux; + static const struct apple_smc_attach_args zero_asa; + struct apple_smc_attach_args asa = zero_asa; + device_t dev; + deviter_t di; + bool attached = false; /* - * Go through all the registered SMC devices and try to attach - * them. + * If this device has already attached, don't attach it again. * - * XXX Horrible quadratic-time loop to avoid holding the rwlock - * during allocation. Fortunately, there are not likely to be - * many of these devices. + * XXX This is a pretty silly way to query the children, but + * struct device doesn't seem to list its children. */ -restart: - registered = NULL; - rw_enter(&apple_smc_registered_devices_lock, RW_READER); - while ((registered = rb_tree_iterate(&apple_smc_registered_devices, - registered, RB_DIR_RIGHT)) != NULL) { - char name[APPLE_SMC_DEVICE_NAME_SIZE]; - CTASSERT(sizeof(name) == sizeof(registered->asd_name)); - - /* Paranoia about null termination. */ - KASSERT(registered->asd_name[strnlen(registered->asd_name, - (sizeof(registered->asd_name) - 1))] == '\0'); - - /* Skip it if we already have it attached. */ - attached = rb_tree_find_node(&smc->smc_devices, - registered->asd_name); - if (attached != NULL) + for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); + dev != NULL; + dev = deviter_next(&di)) { + if (device_parent(dev) != parent) continue; - - /* Try to match it autoconfily. */ - asa.asa_device = registered->asd_name; - child = config_found_ia(smc->smc_dev, APPLE_SMC_BUS, &asa, - NULL); - if (child == NULL) + if (!device_is_a(dev, cf->cf_name)) continue; - - /* Save the name while we drop the lock. */ - (void)strlcpy(name, registered->asd_name, sizeof(name)); - - /* Drop the lock so we can allocate. */ - rw_exit(&apple_smc_registered_devices_lock); - - /* Create a new record for the attachment. */ - attached = kmem_alloc(offsetof(struct apple_smc_dev, - asd_dev[1]), KM_SLEEP); - (void)strlcpy(attached->asd_name, name, sizeof(name)); - attached->asd_dev[0] = child; - - /* Store it in the tree. */ - struct apple_smc_dev *const collision __unused = - rb_tree_insert_node(&smc->smc_devices, attached); - KASSERT(collision == attached); - - /* Start back at the beginning since we dropped the lock. */ - goto restart; + attached = true; + break; } - rw_exit(&apple_smc_registered_devices_lock); + deviter_release(&di); + if (attached) + return 0; - /* Success! */ - return 0; + /* If this device doesn't match, don't attach it. */ + if (!config_match(parent, cf, aux)) + return 0; + + /* Looks hunky-dory. Attach. */ + asa.asa_smc = smc; + (void)config_attach_loc(parent, cf, locators, &asa, NULL); + return 0; } void -apple_smc_child_detached(struct apple_smc_tag *smc, device_t child) +apple_smc_child_detached(struct apple_smc_tag *smc __unused, + device_t child __unused) { - struct apple_smc_dev *dev, *next; - bool done = false; - - /* - * Go through the list of attached devices safely with respect - * to removal and remove any matching entries. There should be - * only one, but paranoia. - */ - for (dev = rb_tree_iterate(&smc->smc_devices, NULL, RB_DIR_RIGHT); - (dev != NULL? - (next = rb_tree_iterate(&smc->smc_devices, dev, - RB_DIR_RIGHT), true) - : false); - dev = next) { - if (dev->asd_dev[0] != child) - continue; - if (done) - printf("apple smc child doubly attached: %s\n", - dev->asd_name); - rb_tree_remove_node(&smc->smc_devices, dev); - kmem_free(dev, offsetof(struct apple_smc_dev, asd_dev[1])); - } } static uint8_t @@ -747,10 +557,10 @@ apple_smc_modcmd(modcmd_t cmd, void *dat switch (cmd) { case MODULE_CMD_INIT: - return apple_smc_init(); + return 0; case MODULE_CMD_FINI: - return apple_smc_fini(); + return 0; default: return ENOTTY; Index: src/sys/dev/ic/apple_smc.h diff -u src/sys/dev/ic/apple_smc.h:1.2 src/sys/dev/ic/apple_smc.h:1.3 --- src/sys/dev/ic/apple_smc.h:1.2 Tue Apr 1 17:48:39 2014 +++ src/sys/dev/ic/apple_smc.h Tue Apr 1 17:48:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_smc.h,v 1.2 2014/04/01 17:48:39 riastradh Exp $ */ +/* $NetBSD: apple_smc.h,v 1.3 2014/04/01 17:48:52 riastradh Exp $ */ /* * Apple System Management Controller Interface @@ -42,7 +42,6 @@ struct apple_smc_tag; struct apple_smc_attach_args { struct apple_smc_tag *asa_smc; - const char *asa_device; }; struct apple_smc_key; @@ -107,9 +106,4 @@ int apple_smc_write_key_2(struct apple_s int apple_smc_write_key_4(struct apple_smc_tag *, const struct apple_smc_key *, uint32_t); -#define APPLE_SMC_DEVICE_NAME_SIZE 0x20 - -int apple_smc_register_device(const char[APPLE_SMC_DEVICE_NAME_SIZE]); -void apple_smc_unregister_device(const char[APPLE_SMC_DEVICE_NAME_SIZE]); - #endif /* _DEV_IC_APPLE_SMC_H_ */ Index: src/sys/dev/ic/apple_smc_fan.c diff -u src/sys/dev/ic/apple_smc_fan.c:1.2 src/sys/dev/ic/apple_smc_fan.c:1.3 --- src/sys/dev/ic/apple_smc_fan.c:1.2 Tue Apr 1 17:48:39 2014 +++ src/sys/dev/ic/apple_smc_fan.c Tue Apr 1 17:48:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_smc_fan.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $ */ +/* $NetBSD: apple_smc_fan.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $ */ /* * Apple System Management Controller: Fans @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: apple_smc_fan.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apple_smc_fan.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -50,8 +50,6 @@ __KERNEL_RCSID(0, "$NetBSD: apple_smc_fa #include <dev/sysmon/sysmonvar.h> -#define APPLE_SMC_DEVICE "applesmcfan" - #define APPLE_SMC_NFANS_KEY "FNum" static const struct fan_sensor { @@ -118,9 +116,6 @@ apple_smc_fan_match(device_t parent, cfd int rv = 0; int error; - if (strcmp(asa->asa_device, APPLE_SMC_DEVICE) != 0) - goto out0; - error = apple_smc_named_key(asa->asa_smc, APPLE_SMC_NFANS_KEY, APPLE_SMC_TYPE_UINT8, &nfans_key); if (error) @@ -424,17 +419,12 @@ apple_smc_fan_modcmd(modcmd_t cmd, void switch (cmd) { case MODULE_CMD_INIT: - error = apple_smc_register_device(APPLE_SMC_DEVICE); - if (error) - return error; #ifdef _MODULE error = config_init_component(cfdriver_ioconf_apple_smc_fan, cfattach_ioconf_apple_smc_fan, cfdata_ioconf_apple_smc_fan); - if (error) { - apple_smc_unregister_device(APPLE_SMC_DEVICE); + if (error) return error; - } #endif return 0; @@ -446,7 +436,6 @@ apple_smc_fan_modcmd(modcmd_t cmd, void if (error) return error; #endif - apple_smc_unregister_device(APPLE_SMC_DEVICE); return 0; default: Index: src/sys/dev/ic/apple_smc_temp.c diff -u src/sys/dev/ic/apple_smc_temp.c:1.2 src/sys/dev/ic/apple_smc_temp.c:1.3 --- src/sys/dev/ic/apple_smc_temp.c:1.2 Tue Apr 1 17:48:39 2014 +++ src/sys/dev/ic/apple_smc_temp.c Tue Apr 1 17:48:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_smc_temp.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $ */ +/* $NetBSD: apple_smc_temp.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $ */ /* * Apple System Management Controller: Temperature Sensors @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: apple_smc_temp.c,v 1.2 2014/04/01 17:48:39 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: apple_smc_temp.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -47,8 +47,6 @@ __KERNEL_RCSID(0, "$NetBSD: apple_smc_te #include <dev/sysmon/sysmonvar.h> -#define APPLE_SMC_DEVICE "applesmctemp" - struct apple_smc_temp_softc { device_t sc_dev; struct apple_smc_tag *sc_smc; @@ -93,9 +91,6 @@ apple_smc_temp_match(device_t parent, cf uint32_t nsensors; int error; - if (strcmp(asa->asa_device, APPLE_SMC_DEVICE) != 0) - return 0; - error = apple_smc_temp_count_sensors(asa->asa_smc, &nsensors); if (error) return 0; @@ -379,17 +374,12 @@ apple_smc_temp_modcmd(modcmd_t cmd, void switch (cmd) { case MODULE_CMD_INIT: - error = apple_smc_register_device(APPLE_SMC_DEVICE); - if (error) - return error; #ifdef _MODULE error = config_init_component(cfdriver_ioconf_apple_smc_temp, cfattach_ioconf_apple_smc_temp, cfdata_ioconf_apple_smc_temp); - if (error) { - apple_smc_unregister_device(APPLE_SMC_DEVICE); + if (error) return error; - } #endif return 0; @@ -401,7 +391,6 @@ apple_smc_temp_modcmd(modcmd_t cmd, void if (error) return error; #endif - apple_smc_unregister_device(APPLE_SMC_DEVICE); return 0; default: Index: src/sys/dev/ic/apple_smcvar.h diff -u src/sys/dev/ic/apple_smcvar.h:1.2 src/sys/dev/ic/apple_smcvar.h:1.3 --- src/sys/dev/ic/apple_smcvar.h:1.2 Tue Apr 1 17:48:39 2014 +++ src/sys/dev/ic/apple_smcvar.h Tue Apr 1 17:48:52 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: apple_smcvar.h,v 1.2 2014/04/01 17:48:39 riastradh Exp $ */ +/* $NetBSD: apple_smcvar.h,v 1.3 2014/04/01 17:48:52 riastradh Exp $ */ /* * Apple System Management Controller State @@ -41,7 +41,6 @@ #include <sys/bus.h> #include <sys/device_if.h> #include <sys/mutex.h> -#include <sys/rbtree.h> struct apple_smc_tag { device_t smc_dev; @@ -55,8 +54,6 @@ struct apple_smc_tag { struct sysctllog *smc_sysctllog; const struct sysctlnode *smc_sysctlnode; #endif - - rb_tree_t smc_devices; }; void apple_smc_attach(struct apple_smc_tag *);