2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /* Copyright 2010 QLogic Corporation */
23
24 /*
25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 #pragma ident "Copyright 2010 QLogic Corporation; ql_hba_fru.c"
29
30 /*
31 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32 *
33 * ***********************************************************************
34 * * **
35 * * NOTICE **
36 * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION **
37 * * ALL RIGHTS RESERVED **
38 * * **
39 * ***********************************************************************
40 *
41 */
42
43 /*
44 * Determine HBA FRU card information for T11 FC-HBA
45 */
46
47 #include <ql_apps.h>
48 #include <ql_api.h>
49 #include <ql_debug.h>
50 #include <ql_ioctl.h>
51 #include <ql_xioctl.h>
52
53 /*
54 * Temporary define until LV headers are updated
55 */
56 #ifndef FC_HBA_PORTSPEED_8GBIT
222 * Input:
223 * ha = adapter state structure
224 * port_info = ptr to LV port strcture.
225 *
226 * Returns:
227 *
228 * Context:
229 * Kernel context.
230 */
231 void
232 ql_populate_hba_fru_details(ql_adapter_state_t *ha,
233 fc_fca_port_info_t *port_info)
234 {
235 fca_port_attrs_t *attrs = &port_info->pi_attrs;
236 uint16_t chip = ha->device_id;
237 uint16_t model = ha->subsys_id;
238 uint16_t ssdevid = ha->subven_id;
239 size_t vlen;
240 int32_t i;
241
242 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
243
244 attrs = &port_info->pi_attrs;
245
246 /* Constants */
247 (void) snprintf(attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
248 "QLogic Corp.");
249 (void) snprintf(attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
250 "%s", QL_NAME);
251 (void) snprintf(attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
252 "%s", ha->adapter_stats->revlvl.qlddv);
253
254 if ((i = ql_vpd_lookup(ha, (uint8_t *)VPD_TAG_SN, (uint8_t *)
255 attrs->serial_number, FCHBA_SERIAL_NUMBER_LEN)) == -1) {
256 attrs->serial_number[0] = '\0';
257 }
258 attrs->hardware_version[0] = '\0';
259
260 /* Dynamic data */
261 (void) snprintf(attrs->firmware_version, FCHBA_FIRMWARE_VERSION_LEN,
262 "%02d.%02d.%02d", ha->fw_major_version, ha->fw_minor_version,
263 ha->fw_subminor_version);
264
265 CACHE_LOCK(ha);
266
267 /* Report FCode / BIOS / EFI version(s). */
268 if (ha->fcache != NULL) {
269 uint32_t types = FTYPE_BIOS|FTYPE_FCODE|FTYPE_EFI;
270 ql_fcache_t *fptr = ha->fcache;
271 int8_t *orv = &*attrs->option_rom_version;
272
273 while ((fptr != NULL) && (types != 0)) {
274 /* Get the next image */
275 if ((fptr = ql_get_fbuf(ha->fcache, types)) != NULL) {
276
277 switch (fptr->type) {
278 case FTYPE_FCODE:
279 (void) snprintf(orv,
280 FCHBA_OPTION_ROM_VERSION_LEN,
281 "%s fcode: %s;", orv, fptr->verstr);
282 break;
283 case FTYPE_BIOS:
284 (void) snprintf(orv,
285 FCHBA_OPTION_ROM_VERSION_LEN,
286 "%s BIOS: %s;", orv, fptr->verstr);
287 break;
288 case FTYPE_EFI:
289 (void) snprintf(orv,
290 FCHBA_OPTION_ROM_VERSION_LEN,
291 "%s EFI: %s;", orv, fptr->verstr);
292 break;
293 default:
294 EL(ha, "ignoring ftype: %xh\n",
295 fptr->type);
296 break;
297 }
298 types &= ~(fptr->type);
299 }
300 }
301 }
302
303 CACHE_UNLOCK(ha);
304
305 if (strlen(attrs->option_rom_version) == 0) {
306 int rval = -1;
307 uint32_t i = 0;
308 caddr_t fcode_ver_buf = NULL;
309
310 if (CFG_IST(ha, CFG_CTRL_2200)) {
311 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
312 rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
313 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version",
314 (caddr_t)&fcode_ver_buf, (int32_t *)&i);
315 }
316
317 (void) snprintf(attrs->option_rom_version,
318 FCHBA_OPTION_ROM_VERSION_LEN, "%s",
319 (rval == DDI_PROP_SUCCESS ? fcode_ver_buf :
320 "No boot image detected"));
321
322 if (fcode_ver_buf != NULL) {
323 kmem_free(fcode_ver_buf, (size_t)i);
324 }
325
326 }
327
328 attrs->vendor_specific_id = ha->adapter_features;
329 attrs->max_frame_size = CFG_IST(ha, CFG_CTRL_24258081) ?
330 (ha->init_ctrl_blk.cb24.max_frame_length[1] << 8 |
331 ha->init_ctrl_blk.cb24.max_frame_length[0]) :
332 (ha->init_ctrl_blk.cb.max_frame_length[1] << 8 |
333 ha->init_ctrl_blk.cb.max_frame_length[0]);
334 attrs->supported_cos = 0x10000000; /* Class 3 only */
335
336 switch (chip & 0xFF00) {
337 case 0x2200:
338 attrs->supported_speed = FC_HBA_PORTSPEED_1GBIT;
339 break;
340 case 0x2300:
341 attrs->supported_speed = FC_HBA_PORTSPEED_2GBIT |
342 FC_HBA_PORTSPEED_1GBIT;
343 break;
344 case 0x2400:
345 case 0x8400:
346 attrs->supported_speed = FC_HBA_PORTSPEED_4GBIT |
347 FC_HBA_PORTSPEED_2GBIT | FC_HBA_PORTSPEED_1GBIT;
348 break;
349 case 0x8000:
350 attrs->supported_speed = FC_HBA_PORTSPEED_10GBIT;
351 break;
352 case 0x2500:
353 attrs->supported_speed = FC_HBA_PORTSPEED_8GBIT |
354 FC_HBA_PORTSPEED_4GBIT | FC_HBA_PORTSPEED_2GBIT |
355 FC_HBA_PORTSPEED_1GBIT;
356
357 /*
358 * Correct supported speeds based on type of
471
472 /*
473 * Populate the LV symbolic node and port name strings
474 *
475 * Symbolic node name format is:
476 * <hostname>
477 *
478 * Symbolic port name format is:
479 * <driver_name>(<instance>,<vp index>)
480 */
481 vlen = (strlen(utsname.nodename) > FCHBA_SYMB_NAME_LEN ?
482 FCHBA_SYMB_NAME_LEN : strlen(utsname.nodename));
483 (void) snprintf((int8_t *)attrs->sym_node_name, vlen, "%s",
484 utsname.nodename);
485
486 vlen = (strlen(QL_NAME) + 9 > FCHBA_SYMB_NAME_LEN ?
487 FCHBA_SYMB_NAME_LEN : strlen(QL_NAME) + 9);
488 (void) snprintf((int8_t *)attrs->sym_port_name, vlen,
489 "%s(%d,%d)", QL_NAME, ha->instance, ha->vp_index);
490
491 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
492 }
493
494 /*
495 * ql_setup_fruinfo
496 * Generates common id's for instances on the same
497 * physical HBA.
498 *
499 * Input:
500 * ha = adapter state structure
501 *
502 * Returns:
503 *
504 * Context:
505 * Kernel context.
506 */
507 void
508 ql_setup_fruinfo(ql_adapter_state_t *ha)
509 {
510 uint32_t mybasedev_len;
511 ql_adapter_state_t *base_ha = NULL;
512
513 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
514
515 /*
516 * To generate common id for instances residing on the
517 * the same HBA, the devpath for each instance is parsed
518 * and those instances which have matching base devpaths are
519 * given same hba_index, and each port on the same hba are
520 * then assigned unique port_indexs based on the devpath.
521 */
522
523 /*
524 * Get this ha's basedev path and its port index
525 */
526 if (ql_get_basedev_len(ha, &mybasedev_len, &ha->fru_port_index) == 0) {
527
528 GLOBAL_STATE_LOCK();
529
530 /*
531 * Search for this basedev against all of the
532 * ha in the ql_hba global list. If found one
533 * then we are part of other adapter in the
534 * ql_hba list and hence use that ha's hba_index.
535 * If not create a new one from the global hba index.
536 */
537 base_ha = ql_search_basedev(ha, mybasedev_len);
538 if (base_ha != NULL && base_ha->fru_hba_index != 0) {
539 ha->fru_hba_index = base_ha->fru_hba_index;
540 } else {
541 ha->fru_hba_index = ql_gfru_hba_index++;
542 }
543
544 if (CFG_IST(ha, CFG_CTRL_8081)) {
545 /*
546 * The FC functions on 81xx hbas are functions 2 and 3
547 * while the Nic functions occupy 0 and 1. Adjust
548 * fru port index to be like previous FCAs.
549 */
550 ha->fru_port_index = ha->flags & FUNCTION_1 ? 1 : 0;
551 }
552
553 GLOBAL_STATE_UNLOCK();
554
555 } else {
556 ha->fru_hba_index = 0;
557 ha->fru_port_index = 0;
558 }
559
560 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
561 }
562
563 /*
564 * ql_get_basedev_len
565 *
566 * Gets the length of the base device name in the
567 * devpath of the current instance.
568 *
569 * Input:
570 * ha - adapter state pointer.
571 * basedev_len - pointer to the integer which
572 * holds the calculated length.
573 * port_index - pointer to the integer which
574 * contains the port index of
575 * for this device.
576 * Returns:
577 * 0 if successfully parsed, -1 otherwise.
578 *
579 * Context:
580 * Kernel context.
581 */
582 static uint32_t
583 ql_get_basedev_len(ql_adapter_state_t *ha, uint32_t *basedev_len,
584 uint32_t *port_index)
585 {
586 int32_t dev_off;
587 int32_t port_off;
588 int8_t *devstr;
589
590 QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
591
592 if (ha->devpath == NULL) {
593 return ((uint32_t)-1);
594 }
595
596 dev_off = (int32_t)(strlen(ha->devpath) - 1);
597 port_off = -1;
598
599 /* Until we reach the first char or a '@' char in the path */
600 while ((dev_off >= 0) && (ha->devpath[dev_off] != '@')) {
601
602 if (ha->devpath[dev_off] == ',') {
603 port_off = dev_off + 1;
604 }
605
606 dev_off--;
607 }
608
609 if (dev_off < 0) {
610 EL(ha, "Invalid device path '%s'. Cannot get basedev\n",
611 ha->devpath);
612 return ((uint32_t)-1);
613 }
614
615 if (port_off == -1) {
616 *port_index = 0;
617 *basedev_len = (uint32_t)strlen(ha->devpath);
618 } else {
619 /* Get the port index */
620 devstr = ha->devpath + port_off;
621 *port_index = stoi(&devstr);
622 if (*port_index == 0) {
623 EL(ha, "Invalid device path '%s'. Cannot get "
624 "port_index\n", ha->devpath);
625 return ((uint32_t)-1);
626 }
627
628 *basedev_len = (uint32_t)(port_off - 1);
629 }
630
631 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
632
633 return (0);
634 }
635
636 /*
637 * ql_search_basedev
638 * Searches the list of ha instances to find which
639 * ha instance has same base device path as input's.
640 *
641 * Input:
642 * myha = current adapter state pointer.
643 * mybasedev_len = Length of the base device in the
644 * device path name.
645 *
646 * Returns:
647 * If match = ptr to matching ha structure.
648 * If no match = NULL ptr.
649 *
650 * Context:
651 * Kernel context.
652 */
653 static ql_adapter_state_t *
654 ql_search_basedev(ql_adapter_state_t *myha, uint32_t mybasedev_len)
655 {
656 ql_link_t *link;
657 ql_adapter_state_t *ha;
658 uint32_t basedev_len, port_index;
659
660 QL_PRINT_3(CE_CONT, "(%d): started\n", myha->instance);
661
662 for (link = ql_hba.first; link != NULL; link = link->next) {
663
664 ha = link->base_address;
665
666 if (ha == NULL) {
667 EL(myha, "null ha link detected!\n");
668 return (NULL);
669 }
670
671 if (ha == myha) {
672 continue;
673 }
674
675 if (ql_get_basedev_len(ha, &basedev_len, &port_index) != 0) {
676 if (ha->devpath == NULL) {
677 EL(myha, "Device path NULL. Unable to get "
678 "the basedev\n");
679 } else {
680 EL(myha, "Invalid device path '%s'. Cannot "
681 "get the hba index and port index\n",
682 ha->devpath);
683 }
684 continue;
685 }
686
687 /*
688 * If both the basedev len do not match, then it
689 * is obvious that both are not pointing to the
690 * same base device.
691 */
692 if ((basedev_len == mybasedev_len) && (strncmp(myha->devpath,
693 ha->devpath, basedev_len) == 0)) {
694
695 /* We found the ha with same basedev */
696 QL_PRINT_3(CE_CONT, "(%d): found, done\n",
697 myha->instance);
698 return (ha);
699 }
700 }
701
702 QL_PRINT_3(CE_CONT, "(%d): not found, done\n", myha->instance);
703
704 return (NULL);
705 }
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /* Copyright 2015 QLogic Corporation */
23
24 /*
25 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
26 */
27
28 #pragma ident "Copyright 2015 QLogic Corporation; ql_hba_fru.c"
29
30 /*
31 * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
32 *
33 * ***********************************************************************
34 * * **
35 * * NOTICE **
36 * * COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION **
37 * * ALL RIGHTS RESERVED **
38 * * **
39 * ***********************************************************************
40 *
41 */
42
43 /*
44 * Determine HBA FRU card information for T11 FC-HBA
45 */
46
47 #include <ql_apps.h>
48 #include <ql_api.h>
49 #include <ql_debug.h>
50 #include <ql_ioctl.h>
51 #include <ql_xioctl.h>
52
53 /*
54 * Temporary define until LV headers are updated
55 */
56 #ifndef FC_HBA_PORTSPEED_8GBIT
222 * Input:
223 * ha = adapter state structure
224 * port_info = ptr to LV port strcture.
225 *
226 * Returns:
227 *
228 * Context:
229 * Kernel context.
230 */
231 void
232 ql_populate_hba_fru_details(ql_adapter_state_t *ha,
233 fc_fca_port_info_t *port_info)
234 {
235 fca_port_attrs_t *attrs = &port_info->pi_attrs;
236 uint16_t chip = ha->device_id;
237 uint16_t model = ha->subsys_id;
238 uint16_t ssdevid = ha->subven_id;
239 size_t vlen;
240 int32_t i;
241
242 QL_PRINT_3(ha, "started\n");
243
244 attrs = &port_info->pi_attrs;
245
246 /* Constants */
247 (void) snprintf(attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
248 "QLogic Corp.");
249 (void) snprintf(attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
250 "%s", QL_NAME);
251 (void) snprintf(attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
252 "%s", ha->adapter_stats->revlvl.qlddv);
253
254 if ((i = ql_vpd_lookup(ha, (uint8_t *)VPD_TAG_SN, (uint8_t *)
255 attrs->serial_number, FCHBA_SERIAL_NUMBER_LEN)) == -1) {
256 attrs->serial_number[0] = '\0';
257 }
258 attrs->hardware_version[0] = '\0';
259
260 /* Dynamic data */
261 (void) snprintf(attrs->firmware_version, FCHBA_FIRMWARE_VERSION_LEN,
262 "%02d.%02d.%02d", ha->fw_major_version, ha->fw_minor_version,
263 ha->fw_subminor_version);
264
265 /* Report FCode / BIOS / EFI version(s). */
266 if (ha->fcache != NULL) {
267 uint32_t types = FTYPE_BIOS|FTYPE_FCODE|FTYPE_EFI;
268 ql_fcache_t *fptr = ha->fcache;
269 int8_t *orv = &*attrs->option_rom_version;
270
271 while ((fptr != NULL) && (types != 0)) {
272 /* Get the next image */
273 if ((fptr = ql_get_fbuf(ha->fcache, types)) != NULL) {
274
275 switch (fptr->type) {
276 case FTYPE_FCODE:
277 (void) snprintf(orv,
278 FCHBA_OPTION_ROM_VERSION_LEN,
279 "%s fcode: %s;", orv, fptr->verstr);
280 break;
281 case FTYPE_BIOS:
282 (void) snprintf(orv,
283 FCHBA_OPTION_ROM_VERSION_LEN,
284 "%s BIOS: %s;", orv, fptr->verstr);
285 break;
286 case FTYPE_EFI:
287 (void) snprintf(orv,
288 FCHBA_OPTION_ROM_VERSION_LEN,
289 "%s EFI: %s;", orv, fptr->verstr);
290 break;
291 default:
292 EL(ha, "ignoring ftype: %xh\n",
293 fptr->type);
294 break;
295 }
296 types &= ~(fptr->type);
297 }
298 }
299 }
300
301 if (strlen(attrs->option_rom_version) == 0) {
302 int rval = -1;
303 uint32_t i = 0;
304 caddr_t fcode_ver_buf = NULL;
305
306 if (CFG_IST(ha, CFG_CTRL_22XX)) {
307 /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
308 rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
309 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version",
310 (caddr_t)&fcode_ver_buf, (int32_t *)&i);
311 }
312
313 (void) snprintf(attrs->option_rom_version,
314 FCHBA_OPTION_ROM_VERSION_LEN, "%s",
315 (rval == DDI_PROP_SUCCESS ? fcode_ver_buf :
316 "No boot image detected"));
317
318 if (fcode_ver_buf != NULL) {
319 kmem_free(fcode_ver_buf, (size_t)i);
320 }
321
322 }
323
324 attrs->vendor_specific_id = ha->adapter_features;
325 attrs->max_frame_size = ha->loginparams.common_service.rx_bufsize;
326 attrs->supported_cos = 0x10000000; /* Class 3 only */
327
328 switch (chip & 0xFF00) {
329 case 0x2000:
330 attrs->supported_speed = chip == 0x2071 ?
331 FC_HBA_PORTSPEED_32GBIT : FC_HBA_PORTSPEED_16GBIT;
332 break;
333 case 0x2200:
334 attrs->supported_speed = chip == 0x2261 ?
335 FC_HBA_PORTSPEED_16GBIT : FC_HBA_PORTSPEED_1GBIT;
336 break;
337 case 0x2300:
338 attrs->supported_speed = FC_HBA_PORTSPEED_2GBIT |
339 FC_HBA_PORTSPEED_1GBIT;
340 break;
341 case 0x2400:
342 case 0x8400:
343 attrs->supported_speed = FC_HBA_PORTSPEED_4GBIT |
344 FC_HBA_PORTSPEED_2GBIT | FC_HBA_PORTSPEED_1GBIT;
345 break;
346 case 0x8000:
347 attrs->supported_speed = FC_HBA_PORTSPEED_10GBIT;
348 break;
349 case 0x2500:
350 attrs->supported_speed = FC_HBA_PORTSPEED_8GBIT |
351 FC_HBA_PORTSPEED_4GBIT | FC_HBA_PORTSPEED_2GBIT |
352 FC_HBA_PORTSPEED_1GBIT;
353
354 /*
355 * Correct supported speeds based on type of
468
469 /*
470 * Populate the LV symbolic node and port name strings
471 *
472 * Symbolic node name format is:
473 * <hostname>
474 *
475 * Symbolic port name format is:
476 * <driver_name>(<instance>,<vp index>)
477 */
478 vlen = (strlen(utsname.nodename) > FCHBA_SYMB_NAME_LEN ?
479 FCHBA_SYMB_NAME_LEN : strlen(utsname.nodename));
480 (void) snprintf((int8_t *)attrs->sym_node_name, vlen, "%s",
481 utsname.nodename);
482
483 vlen = (strlen(QL_NAME) + 9 > FCHBA_SYMB_NAME_LEN ?
484 FCHBA_SYMB_NAME_LEN : strlen(QL_NAME) + 9);
485 (void) snprintf((int8_t *)attrs->sym_port_name, vlen,
486 "%s(%d,%d)", QL_NAME, ha->instance, ha->vp_index);
487
488 QL_PRINT_3(ha, "done\n");
489 }
490
491 /*
492 * ql_setup_fruinfo
493 * Generates common id's for instances on the same
494 * physical HBA.
495 *
496 * Input:
497 * ha = adapter state structure
498 *
499 * Returns:
500 *
501 * Context:
502 * Kernel context.
503 */
504 void
505 ql_setup_fruinfo(ql_adapter_state_t *ha)
506 {
507 uint32_t mybasedev_len;
508 ql_adapter_state_t *base_ha = NULL;
509
510 QL_PRINT_3(ha, "started\n");
511
512 /*
513 * To generate common id for instances residing on the
514 * the same HBA, the devpath for each instance is parsed
515 * and those instances which have matching base devpaths are
516 * given same hba_index, and each port on the same hba are
517 * then assigned unique port_indexs based on the devpath.
518 */
519
520 /*
521 * Get this ha's basedev path and its port index
522 */
523 if (ql_get_basedev_len(ha, &mybasedev_len, &ha->fru_port_index) == 0) {
524
525 /*
526 * Search for this basedev against all of the
527 * ha in the ql_hba global list. If found one
528 * then we are part of other adapter in the
529 * ql_hba list and hence use that ha's hba_index.
530 * If not create a new one from the global hba index.
531 */
532 base_ha = ql_search_basedev(ha, mybasedev_len);
533 if (base_ha != NULL && base_ha->fru_hba_index != 0) {
534 ha->fru_hba_index = base_ha->fru_hba_index;
535 ha->fru_port_index = base_ha->fru_port_index + 1;
536 } else {
537 ha->fru_hba_index = ql_gfru_hba_index++;
538 ha->fru_port_index = 0;
539 }
540 } else {
541 ha->fru_hba_index = 0;
542 ha->fru_port_index = 0;
543 }
544
545 QL_PRINT_3(ha, "done\n");
546 }
547
548 /*
549 * ql_get_basedev_len
550 *
551 * Gets the length of the base device name in the
552 * devpath of the current instance.
553 *
554 * Input:
555 * ha - adapter state pointer.
556 * basedev_len - pointer to the integer which
557 * holds the calculated length.
558 * port_index - pointer to the integer which
559 * contains the port index of
560 * for this device.
561 * Returns:
562 * 0 if successfully parsed, -1 otherwise.
563 *
564 * Context:
565 * Kernel context.
566 */
567 static uint32_t
568 ql_get_basedev_len(ql_adapter_state_t *ha, uint32_t *basedev_len,
569 uint32_t *port_index)
570 {
571 int32_t dev_off;
572 int32_t port_off;
573 int8_t *devstr;
574
575 QL_PRINT_3(ha, "started\n");
576
577 if (ha->devpath == NULL) {
578 return ((uint32_t)-1);
579 }
580
581 dev_off = (int32_t)(strlen(ha->devpath) - 1);
582 port_off = -1;
583
584 /* Until we reach the first char or a '@' char in the path */
585 while ((dev_off >= 0) && (ha->devpath[dev_off] != '@')) {
586
587 if (ha->devpath[dev_off] == ',') {
588 port_off = dev_off + 1;
589 }
590
591 dev_off--;
592 }
593
594 if (dev_off < 0) {
595 EL(ha, "Invalid device path '%s'. Cannot get basedev\n",
596 ha->devpath);
597 return ((uint32_t)-1);
598 }
599
600 if (port_off == -1) {
601 *port_index = 0;
602 *basedev_len = (uint32_t)strlen(ha->devpath);
603 } else {
604 /* Get the port index */
605 devstr = ha->devpath + port_off;
606 *port_index = stoi(&devstr);
607 if (*port_index == 0) {
608 EL(ha, "Invalid device path '%s'. Cannot get "
609 "port_index\n", ha->devpath);
610 return ((uint32_t)-1);
611 }
612
613 *basedev_len = (uint32_t)(port_off - 1);
614 }
615
616 QL_PRINT_3(ha, "done\n");
617
618 return (0);
619 }
620
621 /*
622 * ql_search_basedev
623 * Searches the list of ha instances to find which
624 * ha instance has same base device path as input's.
625 *
626 * Input:
627 * myha = current adapter state pointer.
628 * mybasedev_len = Length of the base device in the
629 * device path name.
630 *
631 * Returns:
632 * If match = ptr to matching ha structure.
633 * If no match = NULL ptr.
634 *
635 * Context:
636 * Kernel context.
637 */
638 static ql_adapter_state_t *
639 ql_search_basedev(ql_adapter_state_t *myha, uint32_t mybasedev_len)
640 {
641 ql_link_t *link;
642 ql_adapter_state_t *ha;
643 uint32_t basedev_len, port_index;
644
645 QL_PRINT_3(myha, "started\n", myha->instance);
646
647 for (link = ql_hba.first; link != NULL; link = link->next) {
648
649 ha = link->base_address;
650
651 if (ha == NULL) {
652 EL(myha, "null ha link detected!\n");
653 return (NULL);
654 }
655
656 if (ha == myha) {
657 continue;
658 }
659
660 if (ql_get_basedev_len(ha, &basedev_len, &port_index) != 0) {
661 if (ha->devpath == NULL) {
662 EL(myha, "Device path NULL. Unable to get "
663 "the basedev\n");
664 } else {
665 EL(myha, "Invalid device path '%s'. Cannot "
666 "get the hba index and port index\n",
667 ha->devpath);
668 }
669 continue;
670 }
671
672 /*
673 * If both the basedev len do not match, then it
674 * is obvious that both are not pointing to the
675 * same base device.
676 */
677 if ((basedev_len == mybasedev_len) && (strncmp(myha->devpath,
678 ha->devpath, basedev_len) == 0)) {
679
680 /* We found the ha with same basedev */
681 QL_PRINT_3(myha, "found, done\n",
682 myha->instance);
683 return (ha);
684 }
685 }
686
687 QL_PRINT_3(myha, "not found, done\n", myha->instance);
688
689 return (NULL);
690 }
|