118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * devinfo.c : main file for libdevinfo-based device enumeration 418c2aff7Sartem * 5*3f7d54a6SGarrett D'Amore * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 618c2aff7Sartem * 718c2aff7Sartem * Licensed under the Academic Free License version 2.1 818c2aff7Sartem * 918c2aff7Sartem **************************************************************************/ 1018c2aff7Sartem 1100687e57Sartem #ifdef HAVE_CONFIG_H 1200687e57Sartem # include <config.h> 1300687e57Sartem #endif 1400687e57Sartem 1518c2aff7Sartem #include <stdio.h> 1618c2aff7Sartem #include <string.h> 1718c2aff7Sartem #include <libdevinfo.h> 1818c2aff7Sartem 1918c2aff7Sartem #include "../osspec.h" 2018c2aff7Sartem #include "../logger.h" 2118c2aff7Sartem #include "../hald.h" 2218c2aff7Sartem #include "../hald_dbus.h" 2318c2aff7Sartem #include "../device_info.h" 2418c2aff7Sartem #include "../util.h" 2518c2aff7Sartem #include "../hald_runner.h" 2618c2aff7Sartem #include "osspec_solaris.h" 2718c2aff7Sartem #include "hotplug.h" 2818c2aff7Sartem #include "devinfo.h" 2918c2aff7Sartem #include "devinfo_pci.h" 3018c2aff7Sartem #include "devinfo_storage.h" 3118c2aff7Sartem #include "devinfo_ieee1394.h" 3218c2aff7Sartem #include "devinfo_usb.h" 3318c2aff7Sartem #include "devinfo_misc.h" 347b840e52Sphitran #include "devinfo_acpi.h" 35a9da3307Snp #include "devinfo_cpu.h" 3618c2aff7Sartem 3718c2aff7Sartem void devinfo_add_subtree(HalDevice *parent, di_node_t node, gboolean is_root); 3818c2aff7Sartem HalDevice *devinfo_add_node(HalDevice *parent, di_node_t node); 3918c2aff7Sartem 4018c2aff7Sartem void 4118c2aff7Sartem devinfo_add(HalDevice *parent, gchar *path) 4218c2aff7Sartem { 4318c2aff7Sartem di_node_t root; 4418c2aff7Sartem 4518c2aff7Sartem if (strcmp (path, "/") == 0) { 4618c2aff7Sartem if ((root = di_init(path, DINFOCACHE)) == DI_NODE_NIL) { 4718c2aff7Sartem HAL_INFO (("di_init() failed %d", errno)); 4818c2aff7Sartem return; 4918c2aff7Sartem } 5018c2aff7Sartem } else { 5118c2aff7Sartem if ((root = di_init(path, DINFOCPYALL)) == DI_NODE_NIL) { 5218c2aff7Sartem HAL_INFO (("di_init() failed %d", errno)); 5318c2aff7Sartem return; 5418c2aff7Sartem } 5518c2aff7Sartem } 5618c2aff7Sartem 5718c2aff7Sartem devinfo_add_subtree(parent, root, TRUE); 5818c2aff7Sartem 5918c2aff7Sartem di_fini (root); 6018c2aff7Sartem } 6118c2aff7Sartem 6218c2aff7Sartem void 6318c2aff7Sartem devinfo_add_subtree(HalDevice *parent, di_node_t node, gboolean is_root) 6418c2aff7Sartem { 6518c2aff7Sartem HalDevice *d; 6618c2aff7Sartem di_node_t root_node, child_node; 6718c2aff7Sartem 6818c2aff7Sartem HAL_INFO (("add_subtree: %s", di_node_name (node))); 6918c2aff7Sartem 7018c2aff7Sartem root_node = node; 7118c2aff7Sartem do { 7218c2aff7Sartem d = devinfo_add_node (parent, node); 7318c2aff7Sartem 7418c2aff7Sartem if ((d != NULL) && 7518c2aff7Sartem (child_node = di_child_node (node)) != DI_NODE_NIL) { 7618c2aff7Sartem devinfo_add_subtree (d, child_node, FALSE); 7718c2aff7Sartem } 7818c2aff7Sartem 7918c2aff7Sartem node = di_sibling_node (node); 8018c2aff7Sartem } while ((node != DI_NODE_NIL) && 8118c2aff7Sartem (!is_root || di_parent_node (node) == root_node)); 8218c2aff7Sartem } 8318c2aff7Sartem 8418c2aff7Sartem void 8518c2aff7Sartem devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path) 8618c2aff7Sartem { 8718c2aff7Sartem char *driver_name, *s; 8818c2aff7Sartem const char *s1; 8918c2aff7Sartem char udi[HAL_PATH_MAX]; 9018c2aff7Sartem 9118c2aff7Sartem if (parent != NULL) { 9200687e57Sartem hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent)); 9318c2aff7Sartem } else { 9418c2aff7Sartem hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local"); 9518c2aff7Sartem } 9618c2aff7Sartem 9718c2aff7Sartem hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), 9818c2aff7Sartem "/org/freedesktop/Hal/devices%s_%d", 9918c2aff7Sartem devfs_path, 10018c2aff7Sartem di_instance (node)); 10118c2aff7Sartem hal_device_set_udi (d, udi); 10218c2aff7Sartem hal_device_property_set_string (d, "info.udi", udi); 10318c2aff7Sartem 10418c2aff7Sartem if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) { 10518c2aff7Sartem hal_device_property_set_string (d, "info.product", s); 10618c2aff7Sartem } else { 10718c2aff7Sartem hal_device_property_set_string (d, "info.product", di_node_name (node)); 10818c2aff7Sartem } 10918c2aff7Sartem 11018c2aff7Sartem hal_device_property_set_string (d, "solaris.devfs_path", devfs_path); 11118c2aff7Sartem 11218c2aff7Sartem if ((driver_name = di_driver_name (node)) != NULL) { 11318c2aff7Sartem hal_device_property_set_string (d, "info.solaris.driver", 11418c2aff7Sartem driver_name); 11518c2aff7Sartem } 11618c2aff7Sartem 11718c2aff7Sartem 11818c2aff7Sartem /* inherit parent's claim attributes */ 11918c2aff7Sartem if (hal_device_property_get_bool (parent, "info.claimed")) { 12018c2aff7Sartem s1 = hal_device_property_get_string (parent, "info.claimed.service"); 12118c2aff7Sartem if (s1 != NULL) { 12218c2aff7Sartem hal_device_property_set_bool (d, "info.claimed", TRUE); 12318c2aff7Sartem hal_device_property_set_string (d, "info.claimed.service", s1); 12418c2aff7Sartem } 12518c2aff7Sartem } 12618c2aff7Sartem } 12718c2aff7Sartem 12818c2aff7Sartem /* device handlers, ordered specific to generic */ 12918c2aff7Sartem static DevinfoDevHandler *devinfo_handlers[] = { 13018c2aff7Sartem &devinfo_computer_handler, 13118c2aff7Sartem &devinfo_cpu_handler, 13218c2aff7Sartem &devinfo_ide_handler, 13318c2aff7Sartem &devinfo_scsi_handler, 13400687e57Sartem &devinfo_pcata_handler, 135*3f7d54a6SGarrett D'Amore &devinfo_blkdev_handler, 13618c2aff7Sartem &devinfo_floppy_handler, 13718c2aff7Sartem &devinfo_usb_handler, 13818c2aff7Sartem &devinfo_ieee1394_handler, 13918c2aff7Sartem &devinfo_lofi_handler, 1407b840e52Sphitran &devinfo_acpi_handler, 141d2ec54f7Sphitran &devinfo_power_button_handler, 142d2ec54f7Sphitran &devinfo_keyboard_handler, 143b453864fSLin Guo - Sun Microsystems &devinfo_mouse_handler, 14417c1f1d2SLin Guo - Sun Microsystems &devinfo_pci_handler, 14518c2aff7Sartem &devinfo_default_handler, 14618c2aff7Sartem NULL 14718c2aff7Sartem }; 14818c2aff7Sartem 14918c2aff7Sartem HalDevice * 15018c2aff7Sartem devinfo_add_node(HalDevice *parent, di_node_t node) 15118c2aff7Sartem { 15218c2aff7Sartem HalDevice *d = NULL; 15318c2aff7Sartem char *devfs_path; 15418c2aff7Sartem char *device_type = NULL; 15518c2aff7Sartem DevinfoDevHandler *handler; 15618c2aff7Sartem int i; 15718c2aff7Sartem 15818c2aff7Sartem devfs_path = di_devfs_path (node); 15918c2aff7Sartem 16018c2aff7Sartem (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type", 16118c2aff7Sartem &device_type); 16218c2aff7Sartem 16318c2aff7Sartem for (i = 0; (d == NULL) && (devinfo_handlers[i] != NULL); i++) { 16418c2aff7Sartem handler = devinfo_handlers[i]; 16518c2aff7Sartem d = handler->add (parent, node, devfs_path, device_type); 16618c2aff7Sartem } 16718c2aff7Sartem 16818c2aff7Sartem di_devfs_path_free(devfs_path); 16918c2aff7Sartem 17000687e57Sartem HAL_INFO (("add_node: %s", d ? hal_device_get_udi (d) : "none")); 17118c2aff7Sartem return (d); 17218c2aff7Sartem } 17318c2aff7Sartem 17418c2aff7Sartem void 17518c2aff7Sartem devinfo_hotplug_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler, int action, int front) 17618c2aff7Sartem { 17718c2aff7Sartem HotplugEvent *hotplug_event; 17818c2aff7Sartem 17918c2aff7Sartem hotplug_event = g_new0 (HotplugEvent, 1); 18018c2aff7Sartem hotplug_event->action = action; 18118c2aff7Sartem hotplug_event->type = HOTPLUG_EVENT_DEVFS; 18218c2aff7Sartem hotplug_event->d = d; 18318c2aff7Sartem strlcpy (hotplug_event->un.devfs.devfs_path, devfs_path, 18418c2aff7Sartem sizeof (hotplug_event->un.devfs.devfs_path)); 18518c2aff7Sartem hotplug_event->un.devfs.handler = handler; 18618c2aff7Sartem 18718c2aff7Sartem hotplug_event_enqueue (hotplug_event, front); 18818c2aff7Sartem } 18918c2aff7Sartem 19018c2aff7Sartem void 19118c2aff7Sartem devinfo_add_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler) 19218c2aff7Sartem { 19318c2aff7Sartem devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 0); 19418c2aff7Sartem } 19518c2aff7Sartem 19618c2aff7Sartem void 19718c2aff7Sartem devinfo_add_enqueue_at_front(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler) 19818c2aff7Sartem { 19918c2aff7Sartem devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 1); 20018c2aff7Sartem } 20118c2aff7Sartem 20218c2aff7Sartem void 20318c2aff7Sartem devinfo_remove_enqueue(gchar *devfs_path, DevinfoDevHandler *handler) 20418c2aff7Sartem { 20518c2aff7Sartem devinfo_hotplug_enqueue (NULL, devfs_path, handler, HOTPLUG_ACTION_REMOVE, 0); 20618c2aff7Sartem } 20718c2aff7Sartem 20818c2aff7Sartem void 20918c2aff7Sartem devinfo_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2) 21018c2aff7Sartem { 21118c2aff7Sartem void *end_token = (void *) userdata1; 21218c2aff7Sartem 21318c2aff7Sartem /* Move from temporary to global device store */ 21418c2aff7Sartem hal_device_store_remove (hald_get_tdl (), d); 21518c2aff7Sartem hal_device_store_add (hald_get_gdl (), d); 21618c2aff7Sartem 21718c2aff7Sartem hotplug_event_end (end_token); 21818c2aff7Sartem } 21918c2aff7Sartem 22018c2aff7Sartem void 22118c2aff7Sartem devinfo_callouts_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2) 22218c2aff7Sartem { 22318c2aff7Sartem void *end_token = (void *) userdata1; 22418c2aff7Sartem 22518c2aff7Sartem /* Discard device if probing reports failure */ 22618c2aff7Sartem if (exit_type != HALD_RUN_SUCCESS || (return_code != 0)) { 22700687e57Sartem HAL_INFO (("Probing for %s failed %d", hal_device_get_udi (d), return_code)); 22818c2aff7Sartem hal_device_store_remove (hald_get_tdl (), d); 22918c2aff7Sartem g_object_unref (d); 23018c2aff7Sartem hotplug_event_end (end_token); 23118c2aff7Sartem return; 23218c2aff7Sartem } 23318c2aff7Sartem 23418c2aff7Sartem /* Merge properties from .fdi files */ 23518c2aff7Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION); 23618c2aff7Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY); 23718c2aff7Sartem 23818c2aff7Sartem hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL); 23918c2aff7Sartem } 24018c2aff7Sartem 24118c2aff7Sartem void 24218c2aff7Sartem devinfo_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2) 24318c2aff7Sartem { 24418c2aff7Sartem void *end_token = (void *) userdata1; 24518c2aff7Sartem DevinfoDevHandler *handler = (DevinfoDevHandler *) userdata2; 24618c2aff7Sartem void (*probing_done) (HalDevice *, guint32, gint, char **, gpointer, gpointer); 24718c2aff7Sartem const gchar *prober; 24818c2aff7Sartem int prober_timeout; 24918c2aff7Sartem 25018c2aff7Sartem if (hal_device_property_get_bool (d, "info.ignore")) { 25118c2aff7Sartem HAL_INFO (("Preprobing merged info.ignore==TRUE")); 25218c2aff7Sartem 25318c2aff7Sartem /* Leave device with info.ignore==TRUE so we won't pick up children */ 25418c2aff7Sartem hal_device_property_remove (d, "info.category"); 25518c2aff7Sartem hal_device_property_remove (d, "info.capabilities"); 25618c2aff7Sartem 25718c2aff7Sartem hal_device_store_remove (hald_get_tdl (), d); 25818c2aff7Sartem hal_device_store_add (hald_get_gdl (), d); 25918c2aff7Sartem 26018c2aff7Sartem hotplug_event_end (end_token); 26118c2aff7Sartem return; 26218c2aff7Sartem } 26318c2aff7Sartem 26418c2aff7Sartem if (handler != NULL && handler->get_prober != NULL) { 26518c2aff7Sartem prober = handler->get_prober (d, &prober_timeout); 26618c2aff7Sartem } else { 26718c2aff7Sartem prober = NULL; 26818c2aff7Sartem } 26918c2aff7Sartem 27018c2aff7Sartem if (handler->probing_done != NULL) { 27118c2aff7Sartem probing_done = handler->probing_done; 27218c2aff7Sartem } else { 27318c2aff7Sartem probing_done = devinfo_callouts_probing_done; 27418c2aff7Sartem } 27518c2aff7Sartem 27618c2aff7Sartem if (prober != NULL) { 27718c2aff7Sartem /* probe the device */ 27800687e57Sartem HAL_INFO(("Probing udi=%s", hal_device_get_udi (d))); 27918c2aff7Sartem hald_runner_run (d, 28018c2aff7Sartem prober, NULL, 28118c2aff7Sartem prober_timeout, 28218c2aff7Sartem probing_done, 28318c2aff7Sartem (gpointer) end_token, (gpointer) handler); 28418c2aff7Sartem } else { 28518c2aff7Sartem probing_done (d, 0, 0, NULL, userdata1, userdata2); 28618c2aff7Sartem } 28718c2aff7Sartem } 28818c2aff7Sartem 28918c2aff7Sartem /* This is the beginning of hotplug even handling */ 29018c2aff7Sartem void 29118c2aff7Sartem hotplug_event_begin_add_devinfo (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token) 29218c2aff7Sartem { 2938b80e8cbSLin Guo - Sun Microsystems HotplugEvent *hotplug_event = (HotplugEvent *)end_token; 2948b80e8cbSLin Guo - Sun Microsystems 29500687e57Sartem HAL_INFO(("Preprobing udi=%s", hal_device_get_udi (d))); 29618c2aff7Sartem 2978b80e8cbSLin Guo - Sun Microsystems if (parent == NULL && (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0)) { 2988b80e8cbSLin Guo - Sun Microsystems HAL_ERROR (("Parent is NULL, devfs_path=%s", hotplug_event->un.devfs.devfs_path)); 2998b80e8cbSLin Guo - Sun Microsystems 3008b80e8cbSLin Guo - Sun Microsystems goto skip; 3018b80e8cbSLin Guo - Sun Microsystems } 3028b80e8cbSLin Guo - Sun Microsystems 3038b80e8cbSLin Guo - Sun Microsystems 30418c2aff7Sartem if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) { 30518c2aff7Sartem HAL_INFO (("Ignoring device since parent has info.ignore==TRUE")); 30618c2aff7Sartem 3078b80e8cbSLin Guo - Sun Microsystems goto skip; 30818c2aff7Sartem } 30918c2aff7Sartem 310112cd14aSqz if (hal_device_store_find (hald_get_tdl (), hal_device_get_udi (d)) == NULL) { 311112cd14aSqz 312112cd14aSqz /* add to TDL so preprobing callouts and prober can access it */ 313112cd14aSqz hal_device_store_add (hald_get_tdl (), d); 314112cd14aSqz } 31518c2aff7Sartem 31618c2aff7Sartem /* Process preprobe fdi files */ 31718c2aff7Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE); 31818c2aff7Sartem 31918c2aff7Sartem /* Run preprobe callouts */ 32018c2aff7Sartem hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler); 3218b80e8cbSLin Guo - Sun Microsystems 3228b80e8cbSLin Guo - Sun Microsystems return; 3238b80e8cbSLin Guo - Sun Microsystems 3248b80e8cbSLin Guo - Sun Microsystems skip: 3258b80e8cbSLin Guo - Sun Microsystems if (hal_device_store_find (hald_get_tdl (), hal_device_get_udi (d))) 3268b80e8cbSLin Guo - Sun Microsystems hal_device_store_remove (hald_get_tdl (), d); 3278b80e8cbSLin Guo - Sun Microsystems 3288b80e8cbSLin Guo - Sun Microsystems g_object_unref (d); 3298b80e8cbSLin Guo - Sun Microsystems hotplug_event_end (end_token); 3308b80e8cbSLin Guo - Sun Microsystems 3318b80e8cbSLin Guo - Sun Microsystems return; 33218c2aff7Sartem } 33318c2aff7Sartem 33418c2aff7Sartem void 33518c2aff7Sartem devinfo_remove (gchar *devfs_path) 33618c2aff7Sartem { 33718c2aff7Sartem devinfo_remove_enqueue ((gchar *)devfs_path, NULL); 33818c2aff7Sartem } 33918c2aff7Sartem 34018c2aff7Sartem /* generate hotplug event for each device in this branch */ 34118c2aff7Sartem void 34218c2aff7Sartem devinfo_remove_branch (gchar *devfs_path, HalDevice *d) 34318c2aff7Sartem { 34418c2aff7Sartem GSList *i; 34518c2aff7Sartem GSList *children; 34618c2aff7Sartem HalDevice *child; 34718c2aff7Sartem char *child_devfs_path; 34818c2aff7Sartem 34918c2aff7Sartem if (d == NULL) { 35018c2aff7Sartem d = hal_device_store_match_key_value_string (hald_get_gdl (), 35118c2aff7Sartem "solaris.devfs_path", devfs_path); 35218c2aff7Sartem if (d == NULL) 35318c2aff7Sartem return; 35418c2aff7Sartem } 35518c2aff7Sartem 35600687e57Sartem HAL_INFO (("remove_branch: %s %s\n", devfs_path, hal_device_get_udi (d))); 35718c2aff7Sartem 35818c2aff7Sartem /* first remove children */ 35918c2aff7Sartem children = hal_device_store_match_multiple_key_value_string (hald_get_gdl(), 36000687e57Sartem "info.parent", hal_device_get_udi (d)); 36118c2aff7Sartem for (i = children; i != NULL; i = g_slist_next (i)) { 36218c2aff7Sartem child = HAL_DEVICE (i->data); 36300687e57Sartem HAL_INFO (("remove_branch: child %s\n", hal_device_get_udi (child))); 36418c2aff7Sartem devinfo_remove_branch ((gchar *)hal_device_property_get_string (child, "solaris.devfs_path"), child); 36518c2aff7Sartem } 36618c2aff7Sartem g_slist_free (children); 36718c2aff7Sartem HAL_INFO (("remove_branch: done with children")); 36818c2aff7Sartem 36918c2aff7Sartem /* then remove self */ 37018c2aff7Sartem HAL_INFO (("remove_branch: queueing %s", devfs_path)); 37118c2aff7Sartem devinfo_remove_enqueue (devfs_path, NULL); 37218c2aff7Sartem } 37318c2aff7Sartem 37418c2aff7Sartem void 37518c2aff7Sartem devinfo_callouts_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2) 37618c2aff7Sartem { 37718c2aff7Sartem void *end_token = (void *) userdata1; 37818c2aff7Sartem 37900687e57Sartem HAL_INFO (("Remove callouts completed udi=%s", hal_device_get_udi (d))); 38018c2aff7Sartem 38118c2aff7Sartem if (!hal_device_store_remove (hald_get_gdl (), d)) { 38218c2aff7Sartem HAL_WARNING (("Error removing device")); 38318c2aff7Sartem } 38418c2aff7Sartem g_object_unref (d); 38518c2aff7Sartem 38618c2aff7Sartem hotplug_event_end (end_token); 38718c2aff7Sartem } 38818c2aff7Sartem 38918c2aff7Sartem void 39018c2aff7Sartem hotplug_event_begin_remove_devinfo (HalDevice *d, gchar *devfs_path, void *end_token) 39118c2aff7Sartem { 39218c2aff7Sartem if (hal_device_has_capability (d, "volume")) { 39318c2aff7Sartem devinfo_volume_hotplug_begin_remove (d, devfs_path, end_token); 39418c2aff7Sartem } else { 39518c2aff7Sartem hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL); 39618c2aff7Sartem } 39718c2aff7Sartem } 39818c2aff7Sartem 39918c2aff7Sartem gboolean 40018c2aff7Sartem devinfo_device_rescan (HalDevice *d) 40118c2aff7Sartem { 40218c2aff7Sartem if (hal_device_has_capability (d, "block")) { 40318c2aff7Sartem return (devinfo_storage_device_rescan (d)); 404076d97abSPhi Tran } else if (hal_device_has_capability (d, "button")) { 405076d97abSPhi Tran return (devinfo_lid_rescan (d)); 4067b840e52Sphitran } else { 40718c2aff7Sartem return (FALSE); 40818c2aff7Sartem } 40918c2aff7Sartem } 41042a7bdedSjacobs 41142a7bdedSjacobs static int 41242a7bdedSjacobs walk_devlinks(di_devlink_t devlink, void *arg) 41342a7bdedSjacobs { 41442a7bdedSjacobs char **path= (char **)arg; 41542a7bdedSjacobs 41642a7bdedSjacobs *path = strdup(di_devlink_path(devlink)); 41742a7bdedSjacobs 41842a7bdedSjacobs return (DI_WALK_TERMINATE); 41942a7bdedSjacobs } 42042a7bdedSjacobs 42142a7bdedSjacobs char * 42242a7bdedSjacobs get_devlink(di_devlink_handle_t devlink_hdl, char *re, char *path) 42342a7bdedSjacobs { 42442a7bdedSjacobs char *devlink_path = NULL; 42542a7bdedSjacobs 42642a7bdedSjacobs (void) di_devlink_walk(devlink_hdl, re, path, 42742a7bdedSjacobs DI_PRIMARY_LINK, &devlink_path, walk_devlinks); 42842a7bdedSjacobs 42942a7bdedSjacobs return (devlink_path); 43042a7bdedSjacobs } 431