17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <stropts.h>
21 #include <string.h>
22 #include <strings.h>
23
24 #include <fm/topo_mod.h>
25 #include <fm/topo_list.h>
26
27 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
28 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
29 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
30 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
31
32 #include "disk.h"
33 #include "disk_drivers.h"
34
35 /*
36 * Request the SAS address of the disk (if any) attached to this mpt_sas
37 * instance at (Enclosure Number, Slot Number).
38 *
39 * Returns:
40 * -2 /devices node (*devctl) does not exist
41 * -1 All other failures
42 * 0 Success
43 */
44 static int
45 get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
46 uint32_t slot, char **sas_address)
47 {
48 int fd, err, i;
49 mptsas_get_disk_info_t gdi;
50 mptsas_disk_info_t *di;
51 size_t disz;
52
53 bzero(&gdi, sizeof (gdi));
54
55 if ((fd = open(devctl, O_RDWR)) == -1) {
56 int rc = (errno == ENOENT ? -2 : -1);
57 topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n",
58 devctl, strerror(errno));
59 return (rc);
60 }
61
62 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
63 topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl,
64 strerror(errno));
65 (void) close(fd);
66 return (-1);
67 }
68
69 gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) *
70 gdi.DiskCount;
71 gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz);
72 if (di == NULL) {
73 topo_mod_dprintf(mod, "memory allocation failed\n");
74 (void) close(fd);
75 return (-1);
76 }
77
78 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
79 topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl,
80 strerror(errno));
81 topo_mod_free(mod, di, disz);
82 (void) close(fd);
83 return (-1);
84 }
85
86 err = -1;
87 for (i = 0; i < gdi.DiskCount; i++) {
88 if (di[i].Enclosure == enclosure && di[i].Slot == slot) {
89 char sas[17]; /* 16 hex digits and NUL */
90 (void) snprintf(sas, 17, "%llx", di[i].SasAddress);
91 topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) "
92 "with adddress %s\n", enclosure, slot, sas);
93 *sas_address = topo_mod_strdup(mod, sas);
94 err = 0;
95 break;
96 }
97 }
98
99 topo_mod_free(mod, di, disz);
100 (void) close(fd);
101 return (err);
102 }
103
104 int
105 disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address)
106 {
107 char *devctl = NULL;
108 uint32_t enclosure, slot;
109 int err;
110 char *elem, *lastp;
111 int ret = -1;
112
113 /*
114 * Get the required properties from the node. These come from
115 * the static XML mapping.
116 */
117 if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING,
118 TOPO_BINDING_DEVCTL, &devctl, &err) != 0 ||
119 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING,
120 TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 ||
121 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING,
122 TOPO_BINDING_SLOT, &slot, &err) != 0) {
123 if (devctl != NULL)
124 topo_mod_strfree(mod, devctl);
125 topo_mod_dprintf(mod, "bay node was missing mpt_sas binding "
126 "properties\n");
127 return (-1);
128 }
129
130 /*
131 * devctl is a (potentially) pipe-separated list of different device
132 * paths to try.
133 */
134 if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) != NULL) {
135 do {
136 topo_mod_dprintf(mod, "trying mpt_sas instance at %s\n",
137 elem);
138
139 ret = get_sas_address(mod, elem, enclosure,
140 slot, sas_address);
141
142 topo_mod_strfree(mod, elem);
143
144 /*
145 * Only try further devctl paths from the list if this
146 * one was not found:
147 */
148 if (ret != -2) {
149 break;
150 } else {
151 topo_mod_dprintf(mod, "instance not found\n");
152 }
153
154 } while ((elem = topo_mod_strsplit(mod, NULL, "|",
155 &lastp)) != NULL);
156 }
157
158 topo_mod_strfree(mod, devctl);
159 return (ret);
160 }
|
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <stropts.h>
21 #include <string.h>
22 #include <strings.h>
23
24 #include <fm/topo_mod.h>
25 #include <fm/topo_list.h>
26
27 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
28 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
29 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
30 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
31
32 #include "disk.h"
33 #include "disk_drivers.h"
34
35 /*
36 * Request the SAS address of the disk (if any) attached to this mpt_sas
37 * instance at (Enclosure Number, Slot Number). The function returns
38 * -1 on error and sets errno to ENOENT _only_ if the /devices node
39 * (*devctl) does not exist.
40 */
41 static int
42 get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure,
43 uint32_t slot, char **sas_address)
44 {
45 int ret = -1, en = ENXIO;
46 int fd, i;
47 mptsas_get_disk_info_t gdi;
48 mptsas_disk_info_t *di;
49 size_t disz;
50
51 bzero(&gdi, sizeof (gdi));
52
53 if ((fd = open(devctl, O_RDWR)) == -1) {
54 en = errno;
55 topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n",
56 devctl, strerror(errno));
57 errno = en;
58 return (-1);
59 }
60
61 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
62 if (errno != ENOENT)
63 en = errno;
64 topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl,
65 strerror(errno));
66 goto out;
67 }
68
69 gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) *
70 gdi.DiskCount;
71 gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz);
72 if (di == NULL) {
73 topo_mod_dprintf(mod, "memory allocation failed\n");
74 en = ENOMEM;
75 goto out;
76 }
77
78 if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) {
79 if (errno != ENOENT)
80 en = errno;
81 topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl,
82 strerror(errno));
83 topo_mod_free(mod, di, disz);
84 goto out;
85 }
86
87 for (i = 0; i < gdi.DiskCount; i++) {
88 if (di[i].Enclosure == enclosure && di[i].Slot == slot) {
89 char sas[17]; /* 16 hex digits and NUL */
90 (void) snprintf(sas, 17, "%llx", di[i].SasAddress);
91 topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) "
92 "with adddress %s\n", enclosure, slot, sas);
93 *sas_address = topo_mod_strdup(mod, sas);
94 en = ret = 0;
95 break;
96 }
97 }
98
99 topo_mod_free(mod, di, disz);
100 out:
101 (void) close(fd);
102 errno = en;
103 return (ret);
104 }
105
106 int
107 disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address)
108 {
109 char *devctl = NULL;
110 uint32_t enclosure, slot;
111 int err;
112 char *elem, *lastp;
113 int ret = -1;
114
115 /*
116 * Get the required properties from the node. These come from
117 * the static XML mapping.
118 */
119 if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING,
120 TOPO_BINDING_DEVCTL, &devctl, &err) != 0 ||
121 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING,
122 TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 ||
123 topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING,
124 TOPO_BINDING_SLOT, &slot, &err) != 0) {
125 if (devctl != NULL)
126 topo_mod_strfree(mod, devctl);
127 topo_mod_dprintf(mod, "bay node was missing mpt_sas binding "
128 "properties\n");
129 return (-1);
130 }
131
132 /*
133 * devctl is a (potentially) pipe-separated list of different device
134 * paths to try.
135 */
136 if ((elem = topo_mod_strsplit(mod, devctl, "|", &lastp)) != NULL) {
137 boolean_t done = B_FALSE;
138 do {
139 topo_mod_dprintf(mod, "trying mpt_sas instance at %s\n",
140 elem);
141
142 ret = get_sas_address(mod, elem, enclosure,
143 slot, sas_address);
144
145 /*
146 * Only try further devctl paths from the list if this
147 * one was not found:
148 */
149 if (ret == 0 || errno != ENOENT) {
150 done = B_TRUE;
151 } else {
152 topo_mod_dprintf(mod, "instance not found\n");
153 }
154
155 topo_mod_strfree(mod, elem);
156
157 } while (!done && (elem = topo_mod_strsplit(mod, NULL, "|",
158 &lastp)) != NULL);
159 }
160
161 topo_mod_strfree(mod, devctl);
162 return (ret);
163 }
|