129 #define SOL_UVERBS_DRV_STATUS_UNLOADED 0x02 |
90 #define SOL_UVERBS_DRV_STATUS_UNLOADED 0x02 |
130 |
91 |
131 static kstat_ctl_t *kc = NULL; /* libkstat cookie */ |
92 static kstat_ctl_t *kc = NULL; /* libkstat cookie */ |
132 static int sol_uverbs_drv_status = SOL_UVERBS_DRV_STATUS_UNKNOWN; |
93 static int sol_uverbs_drv_status = SOL_UVERBS_DRV_STATUS_UNKNOWN; |
133 static int sol_uverbs_minor_dev = -1; |
94 static int sol_uverbs_minor_dev = -1; |
|
95 |
|
96 /* |
|
97 * Ugly, evil and rest of the names that qualify for it. |
|
98 * This is a side definition for the uverbs hca_info till the |
|
99 * new header file can appear in the userland build environment once that |
|
100 * happens this code will go. |
|
101 */ |
|
102 #if (IB_USER_VERBS_SOLARIS_ABI_VERSION == 2) |
|
103 #undef IB_USER_VERBS_SOLARIS_ABI_VERSION |
|
104 #define IB_USER_VERBS_SOLARIS_ABI_VERSION 3 |
|
105 #define __VERBS_COMPAT_MODE 1 |
|
106 |
|
107 /* |
|
108 * Some useful definitions. |
|
109 */ |
|
110 #define PSID_STR_SZ 40 |
|
111 #define IBDEV_NAME_SZ 64 |
|
112 #define HCA_DRIVER_NAME_SZ 40 |
|
113 #define DEVID_STR_SZ 40 |
|
114 |
|
115 /* |
|
116 * These are duplicate definitions to help the build complete on userland |
|
117 * build machines till the header files are populated with the new versions. |
|
118 * Once the new header file is available in the build system this code will |
|
119 * be removed. |
|
120 */ |
|
121 typedef struct sol_uverbs_hca_infov3_s { |
|
122 char uverbs_hca_psid_string[PSID_STR_SZ]; |
|
123 char uverbs_hca_ibdev_name[IBDEV_NAME_SZ]; |
|
124 char uverbs_hca_driver_name[HCA_DRIVER_NAME_SZ]; |
|
125 uint32_t uverbs_hca_driver_instance; |
|
126 uint32_t uverbs_hca_vendorid; |
|
127 uint16_t uverbs_hca_deviceid; |
|
128 uint16_t uverbs_hca_devidx; |
|
129 int32_t uverbs_hca_abi_version; |
|
130 uint64_t uverbs_hca_fw_ver; |
|
131 uint64_t uverbs_hca_node_guid; |
|
132 uint64_t uverbs_hca_node_external_guid; |
|
133 uint64_t uverbs_hca_sys_image_guid; |
|
134 uint32_t uverbs_hca_hw_version; |
|
135 uint8_t uverbs_hca_pad1[4]; |
|
136 char uverbs_hca_devid_string[DEVID_STR_SZ]; |
|
137 } sol_uverbs_hca_infov3_t; |
|
138 |
|
139 typedef struct sol_uverbs_info_v3_s { |
|
140 int32_t uverbs_abi_version; |
|
141 int32_t uverbs_solaris_abi_version; |
|
142 int16_t uverbs_hca_cnt; |
|
143 int8_t uverbs_pad1[6]; /* Padding for alignment */ |
|
144 sol_uverbs_hca_infov3_t uverbs_hca_info[]; |
|
145 } sol_uverbs_infov3_t; |
|
146 |
|
147 #define SIZEOF_UVERBS_INFO (sizeof (sol_uverbs_infov3_t)) |
|
148 #define SIZEOF_HCA_INFO (sizeof (sol_uverbs_hca_infov3_t)) |
|
149 #define UVERBS_INFO(x) ((sol_uverbs_infov3_t *)x) |
|
150 #define HCA_INFO(x) ((sol_uverbs_hca_infov3_t *)x) |
|
151 |
|
152 #else /* (IB_USER_VERBS_SOLARIS_ABI_VERSION == 3) */ |
|
153 |
|
154 #define SIZEOF_UVERBS_INFO (sizeof (sol_uverbs_info_t)) |
|
155 #define SIZEOF_HCA_INFO (sizeof (sol_uverbs_hca_info_t)) |
|
156 #define UVERBS_INFO(x) ((sol_uverbs_info_t *)x) |
|
157 #define HCA_INFO(x) ((sol_uverbs_hca_info_t *)x) |
|
158 |
|
159 #endif /* END */ |
134 |
160 |
135 /* |
161 /* |
136 * check_path() prefixs |
162 * check_path() prefixs |
137 */ |
163 */ |
138 typedef enum cp_prefix_e { |
164 typedef enum cp_prefix_e { |
139 CP_SOL_UVERBS = 1, |
165 CP_SOL_UVERBS = 1, |
140 CP_DEVICE = 2, |
166 CP_DEVICE = 2, |
141 CP_D = 3, |
167 CP_D = 3, |
142 CP_GIDS = 4, |
168 CP_GIDS = 4, |
143 CP_PKEYS = 5, |
169 CP_PKEYS = 5, |
144 CP_MLX4 = 6, |
170 CP_PORTS = 6, |
145 CP_PORTS = 7, |
171 CP_UMAD = 7, |
146 CP_UMAD = 8, |
172 CP_SLASH = 8, |
147 CP_SLASH = 9, |
173 CP_SYS = 9, |
148 CP_SYS = 10, |
174 CP_CLASS = 10, |
149 CP_CLASS = 11, |
175 CP_INFINIBAND_VERBS = 11, |
150 CP_INFINIBAND_VERBS = 12, |
176 CP_INFINIBAND = 12, |
151 CP_INFINIBAND = 13, |
177 CP_INFINIBAND_MAD = 13, |
152 CP_INFINIBAND_MAD = 14, |
178 CP_MISC = 14, |
153 CP_MISC = 15, |
179 CP_RDMA_CM = 15 |
154 CP_RDMA_CM = 16 |
|
155 } cp_prefix_t; |
180 } cp_prefix_t; |
156 |
181 |
157 /* |
182 /* |
158 * Some temporary cache code, until things are cleaned up as part of DR |
183 * Some temporary cache code, until things are cleaned up as part of DR |
159 * work. This will speed up the sysfs emulation. |
184 * work. This will speed up the sysfs emulation. |
160 */ |
185 */ |
161 typedef struct ibdev_cache_info_s { |
186 typedef struct ibdev_cache_info_s { |
162 uint_t ibd_valid; |
187 boolean_t ibd_valid; |
163 uint_t ibd_hw_rev; |
188 uint_t ibd_hw_rev; |
164 char ibd_node_guid_str[20]; |
189 uint_t ibd_abi_version; |
165 char ibd_node_guid_external_str[20]; |
190 uint_t ibd_vendor_id; |
166 char ibd_sys_image_guid[20]; |
191 uint_t ibd_device_id; |
167 char ibd_fw_ver[16]; |
192 char ibd_hca_path[IB_HCA_DEVPATH_SZ]; |
168 char ibd_name[16]; |
193 char ibd_node_guid_str[20]; |
169 int ibd_boardid_index; |
194 char ibd_node_guid_external_str[20]; |
170 uint_t ibd_device_id; |
195 char ibd_sys_image_guid[20]; |
|
196 char ibd_fw_ver[16]; |
|
197 char ibd_name[IBDEV_NAME_SZ]; |
|
198 char ibd_boardid_string[PSID_STR_SZ]; |
|
199 char ibd_devid_string[DEVID_STR_SZ]; |
171 } ibdev_cache_info_t; |
200 } ibdev_cache_info_t; |
172 |
201 |
173 /* hermon - hence 2 */ |
202 /* IB device info cache */ |
174 static ibdev_cache_info_t ibdev_cache[2][MAX_HCAS]; |
203 static ibdev_cache_info_t ibdev_cache[MAX_HCAS]; |
175 |
|
176 typedef struct uverbs_cache_info_s { |
|
177 uint_t uvc_valid; |
|
178 uint_t uvc_ibdev_abi_version; |
|
179 uint_t uvc_vendor_id; |
|
180 uint_t uvc_device_id; |
|
181 int uvc_hca_instance; |
|
182 char uvc_ibdev_name[16]; |
|
183 char uvc_ibdev_hca_path[MAXPATHLEN]; |
|
184 } uverbs_cache_info_t; |
|
185 static uverbs_cache_info_t uverbs_dev_cache[MAX_HCAS]; |
|
186 static int uverbs_abi_version = -1; |
204 static int uverbs_abi_version = -1; |
187 |
205 |
188 typedef struct umad_cache_info_s { |
206 typedef struct umad_cache_info_s { |
189 uint_t umc_valid; |
207 uint_t umc_valid; |
190 int umc_port; |
208 int umc_port; |
232 solaris_fini(void) |
245 solaris_fini(void) |
233 { |
246 { |
234 (void) kstat_close(kc); |
247 (void) kstat_close(kc); |
235 } |
248 } |
236 |
249 |
|
250 #define isdigit(c) ((c) >= '0' && (c) <= '9') |
|
251 |
|
252 /* |
|
253 * Given a device name of the form <driver-prefix><instance>, |
|
254 * get the device number. Device name is of the form |
|
255 * for example:- mlx4_0, mlx4_2 etc. Function will return the device instance |
|
256 * extracted from the name. |
|
257 * for example:- mlx4_0 will return 0 and mlx4_2 will return 2. |
|
258 */ |
237 static int |
259 static int |
238 umad_cache_add(uint_t dev_num, int port, char *ibdev) |
260 get_device_num(const char *device_name) |
239 { |
261 { |
240 if ((dev_num >= MAX_PORTS) || (umad_cache_cnt >= MAX_PORTS)) { |
262 const char *temp; |
241 fprintf(stderr, "dev %d: exceeds umad cache size\n", dev_num); |
263 const char *end; |
242 return (1); |
264 const char *start = device_name; |
243 } |
265 int len; |
244 |
266 int devnum; |
245 umad_dev_cache[dev_num].umc_port = port; |
267 |
246 strcpy(umad_dev_cache[dev_num].umc_ib_dev, ibdev); |
268 if (!start) |
247 umad_dev_cache[dev_num].umc_valid = 1; |
269 return (-1); |
248 umad_cache_cnt++; |
270 |
249 return (0); |
271 len = strlen(device_name); |
250 } |
272 end = &device_name[len - 1]; |
251 |
273 |
252 static int |
274 for (temp = end; temp >= start && isdigit(*temp); temp--) |
253 ibdev_cache_add(uint_t dev_num, ibdev_cache_info_t *info_p) |
275 /* Null body */; |
254 { |
276 |
255 if ((dev_num >= MAX_HCAS) || (ibdev_cache_cnt >= (MAX_HCAS * 2))) { |
277 /* |
256 fprintf(stderr, "dev %d: exceeds hca cache size\n", dev_num); |
278 * Check if the device number is invalid. |
257 return (1); |
279 */ |
258 } |
280 if (temp == end || temp < start) |
259 |
281 return (-1); |
260 if (!(strncmp(info_p->ibd_name, "mlx4", 4))) { |
282 |
261 memcpy(&(ibdev_cache[MLX4][dev_num]), info_p, |
283 devnum = atoi(temp + 1); |
262 sizeof (ibdev_cache_info_t)); |
284 if (devnum < 0 || devnum >= MAX_HCAS) |
263 ibdev_cache[MLX4][dev_num].ibd_valid = 1; |
285 return (-1); |
264 } else { |
286 |
265 fprintf(stderr, "dev %d: has no proper ibdev name\n", dev_num); |
287 return (devnum); |
266 return (1); |
288 } |
267 } |
289 |
268 |
290 /* |
269 ibdev_cache_cnt++; |
291 * For usages where ibdev cache needs to be read based on the IB device |
270 return (0); |
292 * name instead of uverbs device name a simple compare against the cache |
271 } |
293 * entries is used to retrieve the corresponding ibdev cache entry. |
272 |
294 */ |
273 static int |
295 static ibdev_cache_info_t * |
274 uverbs_cache_add(uint_t dev_num, uverbs_cache_info_t *info_p) |
296 ibdev_cache_read_by_devname(const char *devname) |
275 { |
297 { |
276 if ((dev_num >= MAX_HCAS) || (uverbs_cache_cnt >= MAX_HCAS)) { |
298 int idx; |
277 fprintf(stderr, "dev %d: exceeds uverbs cache size\n", dev_num); |
299 ibdev_cache_info_t *cache = NULL; |
278 return (1); |
300 |
279 } |
301 if (!devname) |
280 |
302 return (NULL); |
281 memcpy(&(uverbs_dev_cache[dev_num]), info_p, |
303 |
282 sizeof (uverbs_cache_info_t)); |
304 for (idx = 0; idx < MAX_HCAS; idx++) { |
283 |
305 cache = &ibdev_cache[idx]; |
284 uverbs_dev_cache[dev_num].uvc_valid = 1; |
306 if (strcmp(cache->ibd_name, devname) == 0) |
285 uverbs_cache_cnt++; |
307 break; |
286 return (0); |
308 } |
287 } |
309 |
288 |
310 /* |
|
311 * If we failed to find an entry return NULL. |
|
312 */ |
|
313 if (idx == MAX_HCAS) |
|
314 cache = NULL; |
|
315 |
|
316 return (cache); |
|
317 } |
|
318 |
|
319 /* |
|
320 * Helper function to update the ibdev cache entries with the values obtained |
|
321 * from the uverbs HCA info ioctl. |
|
322 */ |
289 static int |
323 static int |
290 ibdev_cache_init() |
324 ibdev_cache_init() |
291 { |
325 { |
292 ibdev_cache_info_t info; |
326 ibdev_cache_info_t *info; |
293 struct ibv_device **root_dev_list, **dev_list = NULL; |
327 int fd, i, hca_cnt; |
294 struct ibv_device_attr device_attr; |
328 char uverbs_devpath[MAX_OFS_DEVPATH_LEN]; |
295 int i, num_dev, dev_num, ret = 1; |
329 #ifdef __VERBS_COMPAT_MODE |
296 uint64_t guid; |
330 sol_uverbs_infov3_t *uverbs_infop; |
297 const char *p, *ibdev; |
331 sol_uverbs_hca_infov3_t *hca_infop; |
298 |
332 #else |
299 |
333 sol_uverbs_info_t *uverbs_infop; |
300 root_dev_list = dev_list = ibv_get_device_list(&num_dev); |
334 sol_uverbs_hca_info_t *hca_infop; |
301 if (!dev_list) { |
335 #endif /* END __VERBS_COMPAT_MODE */ |
302 fprintf(stderr, "No HCA devices found"); |
336 char *buf; |
303 goto error_exit1; |
337 size_t bufsize; |
304 } |
338 uint16_t major, minor, sub_minor; |
305 |
339 uint64_t raw_fw_ver; |
306 for (i = 0; i < num_dev; i++, dev_list++) { |
340 uint64_t guid; |
307 |
341 |
308 if (sol_ibv_query_device(*dev_list, &device_attr)) { |
342 snprintf(uverbs_devpath, MAX_OFS_DEVPATH_LEN, "%s/%s%d", |
309 fprintf(stderr, "failed to query device %p\n", |
|
310 *dev_list); |
|
311 goto error_exit2; |
|
312 } |
|
313 |
|
314 guid = ntohll(device_attr.node_guid); |
|
315 sprintf(info.ibd_node_guid_str, "%04x:%04x:%04x:%04x", |
|
316 (unsigned)(guid >> 48) & 0xffff, |
|
317 (unsigned)(guid >> 32) & 0xffff, |
|
318 (unsigned)(guid >> 16) & 0xffff, |
|
319 (unsigned)(guid >> 0) & 0xffff); |
|
320 |
|
321 guid = ntohll(device_attr.node_guid_external); |
|
322 sprintf(info.ibd_node_guid_external_str, "%04x:%04x:%04x:%04x", |
|
323 (unsigned)(guid >> 48) & 0xffff, |
|
324 (unsigned)(guid >> 32) & 0xffff, |
|
325 (unsigned)(guid >> 16) & 0xffff, |
|
326 (unsigned)(guid >> 0) & 0xffff); |
|
327 |
|
328 guid = ntohll(device_attr.sys_image_guid); |
|
329 sprintf(info.ibd_sys_image_guid, "%04x:%04x:%04x:%04x", |
|
330 (unsigned)(guid >> 48) & 0xffff, |
|
331 (unsigned)(guid >> 32) & 0xffff, |
|
332 (unsigned)(guid >> 16) & 0xffff, |
|
333 (unsigned)(guid >> 0) & 0xffff); |
|
334 |
|
335 (void) strcpy(info.ibd_fw_ver, device_attr.fw_ver); |
|
336 info.ibd_hw_rev = device_attr.hw_ver; |
|
337 info.ibd_device_id = device_attr.vendor_part_id; |
|
338 |
|
339 ibdev = ibv_get_device_name(*dev_list); |
|
340 if (strncmp(ibdev, "mlx4_", 5) == 0) { |
|
341 p = ibdev + (strlen("mlx4_")); |
|
342 } else { |
|
343 fprintf(stderr, "Invalid device %s\n", ibdev); |
|
344 goto error_exit2; |
|
345 } |
|
346 dev_num = atoi(p); |
|
347 (void) strcpy(info.ibd_name, ibdev); |
|
348 |
|
349 info.ibd_boardid_index = -1; |
|
350 |
|
351 if (ibdev_cache_add(dev_num, &info)) { |
|
352 fprintf(stderr, "failed to add dev %d to ibdev cache\n", |
|
353 dev_num); |
|
354 goto error_exit2; |
|
355 } |
|
356 } |
|
357 |
|
358 ret = 0; |
|
359 |
|
360 /* clean up and Return */ |
|
361 error_exit2: |
|
362 if (root_dev_list) |
|
363 ibv_free_device_list(root_dev_list); |
|
364 error_exit1: |
|
365 return (ret); |
|
366 } |
|
367 |
|
368 static int |
|
369 uverbs_cache_init() |
|
370 { |
|
371 uverbs_cache_info_t info; |
|
372 int dev_num, fd, i, bufsize, hca_cnt; |
|
373 char uverbs_devpath[MAXPATHLEN]; |
|
374 sol_uverbs_info_t *uverbs_infop; |
|
375 sol_uverbs_hca_info_t *hca_infop; |
|
376 char *buf; |
|
377 |
|
378 snprintf(uverbs_devpath, MAXPATHLEN, "%s/%s%d", |
|
379 IB_OFS_DEVPATH_PREFIX, UVERBS_KERNEL_SYSFS_NAME_BASE, |
343 IB_OFS_DEVPATH_PREFIX, UVERBS_KERNEL_SYSFS_NAME_BASE, |
380 sol_uverbs_minor_dev); |
344 sol_uverbs_minor_dev); |
381 |
345 |
382 /* |
346 /* |
383 * using the first sol_uverbs minor node that can be opened to get |
347 * using the first sol_uverbs minor node that can be opened to get |
384 * all the HCA information |
348 * all the HCA information |
385 */ |
349 */ |
386 if ((fd = open(uverbs_devpath, O_RDWR)) < 0) { |
350 if ((fd = open(uverbs_devpath, O_RDWR)) < 0) { |
387 fprintf(stderr, "sol_uverbs failed to open: %s\n", |
351 fprintf(stderr, "sol_uverbs failed to open: %s\n", |
388 strerror(errno)); |
352 strerror(errno)); |
389 goto error_exit1; |
353 return (-1); |
390 } |
354 } |
391 |
355 |
392 bufsize = sizeof (sol_uverbs_info_t) + sizeof (sol_uverbs_hca_info_t) * |
356 bufsize = SIZEOF_UVERBS_INFO + (MAX_HCAS * SIZEOF_HCA_INFO); |
393 MAX_HCAS; |
|
394 buf = malloc(bufsize); |
357 buf = malloc(bufsize); |
|
358 if (!buf) { |
|
359 fprintf(stderr, "ibdev_cache_update() failed to alloc\n"); |
|
360 close(fd); |
|
361 return (-1); |
|
362 } |
395 memset(buf, 0, bufsize); |
363 memset(buf, 0, bufsize); |
396 uverbs_infop = (sol_uverbs_info_t *)buf; |
364 |
|
365 uverbs_infop = UVERBS_INFO(buf); |
397 uverbs_infop->uverbs_hca_cnt = MAX_HCAS; |
366 uverbs_infop->uverbs_hca_cnt = MAX_HCAS; |
398 |
367 |
399 if (ioctl(fd, UVERBS_IOCTL_GET_HCA_INFO, uverbs_infop) != 0) { |
368 if (ioctl(fd, UVERBS_IOCTL_GET_HCA_INFO, uverbs_infop) != 0) { |
400 fprintf(stderr, "sol_uverbs ioctl failed: %s\n", |
369 fprintf(stderr, "sol_uverbs ioctl failed: %s\n", |
401 strerror(errno)); |
370 strerror(errno)); |
402 |
371 |
403 goto error_exit2; |
372 goto error_exit1; |
404 } |
373 } |
405 |
374 |
406 if (uverbs_infop->uverbs_solaris_abi_version != |
375 if (uverbs_infop->uverbs_solaris_abi_version != |
407 IB_USER_VERBS_SOLARIS_ABI_VERSION) { |
376 IB_USER_VERBS_SOLARIS_ABI_VERSION) { |
408 fprintf(stderr, "sol_uverbs solaris_abi_version !=" |
377 fprintf(stderr, "sol_uverbs solaris_abi_version !=" |
409 "IB_USER_VERBS_SOLARIS_ABI_VERSION : %d\n", |
378 "IB_USER_VERBS_SOLARIS_ABI_VERSION : %d\n", |
410 uverbs_infop->uverbs_solaris_abi_version); |
379 uverbs_infop->uverbs_solaris_abi_version); |
411 goto error_exit2; |
380 goto error_exit1; |
412 } |
381 } |
413 |
382 |
414 hca_cnt = uverbs_infop->uverbs_hca_cnt; /* hca count returned */ |
383 hca_cnt = uverbs_infop->uverbs_hca_cnt; /* hca count returned */ |
415 hca_infop = uverbs_infop->uverbs_hca_info; |
384 hca_infop = uverbs_infop->uverbs_hca_info; |
416 |
385 |
|
386 if (hca_cnt > MAX_HCAS) { |
|
387 fprintf(stderr, "Number of HCAs returned exceeds max\n"); |
|
388 goto error_exit1; |
|
389 } |
|
390 |
417 if (uverbs_abi_version == -1) |
391 if (uverbs_abi_version == -1) |
418 uverbs_abi_version = uverbs_infop->uverbs_abi_version; |
392 uverbs_abi_version = uverbs_infop->uverbs_abi_version; |
419 |
393 |
420 for (i = 0; i < hca_cnt; i++, hca_infop++) { |
394 for (i = 0; i < hca_cnt; i++, hca_infop++) { |
421 info.uvc_vendor_id = hca_infop->uverbs_hca_vendorid; |
395 |
422 info.uvc_device_id = hca_infop->uverbs_hca_deviceid; |
396 /* |
423 info.uvc_hca_instance = |
397 * Update the cache. |
424 hca_infop->uverbs_hca_driver_instance; |
398 */ |
425 |
399 info = &ibdev_cache[hca_infop->uverbs_hca_devidx]; |
426 snprintf(info.uvc_ibdev_hca_path, |
400 |
427 sizeof (info.uvc_ibdev_hca_path), |
401 (void) strncpy(info->ibd_name, |
|
402 hca_infop->uverbs_hca_ibdev_name, IBDEV_NAME_SZ); |
|
403 |
|
404 guid = hca_infop->uverbs_hca_node_guid; |
|
405 sprintf(info->ibd_node_guid_str, "%04x:%04x:%04x:%04x", |
|
406 (unsigned)(guid >> 48) & 0xffff, |
|
407 (unsigned)(guid >> 32) & 0xffff, |
|
408 (unsigned)(guid >> 16) & 0xffff, |
|
409 (unsigned)(guid >> 0) & 0xffff); |
|
410 |
|
411 guid = hca_infop->uverbs_hca_node_external_guid; |
|
412 sprintf(info->ibd_node_guid_external_str, "%04x:%04x:%04x:%04x", |
|
413 (unsigned)(guid >> 48) & 0xffff, |
|
414 (unsigned)(guid >> 32) & 0xffff, |
|
415 (unsigned)(guid >> 16) & 0xffff, |
|
416 (unsigned)(guid >> 0) & 0xffff); |
|
417 |
|
418 guid = hca_infop->uverbs_hca_sys_image_guid; |
|
419 sprintf(info->ibd_sys_image_guid, "%04x:%04x:%04x:%04x", |
|
420 (unsigned)(guid >> 48) & 0xffff, |
|
421 (unsigned)(guid >> 32) & 0xffff, |
|
422 (unsigned)(guid >> 16) & 0xffff, |
|
423 (unsigned)(guid >> 0) & 0xffff); |
|
424 |
|
425 raw_fw_ver = hca_infop->uverbs_hca_fw_ver; |
|
426 major = (raw_fw_ver >> 32) & 0xffff; |
|
427 minor = (raw_fw_ver >> 16) & 0xffff; |
|
428 sub_minor = raw_fw_ver & 0xffff; |
|
429 |
|
430 snprintf(info->ibd_fw_ver, sizeof (info->ibd_fw_ver), |
|
431 "%d.%d.%03d", major, minor, sub_minor); |
|
432 |
|
433 info->ibd_hw_rev = hca_infop->uverbs_hca_hw_version; |
|
434 info->ibd_vendor_id = hca_infop->uverbs_hca_vendorid; |
|
435 info->ibd_device_id = hca_infop->uverbs_hca_deviceid; |
|
436 info->ibd_abi_version = hca_infop->uverbs_hca_abi_version; |
|
437 |
|
438 snprintf(info->ibd_hca_path, sizeof (info->ibd_hca_path), |
428 "%s/%s%d", IB_HCA_DEVPATH_PREFIX, |
439 "%s/%s%d", IB_HCA_DEVPATH_PREFIX, |
429 hca_infop->uverbs_hca_driver_name, |
440 hca_infop->uverbs_hca_driver_name, |
430 hca_infop->uverbs_hca_driver_instance); |
441 hca_infop->uverbs_hca_driver_instance); |
431 |
442 |
432 if (strncmp(hca_infop->uverbs_hca_ibdev_name, "mlx4_", 5) == 0) |
443 strncpy(info->ibd_boardid_string, |
433 info.uvc_ibdev_abi_version = |
444 hca_infop->uverbs_hca_psid_string, PSID_STR_SZ); |
434 MLX4_UVERBS_MAX_ABI_VERSION; |
445 |
435 else { |
446 strncpy(info->ibd_devid_string, |
436 fprintf(stderr, "libibverbs: sol_uverbs unsupported " |
447 hca_infop->uverbs_hca_devid_string, DEVID_STR_SZ); |
437 "device: %s\n", hca_infop->uverbs_hca_ibdev_name); |
448 |
438 goto error_exit2; |
449 info->ibd_valid = B_TRUE; |
439 } |
|
440 |
|
441 strcpy(info.uvc_ibdev_name, hca_infop->uverbs_hca_ibdev_name); |
|
442 |
|
443 dev_num = hca_infop->uverbs_hca_devidx; |
|
444 if (uverbs_cache_add(dev_num, &info)) { |
|
445 fprintf(stderr, "failed to add dev %d to uverbs " |
|
446 "cache\n", dev_num); |
|
447 goto error_exit2; |
|
448 } |
|
449 } |
450 } |
450 |
451 |
451 free(buf); |
452 free(buf); |
452 close(fd); |
453 close(fd); |
453 return (1); |
454 return (0); |
454 |
455 |
455 error_exit2: |
456 error_exit1: |
456 free(buf); |
457 free(buf); |
457 close(fd); |
458 close(fd); |
458 |
459 return (-1); |
459 error_exit1: |
460 } |
|
461 |
|
462 static int |
|
463 umad_cache_add(uint_t dev_num, int port, char *ibdev) |
|
464 { |
|
465 if ((dev_num >= MAX_PORTS) || (umad_cache_cnt >= MAX_PORTS)) { |
|
466 fprintf(stderr, "dev %d: exceeds umad cache size\n", dev_num); |
|
467 return (1); |
|
468 } |
|
469 |
|
470 umad_dev_cache[dev_num].umc_port = port; |
|
471 strcpy(umad_dev_cache[dev_num].umc_ib_dev, ibdev); |
|
472 umad_dev_cache[dev_num].umc_valid = 1; |
|
473 umad_cache_cnt++; |
460 return (0); |
474 return (0); |
461 } |
475 } |
462 |
476 |
463 static int |
477 static int |
464 umad_cache_init() |
478 umad_cache_init() |
465 { |
479 { |
466 int i, fd, minor; |
480 int i, fd, minor; |
467 int save_errno = 0; |
481 int save_errno = 0; |
468 int port_cnt, bufsize; |
482 int port_cnt, bufsize; |
469 char umad_devpath[MAXPATHLEN], *buf; |
483 char umad_devpath[MAX_OFS_DEVPATH_LEN], *buf; |
470 sol_umad_ioctl_info_t *umad_infop; |
484 sol_umad_ioctl_info_t *umad_infop; |
471 sol_umad_ioctl_port_info_t *port_infop; |
485 sol_umad_ioctl_port_info_t *port_infop; |
472 |
486 |
473 for (minor = 0; minor < MAX_PORTS; minor++) { |
487 for (minor = 0; minor < MAX_PORTS; minor++) { |
474 snprintf(umad_devpath, MAXPATHLEN, "%s/%s%d", |
488 snprintf(umad_devpath, MAX_OFS_DEVPATH_LEN, "%s/%s%d", |
475 IB_OFS_DEVPATH_PREFIX, UMAD_KERNEL_SYSFS_NAME_BASE, |
489 IB_OFS_DEVPATH_PREFIX, UMAD_KERNEL_SYSFS_NAME_BASE, |
476 minor); |
490 minor); |
477 |
491 |
478 if ((fd = open(umad_devpath, O_RDWR)) > 0) |
492 if ((fd = open(umad_devpath, O_RDWR)) > 0) |
479 break; |
493 break; |
890 static int |
906 static int |
891 infiniband_verbs(char *path, char *buf, size_t size) |
907 infiniband_verbs(char *path, char *buf, size_t size) |
892 { |
908 { |
893 unsigned int device_num; |
909 unsigned int device_num; |
894 int len = -1; |
910 int len = -1; |
895 uverbs_cache_info_t *info_p; |
911 ibdev_cache_info_t *info_p; |
896 |
912 |
897 if (pthread_mutex_lock(&uverbs_cache_mutex) != 0) { |
913 if (pthread_mutex_lock(&ibdev_cache_mutex) != 0) { |
898 fprintf(stderr, "failed: to acquire uverbs_cache_mutex %s\n", |
914 fprintf(stderr, "failed: to acquire ibdev_cache_mutex %s\n", |
899 strerror(errno)); |
915 strerror(errno)); |
900 goto exit; |
916 goto exit; |
901 } |
917 } |
902 |
918 |
903 if (!uverbs_cache_initialized) { |
919 if (ibdev_cache_initialized == B_FALSE) { |
904 if (uverbs_cache_init()) |
920 if (ibdev_cache_init() == 0) |
905 uverbs_cache_initialized = B_TRUE; |
921 ibdev_cache_initialized = B_TRUE; |
906 else { |
922 else { |
907 (void) pthread_mutex_unlock(&uverbs_cache_mutex); |
923 (void) pthread_mutex_unlock(&ibdev_cache_mutex); |
908 #ifdef DEBUG |
924 #ifdef DEBUG |
909 fprintf(stderr, "failed: to init uverbs cache %s\n", |
925 fprintf(stderr, "failed: to init ibdev cache %s\n", |
910 strerror(errno)); |
926 strerror(errno)); |
911 #endif |
927 #endif |
912 goto exit; |
928 goto exit; |
913 } |
929 } |
914 } |
930 } |
915 (void) pthread_mutex_unlock(&uverbs_cache_mutex); |
931 (void) pthread_mutex_unlock(&ibdev_cache_mutex); |
916 |
932 |
917 if (check_path(path, CP_SOL_UVERBS, &device_num)) { |
933 if (check_path(path, CP_SOL_UVERBS, &device_num)) { |
918 |
934 |
919 if (device_num >= MAX_HCAS) { |
935 if (device_num >= MAX_HCAS) { |
920 fprintf(stderr, "Invalid path%s\n", path); |
936 fprintf(stderr, "Invalid path%s\n", path); |
921 goto exit; |
937 goto exit; |
922 } |
938 } |
923 |
939 |
924 if (!uverbs_dev_cache[device_num].uvc_valid) { |
940 if (!ibdev_cache[device_num].ibd_valid) |
925 goto exit; |
941 goto exit; |
926 } |
942 |
927 |
943 info_p = &ibdev_cache[device_num]; |
928 info_p = &uverbs_dev_cache[device_num]; |
|
929 |
944 |
930 if (check_path(path, CP_DEVICE, NULL)) { |
945 if (check_path(path, CP_DEVICE, NULL)) { |
931 /* |
946 /* |
932 * Under Linux, this is a link to the PCI device entry |
947 * Under Linux, this is a link to the PCI device entry |
933 * in /sys/devices/pci...../.... |
948 * in /sys/devices/pci...../.... |
934 */ |
949 */ |
935 if (strcmp(path, "vendor") == 0) { |
950 if (strcmp(path, "vendor") == 0) { |
936 len = 1 + sprintf(buf, "0x%x", |
951 len = 1 + sprintf(buf, "0x%x", |
937 info_p->uvc_vendor_id); |
952 info_p->ibd_vendor_id); |
938 } else if (strcmp(path, "device") == 0) { |
953 } else if (strcmp(path, "device") == 0) { |
939 len = 1 + sprintf(buf, "0x%x", |
954 len = 1 + sprintf(buf, "0x%x", |
940 info_p->uvc_device_id); |
955 info_p->ibd_device_id); |
941 } |
956 } |
942 } else if (strcmp(path, "ibdev") == 0) { |
957 } else if (strcmp(path, "ibdev") == 0) { |
943 len = 1 + sprintf(buf, "%s", |
958 len = 1 + sprintf(buf, "%s", info_p->ibd_name); |
944 info_p->uvc_ibdev_name); |
|
945 } else if (strcmp(path, "abi_version") == 0) { |
959 } else if (strcmp(path, "abi_version") == 0) { |
946 len = 1 + sprintf(buf, "%d", |
960 len = 1 + sprintf(buf, "%d", info_p->ibd_abi_version); |
947 info_p->uvc_ibdev_abi_version); |
|
948 } |
961 } |
949 } else if (strcmp(path, "abi_version") == 0) { |
962 } else if (strcmp(path, "abi_version") == 0) { |
950 |
963 |
951 if (uverbs_abi_version == -1) { |
964 if (uverbs_abi_version == -1) { |
952 fprintf(stderr, "UVerbs ABI Version invalid\n"); |
965 fprintf(stderr, "UVerbs ABI Version invalid\n"); |
1149 } |
1170 } |
1150 exit: |
1171 exit: |
1151 return (len); |
1172 return (len); |
1152 } |
1173 } |
1153 |
1174 |
1154 /* |
|
1155 * This function passes the HW PSID / HWPN string obtained from |
|
1156 * driver HERMON_IOCTL_GET_HWINFO IOCTL. The memory for "hca_hwpsid" |
|
1157 * & "hca_hwpn" argument has to be passed by the caller and has to |
|
1158 * be at least 16 bytes & 64 bytes in size. |
|
1159 */ |
|
1160 static int |
|
1161 get_hca_psid_pn(char *ibd_name, int fd, char *hca_hwpsid, |
|
1162 char *hca_hwpn) |
|
1163 { |
|
1164 hermon_hw_info_ioctl_t hermon_hw_info; |
|
1165 int rc; |
|
1166 |
|
1167 if (strncmp(ibd_name, "mlx4_", 5) == 0) { |
|
1168 if ((rc = ioctl(fd, HERMON_IOCTL_GET_HWINFO, |
|
1169 &hermon_hw_info)) != 0) |
|
1170 return (rc); |
|
1171 |
|
1172 strncpy(hca_hwpsid, hermon_hw_info.af_psid, 16); |
|
1173 strncpy(hca_hwpn, hermon_hw_info.af_hwpn, 64); |
|
1174 } else { |
|
1175 fprintf(stderr, "libibverbs: sol_uverbs unsupported " |
|
1176 "device: %s\n", ibd_name); |
|
1177 return (1); |
|
1178 } |
|
1179 return (0); |
|
1180 } |
|
1181 |
|
1182 /* |
|
1183 * This function passes the HW Part number string obtained from driver |
|
1184 * IOCTL. The memory for "hca_hwpn" argument has to be passed by the |
|
1185 * caller and has to be at least 64 bytes in size. |
|
1186 */ |
|
1187 static int |
|
1188 get_hca_hwpn_str(char *ibd_name, int fd, char *hca_hwpn) |
|
1189 { |
|
1190 hermon_flash_init_ioctl_t hermon_flash_info; |
|
1191 int rc; |
|
1192 |
|
1193 if (strncmp(ibd_name, "mlx4_", 5) == 0) { |
|
1194 if ((rc = ioctl(fd, HERMON_IOCTL_FLASH_INIT, |
|
1195 &hermon_flash_info)) != 0) |
|
1196 return (rc); |
|
1197 strncpy(hca_hwpn, hermon_flash_info.af_hwpn, 64); |
|
1198 } else { |
|
1199 fprintf(stderr, "libibverbs: sol_uverbs unsupported " |
|
1200 "device: %s\n", ibd_name); |
|
1201 return (1); |
|
1202 } |
|
1203 return (0); |
|
1204 } |
|
1205 |
|
1206 static void |
|
1207 init_boardid_index(ibdev_cache_info_t *ibd_info) |
|
1208 { |
|
1209 int i; |
|
1210 int fd; |
|
1211 char hca_hwpsid[16]; |
|
1212 char hca_hwpn[64]; |
|
1213 char *pn_psidp; |
|
1214 boolean_t psid_valid, pn_valid; |
|
1215 |
|
1216 if (pthread_mutex_lock(&uverbs_cache_mutex) != 0) { |
|
1217 fprintf(stderr, "failed: to acquire " |
|
1218 "uverbs_cache_mutex %s\n", |
|
1219 strerror(errno)); |
|
1220 goto boardid_err; |
|
1221 } |
|
1222 if (!uverbs_cache_initialized) { |
|
1223 if (uverbs_cache_init()) |
|
1224 uverbs_cache_initialized = B_TRUE; |
|
1225 else { |
|
1226 (void) pthread_mutex_unlock(&uverbs_cache_mutex); |
|
1227 #ifdef DEBUG |
|
1228 fprintf(stderr, "failed: to init uverbs cache %s\n", |
|
1229 strerror(errno)); |
|
1230 #endif |
|
1231 goto boardid_err; |
|
1232 } |
|
1233 } |
|
1234 (void) pthread_mutex_unlock(&uverbs_cache_mutex); |
|
1235 |
|
1236 for (i = 0; i < MAX_HCAS; i++) { |
|
1237 if (uverbs_dev_cache[i].uvc_valid && |
|
1238 strcmp(uverbs_dev_cache[i].uvc_ibdev_name, |
|
1239 ibd_info->ibd_name) == 0) { |
|
1240 break; |
|
1241 } |
|
1242 } |
|
1243 |
|
1244 if (i == MAX_HCAS) { |
|
1245 fprintf(stderr, "failed to find uverbs_dev for %s\n", |
|
1246 ibd_info->ibd_name); |
|
1247 goto boardid_err; |
|
1248 } |
|
1249 |
|
1250 fd = open(uverbs_dev_cache[i].uvc_ibdev_hca_path, O_RDWR); |
|
1251 if (fd < 0) { |
|
1252 goto boardid_err; |
|
1253 } |
|
1254 |
|
1255 psid_valid = pn_valid = B_FALSE; |
|
1256 if (get_hca_psid_pn(ibd_info->ibd_name, fd, |
|
1257 hca_hwpsid, hca_hwpn)) { |
|
1258 if (get_hca_hwpn_str(ibd_info->ibd_name, fd, hca_hwpn)) { |
|
1259 close(fd); |
|
1260 goto boardid_err; |
|
1261 } else { |
|
1262 if (hca_hwpn[0]) { |
|
1263 if ((pn_psidp = strchr( |
|
1264 hca_hwpn, ' ')) != NULL) |
|
1265 *pn_psidp = '\0'; |
|
1266 pn_valid = B_TRUE; |
|
1267 } |
|
1268 } |
|
1269 } else { |
|
1270 if (hca_hwpsid[0]) { |
|
1271 if ((pn_psidp = strchr( |
|
1272 hca_hwpsid, ' ')) != NULL) |
|
1273 *pn_psidp = '\0'; |
|
1274 psid_valid = B_TRUE; |
|
1275 } else if (hca_hwpn[0]) { |
|
1276 if ((pn_psidp = strchr( |
|
1277 hca_hwpn, ' ')) != NULL) |
|
1278 *pn_psidp = '\0'; |
|
1279 pn_valid = B_TRUE; |
|
1280 } |
|
1281 } |
|
1282 close(fd); |
|
1283 |
|
1284 if (pn_valid == B_FALSE && psid_valid == B_FALSE) |
|
1285 goto boardid_err; |
|
1286 |
|
1287 for (i = 0; i < MLX_MAX_ID; i++) { |
|
1288 /* |
|
1289 * Find PSID number, set the boardid_index, |
|
1290 * Skip index 0, as it is for failure "unknown" |
|
1291 * case |
|
1292 */ |
|
1293 if ((psid_valid == B_TRUE && |
|
1294 strncmp(mlx_mdr[i].mlx_psid, |
|
1295 (const char *)hca_hwpsid, |
|
1296 min(strlen(hca_hwpsid), |
|
1297 strlen(mlx_mdr[i].mlx_psid))) == 0) || |
|
1298 (pn_valid == B_TRUE && |
|
1299 strncmp(mlx_mdr[i].mlx_pn, |
|
1300 (const char *)hca_hwpn, |
|
1301 min(strlen(hca_hwpn), |
|
1302 strlen(mlx_mdr[i].mlx_pn))) == 0)) { |
|
1303 /* Set boardid_index */ |
|
1304 ibd_info->ibd_boardid_index = i; |
|
1305 return; |
|
1306 } |
|
1307 } |
|
1308 |
|
1309 boardid_err: |
|
1310 /* Failure case, default to "unknown" */ |
|
1311 ibd_info->ibd_boardid_index = -2; |
|
1312 } |
|
1313 |
|
1314 static int |
1175 static int |
1315 infiniband(char *path, char *buf, size_t size) |
1176 infiniband(char *path, char *buf, size_t size) |
1316 { |
1177 { |
1317 int len = -1; |
1178 int len = -1; |
1318 unsigned int device_num; |
1179 char dev_name[MAXNAMELEN]; |
1319 char dev_name[10]; |
|
1320 ibdev_cache_info_t *info; |
1180 ibdev_cache_info_t *info; |
1321 |
1181 |
1322 memset(dev_name, 0, 10); |
1182 memset(dev_name, 0, MAXNAMELEN); |
1323 |
1183 |
1324 if (check_path(path, CP_MLX4, &device_num)) { |
1184 if (!check_path_for_hca(path, dev_name)) |
1325 sprintf(dev_name, "mlx4_%d", device_num); |
|
1326 } else { |
|
1327 goto exit; |
1185 goto exit; |
1328 } |
|
1329 |
1186 |
1330 if (check_path(path, CP_PORTS, NULL)) { |
1187 if (check_path(path, CP_PORTS, NULL)) { |
1331 len = infiniband_ports(path, buf, size, dev_name); |
1188 len = infiniband_ports(path, buf, size, dev_name); |
1332 } else if (strcmp(path, "node_type") == 0) { |
1189 } else if (strcmp(path, "node_type") == 0) { |
1333 len = 1 + sprintf(buf, "%d", IBV_NODE_CA); |
1190 len = 1 + sprintf(buf, "%d", IBV_NODE_CA); |