1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (c) 2017, Joyent, Inc. 14 */ 15 16 #include <sys/fm/protocol.h> 17 #include <fm/topo_mod.h> 18 #include <fm/topo_list.h> 19 #include <fm/topo_method.h> 20 21 /* 22 * Common routines to create transceiver entries in the topology tree. 23 */ 24 25 static const topo_pgroup_info_t transceiver_pgroup = { 26 TOPO_PGROUP_TRANSCEIVER, 27 TOPO_STABILITY_PRIVATE, 28 TOPO_STABILITY_PRIVATE, 29 1 30 }; 31 32 static const topo_pgroup_info_t sff_transceiver_pgroup = { 33 TOPO_PGROUP_SFF_TRANSCEIVER, 34 TOPO_STABILITY_PRIVATE, 35 TOPO_STABILITY_PRIVATE, 36 1 37 }; 38 39 int 40 transceiver_range_create(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min, 41 topo_instance_t max) 42 { 43 return (topo_node_range_create(mod, pnode, TRANSCEIVER, min, max)); 44 } 45 46 static tnode_t * 47 transceiver_create_common(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 48 const char *type, boolean_t usable, const char *part, const char *rev, 49 const char *serial) 50 { 51 int err; 52 tnode_t *tn = NULL; 53 nvlist_t *fmri = NULL, *auth = NULL; 54 55 if (type == NULL) { 56 topo_mod_dprintf(mod, "transceiver_create_common missing type " 57 "argument"); 58 goto error; 59 } 60 61 if ((auth = topo_mod_auth(mod, pnode)) == NULL) { 62 topo_mod_dprintf(mod, "topo_mod_auth() failed: %s\n", 63 topo_mod_errmsg(mod)); 64 goto error; 65 } 66 67 if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, 68 TRANSCEIVER, inst, NULL, auth, part, rev, serial)) == NULL) { 69 topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s\n", 70 topo_mod_errmsg(mod)); 71 goto error; 72 } 73 74 if ((tn = topo_node_bind(mod, pnode, TRANSCEIVER, inst, fmri)) == 75 NULL) { 76 topo_mod_dprintf(mod, "topo_node_bind() failed: %s\n", 77 topo_mod_errmsg(mod)); 78 goto error; 79 } 80 81 /* 82 * The FRU for a transceiver is always itself. 83 */ 84 if (topo_node_fru_set(tn, fmri, 0, &err) != 0) { 85 topo_mod_dprintf(mod, "topo_node_fru_set() failed: %s\n", 86 topo_strerror(err)); 87 goto error; 88 } 89 90 if (topo_pgroup_create(tn, &transceiver_pgroup, &err) != 0) { 91 topo_mod_dprintf(mod, "failed to create property group %s: " 92 "%s\n", TOPO_PGROUP_TRANSCEIVER, topo_strerror(err)); 93 goto error; 94 } 95 96 if (topo_prop_set_string(tn, TOPO_PGROUP_TRANSCEIVER, 97 TOPO_PROP_TRANSCEIVER_TYPE, TOPO_PROP_IMMUTABLE, type, 98 &err) != 0) { 99 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 100 TOPO_PROP_TRANSCEIVER_TYPE, topo_strerror(err)); 101 goto error; 102 } 103 104 if (topo_prop_set_string(tn, TOPO_PGROUP_TRANSCEIVER, 105 TOPO_PROP_TRANSCEIVER_USABLE, TOPO_PROP_IMMUTABLE, 106 usable ? "true" : "false", &err) != 0) { 107 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 108 TOPO_PROP_TRANSCEIVER_USABLE, topo_strerror(err)); 109 goto error; 110 } 111 112 nvlist_free(fmri); 113 nvlist_free(auth); 114 return (tn); 115 116 error: 117 topo_node_unbind(tn); 118 nvlist_free(fmri); 119 nvlist_free(auth); 120 return (NULL); 121 } 122 123 int 124 transceiver_create_sff(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 125 boolean_t useable, const char *vendor, const char *part, const char *rev, 126 const char *serial, tnode_t **nodep) 127 { 128 int err; 129 tnode_t *tn = NULL; 130 131 if ((tn = transceiver_create_common(mod, pnode, inst, 132 TOPO_PROP_PORT_TYPE_SFF, useable, part, rev, serial)) == NULL) { 133 return (-1); 134 } 135 136 /* 137 * Always create the SFF property group, even if we can't fill in any 138 * properties. 139 */ 140 if (topo_pgroup_create(tn, &sff_transceiver_pgroup, &err) != 0) { 141 topo_mod_dprintf(mod, "failed to create property group %s: " 142 "%s\n", TOPO_PGROUP_SFF_TRANSCEIVER, topo_strerror(err)); 143 goto error; 144 } 145 146 if (vendor != NULL && topo_prop_set_string(tn, 147 TOPO_PGROUP_SFF_TRANSCEIVER, TOPO_PORT_SFF_TRANSCEIVER_VENDOR, 148 TOPO_PROP_IMMUTABLE, vendor, &err) != 0) { 149 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 150 TOPO_PORT_SFF_TRANSCEIVER_VENDOR, topo_strerror(err)); 151 goto error; 152 } 153 154 if (part != NULL && topo_prop_set_string(tn, 155 TOPO_PGROUP_SFF_TRANSCEIVER, TOPO_PORT_SFF_TRANSCEIVER_PN, 156 TOPO_PROP_IMMUTABLE, part, &err) != 0) { 157 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 158 TOPO_PORT_SFF_TRANSCEIVER_PN, topo_strerror(err)); 159 goto error; 160 } 161 162 if (rev != NULL && topo_prop_set_string(tn, 163 TOPO_PGROUP_SFF_TRANSCEIVER, TOPO_PORT_SFF_TRANSCEIVER_REV, 164 TOPO_PROP_IMMUTABLE, rev, &err) != 0) { 165 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 166 TOPO_PORT_SFF_TRANSCEIVER_REV, topo_strerror(err)); 167 goto error; 168 } 169 170 if (serial != NULL && topo_prop_set_string(tn, 171 TOPO_PGROUP_SFF_TRANSCEIVER, TOPO_PORT_SFF_TRANSCEIVER_SN, 172 TOPO_PROP_IMMUTABLE, serial, &err) != 0) { 173 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 174 TOPO_PORT_SFF_TRANSCEIVER_SN, topo_strerror(err)); 175 goto error; 176 } 177 178 if (nodep != NULL) 179 *nodep = tn; 180 return (0); 181 182 error: 183 topo_node_unbind(tn); 184 return (-1); 185 } 186