diff options
Diffstat (limited to 'usr/src/cmd/hal/hald/solaris/devinfo_cpu.c')
-rw-r--r-- | usr/src/cmd/hal/hald/solaris/devinfo_cpu.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/usr/src/cmd/hal/hald/solaris/devinfo_cpu.c b/usr/src/cmd/hal/hald/solaris/devinfo_cpu.c new file mode 100644 index 0000000000..25128d4de9 --- /dev/null +++ b/usr/src/cmd/hal/hald/solaris/devinfo_cpu.c @@ -0,0 +1,247 @@ +/*************************************************************************** + * + * devinfo_cpu : cpu devices + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Licensed under the Academic Free License version 2.1 + * + **************************************************************************/ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <kstat.h> +#include <sys/utsname.h> +#include <libdevinfo.h> +#include <sys/systeminfo.h> + +#include "../osspec.h" +#include "../logger.h" +#include "../hald.h" +#include "../hald_dbus.h" +#include "../device_info.h" +#include "../util.h" +#include "devinfo_cpu.h" + +static HalDevice *devinfo_cpu_add(HalDevice *, di_node_t, char *, char *); + +DevinfoDevHandler devinfo_cpu_handler = { + devinfo_cpu_add, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static HalDevice * +devinfo_cpu_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type) +{ + + HalDevice *d; + char *prom_device_type = NULL; + int *int_cpu_id; + static int cpu_id = -1; + uint64_t clock_mhz; + di_prom_handle_t phdl; + kstat_ctl_t *kc; + kstat_t *ksp; + kstat_named_t *ksdata; + dbus_bool_t is_supp_freqs; + char udi[HAL_PATH_MAX]; + char *driver_name, *s; + char cpu_devfs_path[HAL_PATH_MAX]; + + /* + * If it is x86, the software device tree node will have the + * device_type information which is the one passed above. If it is + * NULL, check if the node has a PROM entry, and check the device_type + * in case of sparc. Else return NULL + */ + if (device_type == NULL) { + /* + * Check the device type if it has a PROM entry. Because + * in sparc, the device_type entry will in the PROM node + */ + if (di_nodeid (node) == DI_PROM_NODEID) { + phdl = di_prom_init (); + if (phdl == DI_PROM_HANDLE_NIL) { + HAL_ERROR (("Error in Initializing the PROM " + "handle to find cpu device: %s", + strerror (errno))); + return (NULL); + } + if (di_prom_prop_lookup_strings (phdl, node, + "device_type", &prom_device_type) == -1) { + di_prom_fini (phdl); + return (NULL); + } + if (strcmp (prom_device_type, "cpu") != 0) { + di_prom_fini (phdl); + return (NULL); + } + /* + * Get cpuid if available + */ + if (di_prom_prop_lookup_ints (phdl, node, + "cpuid", &int_cpu_id) > 0) { + cpu_id = *int_cpu_id; + } else { + /* + * There is no cpuid entry in this arch.Just + * increment the cpuid which will be the + * current instance + */ + ++cpu_id; + } + di_prom_fini (phdl); + } else { + return (NULL); + } + + } else if (strcmp (device_type, "cpu") == 0) { + /* + * This is a x86 arch, because software device tree node + * has the device_type entry for cpu. The "reg" property + * will have the cpuid. If not just increment the cpuid + * which will be the current cpu instance in the kstat + */ + if (di_prop_lookup_ints (DDI_DEV_T_ANY, node, + "reg", &int_cpu_id) > 0) { + cpu_id = *int_cpu_id; + } else { + /* + * There is no cpuid entry in this arch. Just + * increment the cpuid which will be the + * current instance + */ + ++cpu_id; + } + + } else { + return (NULL); + } + + HAL_DEBUG (("CPUID=> %x", cpu_id)); + + d = hal_device_new (); + + /* + * devinfo_set_default_properties () uses di_instance() as part of + * the udi. For some solaris devices like cpu di_instance() is not + * present and it returns -1. For the udi to be unique can use the + * cpu_id. + */ + hal_device_property_set_string (d, "info.parent", + "/org/freedesktop/Hal/devices/local"); + + /* + * If cpu driver is not installed, then devfs_path returned by + * libdevinfo will be same for all cpu's. + * Since HAL stores the devices in its tree based on the devfs_path, + * To make it unique, will be concatenating devfs_path with cpu_id + */ + if (di_driver_name (node) == NULL) { + snprintf (cpu_devfs_path, HAL_PATH_MAX, "%s_%d", + devfs_path, cpu_id); + } else { + snprintf (cpu_devfs_path, HAL_PATH_MAX, "%s", devfs_path); + } + + HAL_DEBUG(("DevfsPath=> %s, CPUID=> %d", cpu_devfs_path, cpu_id)); + + hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), + "/org/freedesktop/Hal/devices%s_%d", cpu_devfs_path, cpu_id); + hal_device_set_udi (d, udi); + hal_device_property_set_string (d, "info.udi", udi); + if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) { + hal_device_property_set_string (d, "info.product", s); + } else { + hal_device_property_set_string (d, "info.product", + di_node_name (node)); + } + hal_device_property_set_string (d, "solaris.devfs_path", + cpu_devfs_path); + if ((driver_name = di_driver_name (node)) != NULL) { + hal_device_property_set_string (d, "info.solaris.driver", + driver_name); + } + + hal_device_add_capability (d, "processor"); + + hal_device_property_set_int (d, "processor.number", cpu_id); + + /* + * Get the cpu related info from the kstat + */ + kc = kstat_open (); + if (kc == NULL) { + HAL_ERROR (("Could not open kstat to get cpu info: %s", + strerror (errno))); + goto next; + } + + ksp = kstat_lookup (kc, "cpu_info", cpu_id, NULL); + if (ksp == NULL) { + HAL_ERROR (("Could not lookup kstat to get cpu info: %s", + strerror (errno))); + if (kc) { + kstat_close (kc); + } + return (NULL); + } + + kstat_read (kc, ksp, NULL); + ksdata = (kstat_named_t *)kstat_data_lookup (ksp, "clock_MHz"); + if (ksdata == NULL) { + HAL_ERROR (("Could not get kstat clock_MHz data for cpu: %s", + strerror (errno))); + goto next; + } + clock_mhz = (uint64_t)ksdata->value.l; + + if (hal_device_property_set_uint64 (d, "processor.maximum_speed", + clock_mhz) == FALSE) { + HAL_INFO (("Could not set the processor speed device prop")); + } + + + ksdata = (kstat_named_t *)kstat_data_lookup (ksp, + "supported_frequencies_Hz"); + if (ksdata == NULL) { + HAL_INFO (("Could not get kstat supported_frequencies_Hz data" + " for cpu: %s", strerror (errno))); + is_supp_freqs = FALSE; + } else { + /* + * If more than one freq is supported, then they are seperated + * by a ":" + */ + if (strstr (ksdata->value.str.addr.ptr, ":") == NULL) { + is_supp_freqs = FALSE; + } else { + is_supp_freqs = TRUE; + } + } + + if (hal_device_property_set_bool (d, "processor.can_throttle", + is_supp_freqs) == FALSE) { + HAL_INFO (("Could not set the processor.can_throttle" + " device prop")); + } + +next: + if (kc) { + kstat_close (kc); + } + + devinfo_add_enqueue (d, cpu_devfs_path, &devinfo_cpu_handler); + return (d); +} |