2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Because multiple SES targets can be part of a single chassis, we construct 2N/A * our own hierarchy that takes this into account. These SES targets may refer 2N/A * to the same devices (multiple paths) or to different devices (managing 2N/A * different portions of the space). We arrange things into a 2N/A * ses_enum_enclosure_t, which contains a set of ses targets, and a list of all 2N/A * nodes found so far. 2N/A {
0x0,
"Information unknown" },
2N/A {
0x1,
"External SAS 4x receptacle (see SAS-2 and SFF-8470)" },
2N/A {
0x2,
"External Mini SAS 4x receptacle (see SAS-2 and SFF-8088)" },
2N/A {
0xF,
"Vendor-specific external connector" },
2N/A {
0x10,
"Internal wide SAS 4i plug (see SAS-2 and SFF-8484)" },
2N/A "Internal wide Mini SAS 4i receptacle (see SAS-2 and SFF-8087)" },
2N/A {
0x20,
"Internal SAS Drive receptacle (see SAS-2 and SFF-8482)" },
2N/A {
0x21,
"Internal SATA host plug (see SAS-2 and SATA-2)" },
2N/A {
0x22,
"Internal SAS Drive plug (see SAS-2 and SFF-8482)" },
2N/A {
0x23,
"Internal SATA device plug (see SAS-2 and SATA-2)" },
2N/A {
0x2F,
"Internal SAS virtual connector" },
2N/A {
0x3F,
"Vendor-specific internal connector" },
2N/A {
0x70,
"Other Vendor-specific connector" },
2N/A {
0x71,
"Other Vendor-specific connector" },
2N/A {
0x72,
"Other Vendor-specific connector" },
2N/A {
0x73,
"Other Vendor-specific connector" },
2N/A {
0x74,
"Other Vendor-specific connector" },
2N/A {
0x75,
"Other Vendor-specific connector" },
2N/A {
0x76,
"Other Vendor-specific connector" },
2N/A {
0x77,
"Other Vendor-specific connector" },
2N/A {
0x78,
"Other Vendor-specific connector" },
2N/A {
0x79,
"Other Vendor-specific connector" },
2N/A {
0x7A,
"Other Vendor-specific connector" },
2N/A {
0x7B,
"Other Vendor-specific connector" },
2N/A {
0x7C,
"Other Vendor-specific connector" },
2N/A {
0x7D,
"Other Vendor-specific connector" },
2N/A {
0x7E,
"Other Vendor-specific connector" },
2N/A {
0x7F,
"Other Vendor-specific connector" },
2N/A {
0x80,
"Not Defined" }
2N/A "Connector type not definedi by SES-2 standard" 2N/A "Connector type reserved by SES-2 standard" 2N/A * Structure for the hierarchical tree for element nodes. 2N/A * Functions for tracking ses devices which we were unable to open. We retry 2N/A * these at regular intervals using ses_sof_recheck_dir() and if we find that we 2N/A * can now open any of them then we send a sysevent to indicate that a new topo 2N/A * snapshot should be taken. 2N/A * check list of "unable to open" devices 2N/A * see if we can open it now 2N/A * ok - need to force a new snapshot via sysevent. 2N/A * Delete all sof entries. The sysevent will cause a new 2N/A * ses_enum(), which will create a new, updated, list. 2N/A * functions for verifying that the ses_enum_target_t held in a device 2N/A * contract's cookie field is still valid (it may have been freed by 2N/A * Functions for creating and destroying a background thread 2N/A * (ses_contract_thread) used for detecting when ses devices have been 2N/A /* check if we've been asked to exit */ 2N/A /* poll until an event arrives */ 2N/A * Timeout, check to see if an ses device can 2N/A * now be opened. The fmd DR code should have 2N/A * already gotten a sysevent associated with 2N/A * hotplug, so this 'recheck' code should not 2N/A * be necessary, but we recheck anyway - incase 2N/A * ses_open failed for some transient reason. 2N/A /* read the event */ 2N/A /* see if it is an event we are expecting */ 2N/A "got contract event ctid=%d",
ctid);
2N/A /* find target pointer saved in cookie */ 2N/A /* check if target pointer is still valid */ 2N/A "contract already abandoned %x",
event);
2N/A /* if this is an offline event, do the offline */ 2N/A /* if this is the negend, then abandon the contract */ 2N/A /* prefered set of signals that are likely used to terminate threads */ 2N/A /* reserved set of signals that are not allowed to terminate thread */ 2N/A /* Find signal that is not masked and not in the reserved list. */ 2N/A /* find a suitable signal to use for killing the thread below */ 2N/A /* if don't have a handler for this signal, create one */ 2N/A /* create a thread to listen for offline events */ 2N/A /* convert "/dev" path into "/devices" path */ 2N/A /* set up template to create new contract */ 2N/A /* strip "../../devices" off the front and create the contract */ 2N/A /* check if already closed due to contract offline request */ 2N/A * Return a current instance of the node. This is somewhat complicated because 2N/A * we need to take a new snapshot in order to get the new data, but we don't 2N/A * want to be constantly taking SES snapshots if the consumer is going to do a 2N/A * series of queries. So we adopt the strategy of assuming that the SES state 2N/A * is not going to be rapidly changing, and limit our snapshot frequency to 2N/A * some defined bounds. 2N/A * Determine if we need to take a new snapshot. 2N/A * We may have closed the device but not yet abandoned the 2N/A * contract (ie we've had the offline event but not yet the 2N/A * negend). If so, just return failure. 2N/A * The device has been closed due to a contract offline 2N/A * request, then we need to reopen it and create a new contract. 2N/A * If we find ourselves in this situation, we're in 2N/A * trouble. The generation count has changed, which 2N/A * indicates that our current topology is out of date. 2N/A * But we need to consult the new topology in order to 2N/A * determine presence at this moment in time. We can't 2N/A * go back and change the topo snapshot in situ, so 2N/A * we'll just have to fail the call in this unlikely 2N/A * Determine if the element is present. 2N/A * No serial number support yet - so just check if somerthing is there. 2N/A * Sets standard properties for a ses node (enclosure, bay, controller 2N/A * This includes setting the FRU, as well as setting the 2N/A * authority information. When the fru topo node(frutn) is not NULL 2N/A * its resouce should be used as FRU. 2N/A * Set the authority explicitly if specified. 2N/A * Copy the resource and set that as the FRU. 2N/A "topo_node_resource() failed : %s\n",
2N/A "topo_node_resource() failed : %s\n",
2N/A "topo_node_fru_set() failed : %s\n",
2N/A * Set the SES-specific properties so that consumers can query 2N/A * additional information about the particular SES element. 2N/A "failed to create property %s: %s\n",
2N/A "failed to create property %s: %s\n",
2N/A * Callback to add a disk to a given bay. We first check the status-code to 2N/A * determine if a disk is present, ignoring those that aren't in an appropriate 2N/A * state. We then scan the parent bay node's SAS address array to determine 2N/A * possible attached SAS addresses. We create a disk node if the disk is not 2N/A * SAS or the SES target does not support the necessary pages for this; if we 2N/A * find the SAS address, we create a disk node and also correlate it with 2N/A * the corresponding Solaris device node to fill in the rest of the data. 2N/A * Skip devices that are not in a present (and possibly damaged) state. 2N/A * When the bay element status indicate the occupant is not there 2N/A * set the disk binding type to empty and the failback method to none. 2N/A * If SAS address which represents a target port is not found 2N/A * consider it is an empty bay. 2N/A * Note that TOPO_PROP_SAS_ADDR prop includes SAS address from 2N/A * alternate elements that represent the same device. 2N/A /* set to 0 for handling exit with an error. */ 2N/A /* Set occupant presence property. */ 2N/A * If target ports prop is avaiablle set the binding method and 2N/A * occupant target port properties. When the props not set 2N/A * it is considered to an empty bay enumeration and the disk enumerator 2N/A * should handle the case. 2N/A "failed to set binding method: %s\n",
2N/A "failed to set target ports property: " 2N/A * Create the disk range. 2N/A * Call the disk enumerator to create a disk node under the given bay. 2N/A /* copy sas_addresses (target-ports) from parent (with 'w'added) */ 2N/A /* There should be a single child disk node if exists. */ 2N/A * It is okay not to have a child disk node. 2N/A * For example the bay may be empty and the disk 2N/A * enumerator may or may not create a disk node. 2N/A "failed to locate the child disk node\n");
2N/A /* if they all worked then create the property */ 2N/A * Create facility management mode for the given topo node. 2N/A * For the SAS elements inside an internal enclosure 2N/A * no facility management needs to be checked. 2N/A * No sensors for the BAY node. The occupant disk has 2N/A * temperature sensor that is read by the disk transport 2N/A * through the log sense command. The BAY service LED is 2N/A * managed by the host FMA so no facility management 2N/A * properties need to be specified. 2N/A * Following areas are checked for LED facility management. 2N/A * 1. When there exists a FRU element that self-manages the service 2N/A * LED within such enclosure like PSU the corresponding SES element 2N/A * node should report LIBSES_PROP_SVCLED_SELF_MANAGED. 2N/A * 2. parent node reports TOPO_FACMGMT_SVCLED_SELF_MANAGED prop. 2N/A * The child node inherits the parent node setting for the 2N/A * TOPO_FACMGMT_SVCLED_SELF_MANAGED prop. 2N/A * This will avoid parsing the ancestor nodes by the reponse agent 2N/A * like the fru monitor to check the setting for the service LED 2N/A * 3. for an enclosure, check if it is externally managed like 2N/A * Genesis and Jurojin. If not, inidcate that the enclosure is 2N/A * self-managed by setting TOPO_FACMGMT_SVCLED_SELF_MANAGED 2N/A * proerpty. Its child nodes will inherit the property as 2N/A * When the TOPO_FACMGMT_SVCLED_SELF_MANAGED prop doesn't exist 2N/A * the associated service LED for the topo node is considered to be 2N/A * Check the enclosure for LIBSES_PROP_FAULT_EXT_MANAGED 2N/A * property. If it is not externally managed or the prop 2N/A * doesn't exist, the service LED should be self managed. 2N/A * Following areas may need to be checked for SENSOR facility 2N/A * 1. the enclosure self reports out-of-range error for all 2N/A * sensors then no need to set the property for the individual 2N/A * 2. When the enclosure self-reports sensors for a subset of its 2N/A * components so the sec_self_report flag can not be set for the 2N/A * enclosure another property like 2N/A * "libses-elem-sensor-self-reported" needs to be reported 2N/A * through libses discovery to indicate that an individual 2N/A * SES element has its sensors self-reported. 2N/A * Currently no enclosure with behavie #2 so we just handle 2N/A * enclosure level self-reporting. 2N/A /* create the facility management property group. */ 2N/A /* create the service led self managed property. */ 2N/A "management property %s: %s\n",
2N/A /* create the enclosure sensor self reported property. */ 2N/A "management property %s: %s\n",
2N/A * Callback to create a basic node (bay, psu, fan, or controller and expander). 2N/A * Each SIM on a JBOD does not report the peer SIMs fruprom, and for 2N/A * this reason, we can't just trust the information from one ses traget 2N/A * for the fru information for CONTROLLER nodes. The sen_alt_nodes 2N/A * contains the list of all ses nodes that match this nodes' 2N/A * target should report the correct information. 2N/A * Create the node. The interesting information is all copied from the 2N/A * parent enclosure node, so there is not much to do. 2N/A * We want to report revision information for the controller nodes, but 2N/A * we do not get per-element revision information. However, we do have 2N/A * revision information for the entire enclosure, and we can use the 2N/A * 'reported-via' property to know that this controller corresponds to 2N/A * the given revision information. This means we cannot get revision 2N/A * information for targets we are not explicitly connected to, but 2N/A * there is little we can do about the situation. 2N/A * Some enclosure like Genesis can have multiple 2N/A * SAS exapnders (with SES and SMP services) 2N/A * associated with a single controller. 2N/A * The revison of each SAS expander may be different 2N/A * since a firmware is downloaded on them separately. 2N/A * Here we capture the revision info of an individual 2N/A * exapander from an smp node firmware revison property 2N/A * which is acquired through devinfo snapshot. 2N/A /* search matching ses_di_node. */ 2N/A "SAS Expander (%s) rev %s",
2N/A * For the node label, we look for the following in order: 2N/A * <ses-class-description> <instance> 2N/A * <default-type-label> <instance> 2N/A * We are adding reported target path using the report bit 2N/A * from SES Enclosure Status page. The SES-2 spec defines 2N/A * the report bit for the Device Slot, SCSI Ports and 2N/A * ESC electronics(controller) element. 2N/A * We care about the controller element to help 2N/A * match the controller label with host device information 2N/A * including SAS address. 2N/A * For SAS enclosure that provides SES Additional Element Status(AES) 2N/A * data for SAS exapander under the controller the SAS expander 2N/A * properties shows the host device information but we need to 2N/A * deal with the case that either no SAS expander element is not 2N/A * supported or SES AES data is not available. 2N/A * Check all alternate nodes and collect the device path 2N/A * of an enclosure target that indicated it manages the 2N/A * controlleri through the report bit. 2N/A * Found an alternate node with report bit set. 2N/A * Note that the string array is used to capture 2N/A * reported target path since there may be multiple 2N/A * enclosure targets in a controller. 2N/A "Reported target path(index %d): %s.", i,
2N/A * There should be at least one reported target for 2N/A * the controller. In oder to avoid termination 2N/A * due to missing reported target we create the prop 2N/A * only when the reported target exists. 2N/A * When no reported target prop exists on the topo 2N/A * controller node it should be considered as an error. 2N/A "failed to create property %s: %s\n",
2N/A "topo_method_register() failed: %s",
2N/A * Only fan, psu, and controller nodes have a 'present' method. 2N/A * Bay nodes are always present, and disk nodes are present by 2N/A * virtue of being enumerated and SAS expander nodes and 2N/A * SAS connector nodes are also always present once 2N/A * the parent controller is found. 2N/A "topo_method_register() failed: %s",
2N/A /* check the facility mangement setting. */ 2N/A * Create SAS expander specific props. 2N/A * the uninstalled expander is not enumerated by checking 2N/A * the element status code. No present present' method provided. 2N/A * Get the Expander SAS address. It should exist. 2N/A /* search matching ses_di_node. */ 2N/A "ses_set_expander_props: Failed to find matching " 2N/A "devinfo node for Expander SAS address %s",
2N/A /* continue on to get storage group props. */ 2N/A "failed to create smp property group %s\n",
2N/A "set phys-path error %s\n",
2N/A /* count number of devlinks for this device. */ 2N/A /* construst devlink array. */ 2N/A "set smp devfs-link error %s\n",
2N/A /* update the ses property group with SES target info */ 2N/A /* SES prop group doesn't exist but failed to be created. */ 2N/A /* locate assciated enclosure ses_di_node. */ 2N/A * check if attached port exists and 2N/A * its node type is enclosure and 2N/A * attached port is same as sas address of 2N/A * bridge port for virtual phy indication 2N/A "ses_set_expander_props: Failed to find attached " 2N/A "port for Exapnder SAS address %s",
2N/A "set ses dev error %s\n",
2N/A "set ses devid error %s\n",
2N/A "set ses phys-path error %s\n",
2N/A /* count number of devlinks for this device. */ 2N/A /* construct devlink array. */ 2N/A "set ses devfs-link error %s\n",
2N/A /* create the storage group */ 2N/A /* set the SAS address prop out of expander element status. */ 2N/A /* Get the phy information for the expander */ 2N/A * For each phy, get the connector element index and 2N/A * stores into connector element index array. 2N/A /* Fail to get the index. set to -1. */ 2N/A /* set the phy count prop of the expander. */ 2N/A * set the connector element index of 2N/A * the expander phys. 2N/A /* populate other misc storage group properties */ 2N/A "set serial error %s\n",
2N/A * Create SAS expander specific props. 2N/A * convert phy mask to string. 2N/A /* create the storage group */ 2N/A /* set the SAS address prop of the expander. */ 2N/A /* Get the connector type information for the expander */ 2N/A for (i = 0; ; i++) {
2N/A /* set the phy count prop of the expander. */ 2N/A * Instantiate SAS expander nodes for a given ESC Electronics node(controller) 2N/A * For SES constroller node, check to see if there are 2N/A * associated SAS expanders. 2N/A * No SAS expander found notthing to process. 2N/A * The max number represent the number of elements 2N/A * deducted from the highest SES_PROP_ELEMENT_CLASS_INDEX 2N/A * of SET_ET_SAS_EXPANDER type element. 2N/A * There may be multiple ESC Electronics element(controllers) 2N/A * within JBOD(typicall two for redundancy) and SAS expander 2N/A * elements are associated with only one of them. We are 2N/A * still creating the range based max number here. 2N/A * That will cover the case that all expanders are associated 2N/A * with one SES controller. 2N/A "topo_node_create_range() failed: %s",
2N/A * Search exapnders with the parent index matching with 2N/A * ESC Electronics element index. 2N/A * Note the index used here is a global index across 2N/A * get the parent ESC controller. 2N/A * Don't create a ndoe. 2N/A * The element should have status code. 2N/A * If not there is no way to find 2N/A * out if the expander element exist or 2N/A /* Get the physical parent index to compare. */ 2N/A /* indentation moved forward */ 2N/A * Handle basic node information of SAS expander 2N/A * element - binding to parent node and 2N/A * allocating FMRI... 2N/A * Now handle SAS expander unique portion of node creation. 2N/A * The max nubmer of the phy count is 256 since SES-2 2N/A * defines as 1 byte field. The cidxlist has the same 2N/A * number of elements. 2N/A * We use size 64 array to store the connectors. 2N/A * Typically a connectors associated with 4 phys so that 2N/A * matches with the max number of connecters associated 2N/A * The phy count goes up to 38 for Sun supported 2N/A * error on getting specific prop failed. 2N/A * continue on. Note that the node is 2N/A * count represetns the number of connectors discovered so far. 2N/A /* connector index is valid. */ 2N/A * Just update phy mask. 2N/A * The postion for connector 2N/A * index lists(cidxlist index) 2N/A * If j and count matche a new connector 2N/A /* add a new index and phy mask. */ 2N/A * create range for the connector nodes. 2N/A * The class index of the ses connector element 2N/A * is set as the instance nubmer for the node. 2N/A * Even though one expander may not have all connectors 2N/A * are associated with we are creating the range with 2N/A * max possible instance number. 2N/A * No SAS connector found nothing to process. 2N/A "topo_node_create_range() failed: %s",
2N/A /* search matching connector element using the index. */ 2N/A * Get the physical parent index to 2N/A * The connector elements are children 2N/A * of ESC Electronics element even 2N/A * though we enumerate them under 2N/A * an expander in libtopo. 2N/A /* now create a libtopo node. */ 2N/A /* Create generic props. */ 2N/A /* Create connector specific props. */ 2N/A /* end indentation change */ 2N/A * Instantiate any protocol specific portion of a node. 2N/A /* create SAS specific children(expanders and connectors. */ 2N/A * Instantiate any children of a given type. 2N/A * First go through and count how many matching nodes we have. 2N/A * No enclosure should export both DEVICE and ARRAY_DEVICE elements. 2N/A * Since we map both of these to 'disk', if an enclosure does this, we 2N/A * just ignore the array elements. 2N/A "topo_node_create_range() failed: %s",
2N/A * With flat layout of ses nodes there is no 2N/A * way to find out the direct FRU for a node. 2N/A * Passing NULL for fru topo node. Note that 2N/A * ses_create_children_from_phys_tree() provides 2N/A * the actual direct FRU for a node. 2N/A * For some SES element there may be protocol specific 2N/A * information to process. Here we are processing 2N/A * the association between enclosure controller and 2N/A /* create SAS expander node */ 2N/A * Instantiate a new subchassis instance in the topology. 2N/A * Copy authority information from parent enclosure node 2N/A * Record the subchassis serial number in the FMRI. 2N/A * For now, we assume that logical id is the subchassis serial number. 2N/A * If this assumption changes in future, then the following 2N/A * piece of code will need to be updated via an RFE. 2N/A * Look for the subchassis label in the following order: 2N/A * <ses-class-description> <instance> 2N/A * <default-type-label> <instance> 2N/A * For subchassis, the default label is "SUBCHASSIS" 2N/A * Set the 'chassis-type' property for this subchassis. This is either 2N/A * 'ses-class-description' or 'subchassis'. 2N/A * For enclosures, we want to include all possible targets (for upgrade 2N/A * Create the nodes for controllers and bays. 2N/A * Function we use to insert a node. 2N/A * If the element only index of the root is same as the physical 2N/A * parent index of a node to be added, add the node as a child of 2N/A * if the physical parent of the current root and the child 2N/A * is same, then this should be a sibling node. 2N/A * Siblings can be different element types and arrange 2N/A /* add a node in front of matching element type. */ 2N/A /* no matching. Add the child at the end. */ 2N/A * The root and the node is not directly related. 2N/A * Try to insert to the child sub-tree first and then try to 2N/A * insert to the sibling sub-trees. If fails for both 2N/A * the caller will retry insertion later. 2N/A * Construct tree view of ses elements through parent phyiscal element index. 2N/A * The root of tree is already constructed using the enclosure element. 2N/A "failed to allocate root.");
2N/A * the prop should exist. continue to see if 2N/A * we can build a partial tree with other elements. 2N/A "ses_construct_phys_tree(): Failed to find prop %s " 2N/A "on ses element type %llu and instance %llu " 2N/A "ses_construct_phys_tree(): Failed to " 2N/A "find prop %s on ses element type %llu " 2N/A "and instance %llu (CSN %s).",
2N/A * Ignore if the prop doesn't exist. 2N/A * Note that the enclosure itself should be 2N/A * a FRU so if no FRU found the enclosure FRU 2N/A * can be a direct FRU. 2N/A /* collect unresolved element to process later. */ 2N/A * The parent of a child node may not be inserted yet. 2N/A * Trying to insert the child until no child is left or 2N/A * no child is not added further. For the latter 2N/A * the hierarchical relationship between elements 2N/A * should be checked through SUNW,FRUID page. 2N/A * u_watch is a watch dog to check the prgress of unresolved 2N/A * We just scanned one round for the 2N/A * unresolved list. Check to see whether we 2N/A * have nodes inserted, if none, we should 2N/A * break in case of an indefinite loop. 2N/A * Indicate there is unhandled node. 2N/A * Chain free the whole unsolved 2N/A * We just inserted one rpnode, increment the 2N/A * unsolved_inserted counter. We will utilize this 2N/A * counter to detect an indefinite insertion loop. 2N/A * watch dog node itself is inserted. 2N/A * Set it to the tail and refresh the watching. 2N/A /* check if there is left out unresolved nodes. */ 2N/A "Failed to construct physical view of the following " 2N/A "ses elements of Chassis (CSN %s).",
2N/A "\telement type (%llu) and instance (%llu)",
2N/A * Free the whole phys tree. 2N/A /* Free child tree. */ 2N/A /* Free sibling trees. */ 2N/A /* Free root node itself. */ 2N/A * Parses phys_enum_type table to get the index of the given type. 2N/A * Recusrive routine for top-down enumeration of the tree. 2N/A /* check if range needs to be created. */ 2N/A "topo_node_create_range() failed: " 2N/A /* found direct FRU node. */ 2N/A * For some SES element there may be protocol specific 2N/A * information to process. Here we are processing 2N/A * the association between enclosure controller and 2N/A /* create SAS expander node */ 2N/A * Instantiate types of nodes that are specified in the hierarchy 2N/A * element type list. 2N/A * First get max range for each type of element to be enumerated. 2N/A "ses_create_children_from_phys_tree() failed: ");
2N/A * check whether FM_IOC_GENTOPO_LEGACY is set or not. 2N/A * return value: 0 if is set. 2N/A * -1 if fail to check or it is not set. 2N/A /* set up buffers and ioctl data structure */ 2N/A /* send the ioctl to /dev/fm to retrieve legacy variable */ 2N/A /* legacy kernel variable not set. */ 2N/A * Instantiate internal expander attached drives in the topology. 2N/A * input chassis should represent an internal enclosure. 2N/A * For some platforms both direct attached and expander attached 2N/A * drives may exist and the instance number can be coordinated 2N/A * through max_internal_inst var. 2N/A * Now enumeratate the bays within the internal enclosure. 2N/A * For x86, verifiy the x86gentopo_legacy should be turned off. 2N/A * When legacy flag is set it is expected that disk map 2N/A * file for internal disk enumeration is provided. 2N/A * Note that direct attached internal disks are not 2N/A * handled here. Those disks are supposed to be handled by x86 gentopo 2N/A * through SMBIOS type 7 OEM record. 2N/A "within the internal enclosure.",
2N/A "nodes of an expander attached internal " 2N/A "topo_node_create_range() failed: " 2N/A "Internal bay elemnet " 2N/A "creation failed.");
2N/A "nodes of an expander attached internal " 2N/A * Manufacturing strings can contain characters that are invalid for use in hc 2N/A * authority names. This trims leading and trailing whitespace, and 2N/A * substitutes any characters known to be bad. 2N/A * Instantiate a new chassis instance in the topology. 2N/A * For an internal chassis, no chassis is created. 2N/A * An SAS expander element is enumerated. 2N/A * as a child of the platform chassis to represent 2N/A * internal expander. 2N/A * Count the nubmer of expanders in the internal enclosure. 2N/A " an internal SAS expander element",
2N/A "topo_node_create_range() failed: %s",
2N/A * Passing NULL for the fru node if the 2N/A * internal enclosure is a FRU so the 2N/A * SAS expander element itself will be 2N/A * reported as a FRU. 2N/A * Othewise set the parent(chassis) 2N/A "Internal SAS expander " 2N/A "elemnet creation failed.");
2N/A * Check to see if there are any devices presennt in the chassis. If 2N/A * not, ignore the chassis alltogether. This is most useful for 2N/A * ignoring internal HBAs that present a SES target but don't actually 2N/A * manage any of the devices. 2N/A * We use the following property mappings: 2N/A * manufacturer vendor-id 2N/A * serial-number libses-chassis-serial 2N/A * part-number libses-part-number 2N/A * The libses-part-number comes from the decoded FRUPROM and so will 2N/A * only be available on Sun/Oracle storage arrays, so we still want to 2N/A * enumerate the ses-enclosure node, even if this property isn't 2N/A * To construct the authority information, we 'clean' each string by 2N/A * removing any offensive characters and trimmming whitespace. For the 2N/A * 'product-id', we use a concatenation of 'manufacturer-model'. We 2N/A * also take the numerical serial number and convert it to a string. 2N/A * Construct the topo node and bind it to our parent. 2N/A * We pass NULL for the parent FMRI because there is no resource 2N/A * associated with it. For the toplevel enclosure, we leave the 2N/A * individual components within the chassis. 2N/A "topo_method_register() failed: %s",
2N/A * For enclosures, we want to include all possible targets (for upgrade 2N/A "failed to create property %s: %s\n",
2N/A * The enclosure is supported through SUNW,FRUID. 2N/A * Need to enumerate the nodes through hierarchical order. 2N/A "failed to allocate root: %s\n",
2N/A "ses_create_chassis(): Failed to find prop %s " 2N/A "on enclosure element (CSN %s).",
2N/A /* an enclosure should be a FRU. continue to process. */ 2N/A "ses_create_chassis(): Failed to find prop %s " 2N/A "on enclosure element (CSN %s).",
2N/A "Enclosure element(CSN %s) should have " 2N/A "itself as the parent to be the root node " 2N/A /* construct a tree. */ 2N/A "Failed to construct FRU hierarchical " 2N/A "tree on enclosure (CSN %s.)",
2N/A /* enumerate elements from the tree. */ 2N/A "Failed to create children topo nodes out " 2N/A "of FRU hierarchical tree on enclosure " 2N/A /* destroy the phys tree. */ 2N/A "FRU boundary tree based enumeration: %.6f seconds",
2N/A * Create the nodes for power supplies, fans, controllers and 2N/A * devices. Note that SAS exopander nodes and connector nodes 2N/A * are handled through protocol specific processing of 2N/A "instance %u\nand target (%s) under Chassis with CSN %s",
2N/A * Create a bay node explicitly enumerated via XML. 2N/A * Iterate over chassis looking for an internal enclosure. This 2N/A * property is set via a vendor-specific plugin, and there should only 2N/A * ever be a single internal chassis in a system. 2N/A * Initialize chassis or subchassis. 2N/A "FRU(%s), externally managed(%s), sensor self report(%s)",
2N/A * Gather nodes from the current SES target into our chassis list, merging the 2N/A * results if necessary. 2N/A * If we have already identified the chassis for this target, 2N/A * then this is a secondary enclosure and we should ignore it, 2N/A * along with the rest of the tree (since this is depth-first). 2N/A * Go through the list of chassis we have seen so far and see 2N/A * if this serial number matches one of the known values. 2N/A * If so, check whether this enclosure is a subchassis. 2N/A * We need to determine whether this enclosure node 2N/A * represents a chassis or a subchassis. Since we may 2N/A * receive the enclosure nodes in a non-deterministic 2N/A * manner, we need to account for all possible combinations: 2N/A * 1. Chassis for the current CSN has not yet been 2N/A * 1.1 This is a new chassis: 2N/A * allocate and instantiate the chassis 2N/A * 1.2 This is a new subchassis: 2N/A * allocate a placeholder chassis 2N/A * allocate and instantiate the subchassis 2N/A * link the subchassis to the chassis 2N/A * 2. Chassis for the current CSN has been allocated 2N/A * 2.1 This is a duplicate chassis enclosure 2N/A * check whether to override old chassis 2N/A * append to chassis' target list 2N/A * 2.2 Only placeholder chassis exists 2N/A * fill in the chassis fields 2N/A * 2.3 This is a new subchassis 2N/A * allocate and instantiate the subchassis 2N/A * link the subchassis to the chassis 2N/A * 2.4 This is a duplicate subchassis enclosure 2N/A * check whether to override old chassis 2N/A * append to chassis' target list 2N/A /* 1. Haven't seen a chassis with this CSN before */ 2N/A /* 1.1 This is a new chassis */ 2N/A /* 1.2 This is a new subchassis */ 2N/A "subchassis with CSN %s and index %llu",
2N/A * We have a chassis or subchassis with this CSN. If 2N/A * it's a chassis, we must check to see whether it is 2N/A * a placeholder previously created because we found a 2N/A * subchassis with this CSN. We will know that because 2N/A * the sec_target value will not be set; it is set only 2N/A * in ses_init_chassis(). In that case, initialise it 2N/A * as a new chassis; otherwise, it's a duplicate and we 2N/A * need to append only. 2N/A /* 2.1 This is a duplicate chassis */ 2N/A "duplicate chassis with CSN (%s)",
2N/A /* Placeholder chassis - init it up */ 2N/A "placeholder chassis with CSN %s",
2N/A /* This is a subchassis */ 2N/A /* 2.3 This is a new subchassis */ 2N/A "new subchassis with CSN (%s) " 2N/A /* 2.4 This is a duplicate subchassis */ 2N/A "duplicate subchassis with " 2N/A * If we haven't yet seen an enclosure node and identified the 2N/A * current chassis, something is very wrong; bail out. 2N/A * If this isn't one of the element types we care about, then 2N/A * Get the current instance number and see if we already know 2N/A * about this element. If so, it means we have multiple paths 2N/A * to the same elements, and we should ignore the current path. 2N/A * We prefer the new element under the following circumstances: 2N/A * - The currently known element's status is unknown or not 2N/A * available, but the new element has a known status. This 2N/A * occurs if a given element is only available through a 2N/A * particular target. 2N/A "target(%s) node(type %llu, instance %llu) " 2N/A "status(current: %llu previous: %llu)",
2N/A "replacing the current topo node");
2N/A * Open the SES target directory and iterate over any available 2N/A * If the SES target directory does not exist, then return as if 2N/A * there are no active targets. 2N/A * Create a new target instance and take a snapshot. 2N/A * We keep track of the SES device path and export it on a 2N/A * per-node basis to allow higher level software to get to the 2N/A * corresponding SES state. 2N/A * Enumerate over all SES elements and merge them into the 2N/A * correct ses_enum_chassis_t. 2N/A * Check to make sure we're being invoked sensibly, and that we're not 2N/A * being invoked as part of a post-processing step. 2N/A * If this is the first time we've called our enumeration method, then 2N/A * gather information about any available enclosures. 2N/A * We search both the ses(7D) and sgen(7D) locations, so we are 2N/A * independent of any particular driver class bindings. 2N/A * This is a request to enumerate enclosures. Go 2N/A * through all the targets and create chassis nodes where 2N/A * necessary for an external enclosure. For an internal 2N/A * enclosure no chassis is created since the platform chassis 2N/A * itself is considered to be the chassis for internal SES 2N/A * reqdata can be passed to get max instance 2N/A * number used for expander attached internal 2N/A * It is a kludge but can avoid overhead 2N/A * to parse topo just to get the max instance 2N/A * of previously enumerated bays for 2N/A * coordinating instance nubmer for any other 2N/A * bays under chassis. 2N/A * This is a request to enumerate a specific bay underneath the 2N/A * root chassis (for internal disks). 2N/A * This is a bit of a kludge. In order to allow internal disks to be 2N/A * enumerated and share snapshot-specific information with the external 2N/A * enclosure enumeration, we rely on the fact that we will be invoked 2N/A * for the 'ses-enclosure' node last.