1 /*
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 /*
29  * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
30  *
31  * ***********************************************************************
32  * *									**
33  * *				NOTICE					**
34  * *		COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION		**
35  * *			ALL RIGHTS RESERVED				**
36  * *									**
37  * ***********************************************************************
38  *
39  */
40 
41 /*
42  * Determine HBA FRU card information for T11 FC-HBA
43  */
44 
45 #include <ql_apps.h>
46 #include <ql_api.h>
47 #include <ql_debug.h>
48 #include <ql_ioctl.h>
49 #include <ql_xioctl.h>
50 
51 /*
52  * Temporary define until LV headers are updated
53  */
54 #ifndef	FC_HBA_PORTSPEED_8GBIT
55 #define	FC_HBA_PORTSPEED_8GBIT		16    /* 8 GBit/sec */
56 #endif
57 
58 /* Local prototypes */
59 static uint32_t ql_get_basedev_len(ql_adapter_state_t *, uint32_t *,
60     uint32_t *);
61 static ql_adapter_state_t *ql_search_basedev(ql_adapter_state_t *, uint32_t);
62 
63 /* Local structures */
64 static struct ql_known_models {
65 	uint16_t    ssid;		/* Subsystem ID */
66 	uint16_t    ssvid;		/* Subsystem Vendor ID */
67 	char	    model[256];
68 	char	    model_description[256];
69 
70 } models[] = {
71 	{
72 	    /* QLogic */
73 	    0x2, 0x1077, "QLA2200", "QLogic PCI to 1Gb FC, Single Channel"
74 	}, {
75 	    /* QLogic */
76 	    0x9, 0x1077, "QLA2300", "QLogic PCI to 2Gb FC, Single Channel"
77 	}, {
78 	    /* QLA2200, SUN2200 Amber */
79 	    0x4082, 0x1077, "375-3019-xx", "X6799A"
80 	}, {
81 	    /* QLA2212, SUN2212 Crystal+ */
82 	    0x4083, 0x1077, "375-3030-xx", "X6727A"
83 	}, {
84 	    /* QCP2202, SUNQCP2202 Diamond */
85 	    0x4084, 0x1077, "375-0118-xx", "X6748A"
86 	}, {
87 	    /* QLA2202FS, SUN2202FS Ivory */
88 	    0x4085, 0x1077, "375-3048-xx", "X6757A"
89 	}, {
90 	    /* QLogic */
91 	    0x100, 0x1077, "QLA2340",
92 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
93 	}, {
94 	    /* QLogic */
95 	    0x101, 0x1077, "QLA2342",
96 	    "QLogic 133MHz PCI-X to 2Gb FC, Dual Channel"
97 	}, {
98 	    /* QLogic */
99 	    0x102, 0x1077, "QLA2344",
100 	    "QLogic 133MHz PCI-X to 2Gb FC, Quad Channel"
101 	}, {
102 	    /* QLogic */
103 	    0x103, 0x1077, "QCP2342", "QLogic cPCI to 2Gb FC, Dual Channel"
104 	}, {
105 	    /* QLogic */
106 	    0x104, 0x1077, "QSB2340", "QLogic SBUS to 2Gb FC, Single Channel"
107 	}, {
108 	    /* QLogic */
109 	    0x105, 0x1077, "QSB2342", "QLogic SBUS to 2Gb FC, Dual Channel"
110 	}, {
111 	    /* QLA2310, SUN-66MHz PCI-X to 2Gb FC, Single Channel, Amber 2 */
112 	    0x0106, 0x1077, "375-3102-xx", "SG-XPCI1FC-QF2 (X6767A)"
113 	}, {
114 	    /* QLogic */
115 	    0x109, 0x1077, "QCP2340", "QLogic cPCI to 2Gb FC, Single Channel"
116 	}, {
117 	    /* QLA2342, SUN-133MHz PCI-X to 2Gb FC, Dualchannel, Crystal 2A */
118 	    0x010A, 0x1077, "375-3108-xx", "SG-XPCI2FC-QF2 (X6768A)"
119 	}, {
120 	    /* QLogic */
121 	    0x115, 0x1077, "QLA2360",
122 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
123 	}, {
124 	    /* QLogic */
125 	    0x116, 0x1077, "QLA2362",
126 	    "QLogic 133MHz PCI-X to 2Gb FC, Dual Channel"
127 	}, {
128 	    /* QLogic */
129 	    0x117, 0x1077, "QLE2360",
130 	    "QLogic PCI-Express to 2Gb FC, Single Channel"
131 	}, {
132 	    /* QLogic */
133 	    0x118, 0x1077, "QLE2362",
134 	    "QLogic PCI Express to 2Gb FC, Dual Channel"
135 	}, {
136 	    /* QLogic */
137 	    0x119, 0x1077, "QLA200",
138 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
139 	}, {
140 	    /* QLogic */
141 	    0x11c, 0x1077, "QLA200P",
142 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
143 	}, {
144 	    /* QLogic */
145 	    0x12f, 0x1077, "QLA210",
146 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
147 	}, {
148 	    /* QLogic */
149 	    0x130, 0x1077, "EMC250-051-900",
150 	    "QLogic 133MHz PCI-X to 2Gb FC, Single Channel"
151 	}, {
152 	    /* QLA210, SUN-133MHz PCI-X to 2Gb FC, Single Channel, Prism */
153 	    0x132, 0x1077, "375-32X3-01", "SG-PCI1FC-QLC"
154 	}, {
155 	    /* QLogic */
156 	    0x13e, 0x1077, "QLE210",
157 	    "QLogic PCI Express 2Gb FC, Single Channel"
158 	}, {
159 	    /* Sun */
160 	    0x149, 0x1077, "QLA2340",
161 	    "SUN - 133MHz PCI-X to 2Gb FC, Single Channel"
162 	}, {
163 	    /* HP */
164 	    0x100, 0x0e11, "QLA2340-HP", "PCIX to 2Gb FC, Single Channel"
165 	}, {
166 	    /* HP */
167 	    0x101, 0x0e11, "QLA2342-HP", "PCIX to 2Gb FC, Dual Channel"
168 	}, {
169 	    /* HP */
170 	    0x103, 0x0e11, "QLA2312-HP",
171 	    "HP Bladed Server Balcony Card - HP BalcnL"
172 	}, {
173 	    /* HP */
174 	    0x104, 0x0e11, "QLA2312-HP", "HP Bladed Server - HP MezzF"
175 	}, {
176 	    /* HP */
177 	    0x105, 0x0e11, "QLA2312-HP", "HP Bladed Server - HP BalcnL"
178 	}, {
179 	    /* HP */
180 	    0x106, 0x0e11, "QLA2312-HP", "HP Bladed Server - HP BalcnF"
181 	}, {
182 	    /* HP */
183 	    0x107, 0x0e11, "QLA2312-HP", "HP Bladed Server"
184 	}, {
185 	    /* HP */
186 	    0x108, 0x0e11, "QLA2312-HP", "HP Bladed Server"
187 	}, {
188 	    /* IBM FCEC */
189 	    0x27d, 0x1014, "IBM-FCEC",
190 	    "IBM eServer Blade Center FC Expansion Card"
191 	}, {
192 	    /* IBM FCEC */
193 	    0x2fb, 0x1014, "IBM-FCEC",
194 	    "IBM eServer Blade Center FC SFF Expansion Card"
195 	}, {
196 	    /* Intel */
197 	    0x34ba, 0x8086, "Intel SBFCM",
198 	    "Intel Server FC Expansion Card SBFCM"
199 	}, {
200 	    /* Intel */
201 	    0x34a0, 0x8086, "Intel SBEFCM",
202 	    "Intel Server SFF FC Expansion Card SBFCM"
203 	}, {
204 	    /* FCI/O */
205 	    0x1051, 0x1734, "FCI/O-CARD2Gb/s",
206 	    "FSC-Quanta FC I/O-Card 2GBit/s"
207 	}, {
208 	    /* Dell */
209 	    0x18a, 0x1028, "FCI/O-CARD2Gb/s", "Dell Glacier Blade Server"
210 	}, {
211 	    /* end of list */
212 	    0, 0, 0, 0, 0, 0
213 	} };
214 
215 /*
216  * ql_populate_hba_fru_details
217  *	Sets up HBA fru information for UL utilities
218  *	(cfgadm, fcinfo, et. al.)
219  *
220  * Input:
221  *	ha		= adapter state structure
222  *	port_info	= ptr to LV port strcture.
223  *
224  * Returns:
225  *
226  * Context:
227  *	Kernel context.
228  */
229 void
ql_populate_hba_fru_details(ql_adapter_state_t * ha,fc_fca_port_info_t * port_info)230 ql_populate_hba_fru_details(ql_adapter_state_t *ha,
231     fc_fca_port_info_t *port_info)
232 {
233 	fca_port_attrs_t	*attrs = &port_info->pi_attrs;
234 	uint16_t		chip = ha->device_id;
235 	uint16_t		model = ha->subsys_id;
236 	uint16_t		ssdevid = ha->subven_id;
237 	size_t			vlen;
238 	int32_t			i;
239 
240 	QL_PRINT_3(ha, "started\n");
241 
242 	attrs = &port_info->pi_attrs;
243 
244 	/* Constants */
245 	(void) snprintf(attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
246 	    "QLogic Corp.");
247 	(void) snprintf(attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
248 	    "%s", QL_NAME);
249 	(void) snprintf(attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
250 	    "%s", ha->adapter_stats->revlvl.qlddv);
251 
252 	if ((i = ql_vpd_lookup(ha, (uint8_t *)VPD_TAG_SN, (uint8_t *)
253 	    attrs->serial_number, FCHBA_SERIAL_NUMBER_LEN)) == -1) {
254 		attrs->serial_number[0] = '\0';
255 	}
256 	attrs->hardware_version[0] = '\0';
257 
258 	/* Dynamic data */
259 	(void) snprintf(attrs->firmware_version, FCHBA_FIRMWARE_VERSION_LEN,
260 	    "%02d.%02d.%02d", ha->fw_major_version, ha->fw_minor_version,
261 	    ha->fw_subminor_version);
262 
263 	/* Report FCode / BIOS / EFI version(s). */
264 	if (ha->fcache != NULL) {
265 		uint32_t	types = FTYPE_BIOS|FTYPE_FCODE|FTYPE_EFI;
266 		ql_fcache_t	*fptr = ha->fcache;
267 		int8_t		*orv = &*attrs->option_rom_version;
268 
269 		while ((fptr != NULL) && (types != 0)) {
270 			/* Get the next image */
271 			if ((fptr = ql_get_fbuf(ha->fcache, types)) != NULL) {
272 
273 				switch (fptr->type) {
274 				case FTYPE_FCODE:
275 					(void) snprintf(orv,
276 					    FCHBA_OPTION_ROM_VERSION_LEN,
277 					    "%s fcode: %s;", orv, fptr->verstr);
278 					break;
279 				case FTYPE_BIOS:
280 					(void) snprintf(orv,
281 					    FCHBA_OPTION_ROM_VERSION_LEN,
282 					    "%s BIOS: %s;", orv, fptr->verstr);
283 					break;
284 				case FTYPE_EFI:
285 					(void) snprintf(orv,
286 					    FCHBA_OPTION_ROM_VERSION_LEN,
287 					    "%s EFI: %s;", orv, fptr->verstr);
288 					break;
289 				default:
290 					EL(ha, "ignoring ftype: %xh\n",
291 					    fptr->type);
292 					break;
293 				}
294 				types &= ~(fptr->type);
295 			}
296 		}
297 	}
298 
299 	if (strlen(attrs->option_rom_version) == 0) {
300 		int		rval = -1;
301 		uint32_t	i = 0;
302 		caddr_t		fcode_ver_buf = NULL;
303 
304 		if (CFG_IST(ha, CFG_CTRL_22XX)) {
305 			/*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
306 			rval = ddi_getlongprop(DDI_DEV_T_ANY, ha->dip,
307 			    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version",
308 			    (caddr_t)&fcode_ver_buf, (int32_t *)&i);
309 		}
310 
311 		(void) snprintf(attrs->option_rom_version,
312 		    FCHBA_OPTION_ROM_VERSION_LEN, "%s",
313 		    (rval == DDI_PROP_SUCCESS ? fcode_ver_buf :
314 		    "No boot image detected"));
315 
316 		if (fcode_ver_buf != NULL) {
317 			kmem_free(fcode_ver_buf, (size_t)i);
318 		}
319 
320 	}
321 
322 	attrs->vendor_specific_id = ha->adapter_features;
323 	attrs->max_frame_size = ha->loginparams.common_service.rx_bufsize;
324 	attrs->supported_cos = 0x10000000; /* Class 3 only */
325 
326 	switch (chip & 0xFF00) {
327 	case 0x2000:
328 		attrs->supported_speed = chip == 0x2071 ?
329 		    FC_HBA_PORTSPEED_32GBIT : FC_HBA_PORTSPEED_16GBIT;
330 		break;
331 	case 0x2200:
332 		attrs->supported_speed = chip == 0x2261 ?
333 		    FC_HBA_PORTSPEED_16GBIT : FC_HBA_PORTSPEED_1GBIT;
334 		break;
335 	case 0x2300:
336 		attrs->supported_speed = FC_HBA_PORTSPEED_2GBIT |
337 		    FC_HBA_PORTSPEED_1GBIT;
338 		break;
339 	case 0x2400:
340 	case 0x8400:
341 		attrs->supported_speed = FC_HBA_PORTSPEED_4GBIT |
342 		    FC_HBA_PORTSPEED_2GBIT | FC_HBA_PORTSPEED_1GBIT;
343 		break;
344 	case 0x8000:
345 		attrs->supported_speed = FC_HBA_PORTSPEED_10GBIT;
346 		break;
347 	case 0x2500:
348 		attrs->supported_speed = FC_HBA_PORTSPEED_8GBIT |
349 		    FC_HBA_PORTSPEED_4GBIT | FC_HBA_PORTSPEED_2GBIT |
350 		    FC_HBA_PORTSPEED_1GBIT;
351 
352 		/*
353 		 * Correct supported speeds based on type of
354 		 * sfp that is present
355 		 */
356 		switch (ha->sfp_stat) {
357 		case 2:
358 		case 4:
359 			/* 4GB sfp */
360 			attrs->supported_speed &= ~FC_HBA_PORTSPEED_8GBIT;
361 			break;
362 		case 3:
363 		case 5:
364 			/* 8GB sfp */
365 			attrs->supported_speed &= ~FC_HBA_PORTSPEED_1GBIT;
366 			break;
367 		default:
368 			EL(ha, "sfp_stat: %xh\n", ha->sfp_stat);
369 			break;
370 
371 		}
372 
373 		break;
374 	case 0x5400:
375 		if (model == 0x13e) {
376 			/* QLE210 */
377 			attrs->supported_speed = FC_HBA_PORTSPEED_2GBIT;
378 		} else {
379 			attrs->supported_speed = FC_HBA_PORTSPEED_4GBIT;
380 		}
381 		break;
382 	case 0x6300:
383 		attrs->supported_speed = FC_HBA_PORTSPEED_2GBIT;
384 		break;
385 	default:
386 		attrs->supported_speed = FC_HBA_PORTSPEED_UNKNOWN;
387 		break;
388 	}
389 
390 	/* Use parent dip as adapter identifier */
391 	attrs->hba_fru_details.low = 0x514C6F6769630000; /* QLogic */
392 
393 	if (ha->fru_hba_index == 0) {
394 		EL(ha, "unable to generate high_fru details from "
395 		    "device path: %s\n", ha->devpath);
396 		attrs->hba_fru_details.low = 0;
397 		attrs->hba_fru_details.high = 0;
398 		attrs->hba_fru_details.port_index = 0;
399 	} else {
400 		attrs->hba_fru_details.high = ha->fru_hba_index;
401 		attrs->hba_fru_details.port_index = ha->fru_port_index;
402 	}
403 
404 	/*
405 	 * Populate the model info. Legacy (22xx, 23xx, 63xx) do not
406 	 * have vpd info, so use the hard coded table. Anything else
407 	 * has VPD (or is suppose to have VPD), so use that. For both
408 	 * cases, if the model isn't found, use defaults.
409 	 */
410 
411 	switch (chip & 0xFF00) {
412 	case 0x2200:
413 	case 0x2300:
414 	case 0x6300:
415 		/* Table based data */
416 		for (i = 0; models[i].ssid; i++) {
417 			if ((model == models[i].ssid) &&
418 			    (ssdevid == models[i].ssvid)) {
419 				break;
420 			}
421 		}
422 
423 		if (models[i].ssid) {
424 			(void) snprintf(attrs->model, FCHBA_MODEL_LEN, "%s",
425 			    models[i].model);
426 			(void) snprintf(attrs->model_description,
427 			    FCHBA_MODEL_DESCRIPTION_LEN, "%s",
428 			    models[i].model_description);
429 		} else {
430 			(void) snprintf(attrs->model, FCHBA_MODEL_LEN,
431 			    "%x", chip);
432 			(void) snprintf(attrs->model_description,
433 			    FCHBA_MODEL_DESCRIPTION_LEN, "%x", chip);
434 		}
435 
436 		/* Special model handling for RoHS version of the HBA */
437 		if (models[i].ssid == 0x10a && ha->adapInfo[10] ==
438 		    (uint8_t)0x36) {
439 			(void) snprintf(attrs->model, FCHBA_MODEL_LEN, "%s",
440 			    "375-3363-xx");
441 			(void) snprintf(attrs->model_description,
442 			    FCHBA_MODEL_DESCRIPTION_LEN, "%s",
443 			    "SG-XPCI2FC-QF2-Z");
444 		}
445 		break;
446 
447 	case 0x2400:
448 	case 0x2500:
449 	case 0x5400:
450 	case 0x8400:
451 	case 0x8000:
452 	default:
453 		if ((i = ql_vpd_lookup(ha, (uint8_t *)VPD_TAG_PN,
454 		    (uint8_t *)attrs->model, FCHBA_MODEL_LEN)) >= 0) {
455 			(void) ql_vpd_lookup(ha, (uint8_t *)VPD_TAG_PRODID,
456 			    (uint8_t *)attrs->model_description,
457 			    FCHBA_MODEL_DESCRIPTION_LEN);
458 		} else {
459 			(void) snprintf(attrs->model, FCHBA_MODEL_LEN,
460 			    "%x", chip);
461 			(void) snprintf(attrs->model_description,
462 			    FCHBA_MODEL_DESCRIPTION_LEN, "%x", chip);
463 		}
464 		break;
465 	}
466 
467 	/*
468 	 * Populate the LV symbolic node and port name strings
469 	 *
470 	 * Symbolic node name format is:
471 	 *	<hostname>
472 	 *
473 	 * Symbolic port name format is:
474 	 *	<driver_name>(<instance>,<vp index>)
475 	 */
476 	vlen = (strlen(utsname.nodename) > FCHBA_SYMB_NAME_LEN ?
477 	    FCHBA_SYMB_NAME_LEN : strlen(utsname.nodename));
478 	(void) snprintf((int8_t *)attrs->sym_node_name, vlen, "%s",
479 	    utsname.nodename);
480 
481 	vlen = (strlen(QL_NAME) + 9 > FCHBA_SYMB_NAME_LEN ?
482 	    FCHBA_SYMB_NAME_LEN : strlen(QL_NAME) + 9);
483 	(void) snprintf((int8_t *)attrs->sym_port_name, vlen,
484 	    "%s(%d,%d)", QL_NAME, ha->instance, ha->vp_index);
485 
486 	QL_PRINT_3(ha, "done\n");
487 }
488 
489 /*
490  * ql_setup_fruinfo
491  *	Generates common id's for instances on the same
492  *	physical HBA.
493  *
494  * Input:
495  *	ha =  adapter state structure
496  *
497  * Returns:
498  *
499  * Context:
500  *	Kernel context.
501  */
502 void
ql_setup_fruinfo(ql_adapter_state_t * ha)503 ql_setup_fruinfo(ql_adapter_state_t *ha)
504 {
505 	uint32_t		mybasedev_len;
506 	ql_adapter_state_t	*base_ha = NULL;
507 
508 	QL_PRINT_3(ha, "started\n");
509 
510 	/*
511 	 * To generate common id for instances residing on the
512 	 * the same HBA, the devpath for each instance is parsed
513 	 * and those instances which have matching base devpaths are
514 	 * given same hba_index, and each port on the same hba are
515 	 * then assigned unique port_indexs based on the devpath.
516 	 */
517 
518 	/*
519 	 * Get this ha's basedev path and its port index
520 	 */
521 	if (ql_get_basedev_len(ha, &mybasedev_len, &ha->fru_port_index) == 0) {
522 
523 		/*
524 		 * Search for this basedev against all of the
525 		 * ha in the ql_hba global list. If found one
526 		 * then we are part of other adapter in the
527 		 * ql_hba list and hence use that ha's hba_index.
528 		 * If not create a new one from the global hba index.
529 		 */
530 		base_ha = ql_search_basedev(ha, mybasedev_len);
531 		if (base_ha != NULL && base_ha->fru_hba_index != 0) {
532 			ha->fru_hba_index = base_ha->fru_hba_index;
533 			ha->fru_port_index = base_ha->fru_port_index + 1;
534 		} else {
535 			ha->fru_hba_index = ql_gfru_hba_index++;
536 			ha->fru_port_index = 0;
537 		}
538 	} else {
539 		ha->fru_hba_index = 0;
540 		ha->fru_port_index = 0;
541 	}
542 
543 	QL_PRINT_3(ha, "done\n");
544 }
545 
546 /*
547  *  ql_get_basedev_len
548  *
549  *	Gets the length of the base device name in the
550  *	devpath of the current instance.
551  *
552  * Input:
553  *	ha		- adapter state pointer.
554  *	basedev_len	- pointer to the integer which
555  *			  holds the calculated length.
556  *	port_index	- pointer to the integer which
557  *			  contains the port index of
558  *			  for this device.
559  * Returns:
560  *	0 if successfully parsed, -1 otherwise.
561  *
562  * Context:
563  *	Kernel context.
564  */
565 static uint32_t
ql_get_basedev_len(ql_adapter_state_t * ha,uint32_t * basedev_len,uint32_t * port_index)566 ql_get_basedev_len(ql_adapter_state_t *ha, uint32_t *basedev_len,
567     uint32_t *port_index)
568 {
569 	int32_t		dev_off;
570 	int32_t		port_off;
571 	int8_t		*devstr;
572 
573 	QL_PRINT_3(ha, "started\n");
574 
575 	if (ha->devpath == NULL) {
576 		return ((uint32_t)-1);
577 	}
578 
579 	dev_off = (int32_t)(strlen(ha->devpath) - 1);
580 	port_off = -1;
581 
582 	/* Until we reach the first char or a '@' char in the path */
583 	while ((dev_off >= 0) && (ha->devpath[dev_off] != '@')) {
584 
585 		if (ha->devpath[dev_off] == ',') {
586 			port_off = dev_off + 1;
587 		}
588 
589 		dev_off--;
590 	}
591 
592 	if (dev_off < 0) {
593 		EL(ha, "Invalid device path '%s'. Cannot get basedev\n",
594 		    ha->devpath);
595 		return ((uint32_t)-1);
596 	}
597 
598 	if (port_off == -1) {
599 		*port_index = 0;
600 		*basedev_len = (uint32_t)strlen(ha->devpath);
601 	} else {
602 		/* Get the port index */
603 		devstr = ha->devpath + port_off;
604 		*port_index = stoi(&devstr);
605 		if (*port_index == 0) {
606 			EL(ha, "Invalid device path '%s'. Cannot get "
607 			    "port_index\n", ha->devpath);
608 			return ((uint32_t)-1);
609 		}
610 
611 		*basedev_len = (uint32_t)(port_off - 1);
612 	}
613 
614 	QL_PRINT_3(ha, "done\n");
615 
616 	return (0);
617 }
618 
619 /*
620  * ql_search_basedev
621  *	Searches the list of ha instances to find which
622  *	ha instance has same base device path as input's.
623  *
624  * Input:
625  *	myha 		= current adapter state pointer.
626  *	mybasedev_len	= Length of the base device in the
627  *			  device path name.
628  *
629  * Returns:
630  *	If match	= ptr to matching ha structure.
631  *	If no match	= NULL ptr.
632  *
633  * Context:
634  *	Kernel context.
635  */
636 static ql_adapter_state_t *
ql_search_basedev(ql_adapter_state_t * myha,uint32_t mybasedev_len)637 ql_search_basedev(ql_adapter_state_t *myha, uint32_t mybasedev_len)
638 {
639 	ql_link_t		*link;
640 	ql_adapter_state_t	*ha;
641 	uint32_t		basedev_len, port_index;
642 
643 	QL_PRINT_3(myha, "started\n", myha->instance);
644 
645 	for (link = ql_hba.first; link != NULL; link = link->next) {
646 
647 		ha = link->base_address;
648 
649 		if (ha == NULL) {
650 			EL(myha, "null ha link detected!\n");
651 			return (NULL);
652 		}
653 
654 		if (ha == myha) {
655 			continue;
656 		}
657 
658 		if (ql_get_basedev_len(ha, &basedev_len, &port_index) != 0) {
659 			if (ha->devpath == NULL) {
660 				EL(myha, "Device path NULL. Unable to get "
661 				    "the basedev\n");
662 			} else {
663 				EL(myha, "Invalid device path '%s'. Cannot "
664 				    "get the hba index and port index\n",
665 				    ha->devpath);
666 			}
667 			continue;
668 		}
669 
670 		/*
671 		 * If both the basedev len do not match, then it
672 		 * is obvious that both are not pointing to the
673 		 * same base device.
674 		 */
675 		if ((basedev_len == mybasedev_len) && (strncmp(myha->devpath,
676 		    ha->devpath, basedev_len) == 0)) {
677 
678 			/* We found the ha with same basedev */
679 			QL_PRINT_3(myha, "found, done\n",
680 			    myha->instance);
681 			return (ha);
682 		}
683 	}
684 
685 	QL_PRINT_3(myha, "not found, done\n", myha->instance);
686 
687 	return (NULL);
688 }
689