1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte /*LINTLIBRARY*/
28*fcf3ce44SJohn Forte 
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte /*
31*fcf3ce44SJohn Forte  *	This module is part of fibre channel interface library.
32*fcf3ce44SJohn Forte  */
33*fcf3ce44SJohn Forte 
34*fcf3ce44SJohn Forte /*
35*fcf3ce44SJohn Forte  * I18N message number ranges
36*fcf3ce44SJohn Forte  *  This file: 11000 - 11499
37*fcf3ce44SJohn Forte  *  Shared common messages: 1 - 1999
38*fcf3ce44SJohn Forte  */
39*fcf3ce44SJohn Forte 
40*fcf3ce44SJohn Forte /* #define		_POSIX_SOURCE 1 */
41*fcf3ce44SJohn Forte 
42*fcf3ce44SJohn Forte /*	Includes	*/
43*fcf3ce44SJohn Forte #include	<stdlib.h>
44*fcf3ce44SJohn Forte #include	<stdio.h>
45*fcf3ce44SJohn Forte #include	<sys/file.h>
46*fcf3ce44SJohn Forte #include	<sys/errno.h>
47*fcf3ce44SJohn Forte #include	<sys/types.h>
48*fcf3ce44SJohn Forte #include	<sys/param.h>
49*fcf3ce44SJohn Forte #include	<sys/stat.h>
50*fcf3ce44SJohn Forte #include	<fcntl.h>
51*fcf3ce44SJohn Forte #include	<unistd.h>
52*fcf3ce44SJohn Forte #include	<errno.h>
53*fcf3ce44SJohn Forte #include	<string.h>
54*fcf3ce44SJohn Forte #include	<strings.h>
55*fcf3ce44SJohn Forte #include	<sys/sunddi.h>
56*fcf3ce44SJohn Forte #include	<sys/scsi/scsi.h>
57*fcf3ce44SJohn Forte #include	<nl_types.h>
58*fcf3ce44SJohn Forte #include	<l_common.h>
59*fcf3ce44SJohn Forte #include	<stgcom.h>
60*fcf3ce44SJohn Forte #include	<l_error.h>
61*fcf3ce44SJohn Forte #include	<g_state.h>
62*fcf3ce44SJohn Forte 
63*fcf3ce44SJohn Forte /* Forward declarations */
64*fcf3ce44SJohn Forte static int issue_lip(char *, int);
65*fcf3ce44SJohn Forte 
66*fcf3ce44SJohn Forte 
67*fcf3ce44SJohn Forte /*	Global variables	*/
68*fcf3ce44SJohn Forte extern	uchar_t		g_switch_to_alpa[];
69*fcf3ce44SJohn Forte extern	uchar_t		g_sf_alpa_to_switch[];
70*fcf3ce44SJohn Forte 
71*fcf3ce44SJohn Forte /*
72*fcf3ce44SJohn Forte  * starts a device.
73*fcf3ce44SJohn Forte  *
74*fcf3ce44SJohn Forte  * RETURNS:
75*fcf3ce44SJohn Forte  *	0	 if O.K.
76*fcf3ce44SJohn Forte  *	non-zero otherwise
77*fcf3ce44SJohn Forte  */
78*fcf3ce44SJohn Forte int
g_dev_start(char * drv_path,int verbose)79*fcf3ce44SJohn Forte g_dev_start(char *drv_path, int verbose)
80*fcf3ce44SJohn Forte {
81*fcf3ce44SJohn Forte int status;
82*fcf3ce44SJohn Forte 
83*fcf3ce44SJohn Forte 	if ((drv_path != NULL) && (*drv_path != '\0')) {
84*fcf3ce44SJohn Forte 		if (status = g_start(drv_path)) {
85*fcf3ce44SJohn Forte 			return (status);
86*fcf3ce44SJohn Forte 		}
87*fcf3ce44SJohn Forte 	}
88*fcf3ce44SJohn Forte 	return (L_INVALID_PATH);
89*fcf3ce44SJohn Forte }
90*fcf3ce44SJohn Forte 
91*fcf3ce44SJohn Forte 
92*fcf3ce44SJohn Forte 
93*fcf3ce44SJohn Forte /*
94*fcf3ce44SJohn Forte  * stops a device. If the device was
95*fcf3ce44SJohn Forte  * reserved by a host, it gets multiple
96*fcf3ce44SJohn Forte  * paths to the device and try to stop the
97*fcf3ce44SJohn Forte  * device using a different path.
98*fcf3ce44SJohn Forte  *
99*fcf3ce44SJohn Forte  * Returns:
100*fcf3ce44SJohn Forte  *	0 if OK
101*fcf3ce44SJohn Forte  *	-1 otherwise
102*fcf3ce44SJohn Forte  */
103*fcf3ce44SJohn Forte 
104*fcf3ce44SJohn Forte int
g_dev_stop(char * drv_path,struct wwn_list_struct * wwn_list,int verbose)105*fcf3ce44SJohn Forte g_dev_stop(char *drv_path, struct wwn_list_struct *wwn_list,
106*fcf3ce44SJohn Forte 						int verbose)
107*fcf3ce44SJohn Forte {
108*fcf3ce44SJohn Forte int		status, err;
109*fcf3ce44SJohn Forte char		*phys_path;
110*fcf3ce44SJohn Forte struct dlist	*ml = NULL;
111*fcf3ce44SJohn Forte 
112*fcf3ce44SJohn Forte 
113*fcf3ce44SJohn Forte 	/* stop the device */
114*fcf3ce44SJohn Forte 	/* Make the stop NOT immediate, so we wait. */
115*fcf3ce44SJohn Forte 	if ((drv_path == NULL) || (*drv_path == '\0')) {
116*fcf3ce44SJohn Forte 		return (L_INVALID_PATH);
117*fcf3ce44SJohn Forte 	}
118*fcf3ce44SJohn Forte 	if ((status = g_stop(drv_path, 0)) != 0) {
119*fcf3ce44SJohn Forte 		/*
120*fcf3ce44SJohn Forte 		 * In case of reservation conflict,
121*fcf3ce44SJohn Forte 		 * get the multiple paths and try to
122*fcf3ce44SJohn Forte 		 * stop the device through the path
123*fcf3ce44SJohn Forte 		 * which held the reservations.
124*fcf3ce44SJohn Forte 		 */
125*fcf3ce44SJohn Forte 		if ((status & ~L_SCSI_ERROR) == STATUS_RESERVATION_CONFLICT) {
126*fcf3ce44SJohn Forte 			if ((phys_path = g_get_physical_name(drv_path))
127*fcf3ce44SJohn Forte 								== NULL) {
128*fcf3ce44SJohn Forte 				return (L_INVALID_PATH);
129*fcf3ce44SJohn Forte 			}
130*fcf3ce44SJohn Forte 			if ((err = g_get_multipath(phys_path, &ml,
131*fcf3ce44SJohn Forte 						wwn_list, verbose)) != 0) {
132*fcf3ce44SJohn Forte 				return (err);
133*fcf3ce44SJohn Forte 			}
134*fcf3ce44SJohn Forte 			while (ml != NULL) {
135*fcf3ce44SJohn Forte 				if (g_stop(ml->logical_path, 0) == 0) {
136*fcf3ce44SJohn Forte 					(void) g_free_multipath(ml);
137*fcf3ce44SJohn Forte 					goto done;
138*fcf3ce44SJohn Forte 				}
139*fcf3ce44SJohn Forte 				ml = ml->next;
140*fcf3ce44SJohn Forte 			}
141*fcf3ce44SJohn Forte 			(void) g_free_multipath(ml);
142*fcf3ce44SJohn Forte 		}
143*fcf3ce44SJohn Forte 		return (status);
144*fcf3ce44SJohn Forte 	}
145*fcf3ce44SJohn Forte done:
146*fcf3ce44SJohn Forte 	return (0);
147*fcf3ce44SJohn Forte }
148*fcf3ce44SJohn Forte 
149*fcf3ce44SJohn Forte /*
150*fcf3ce44SJohn Forte  * This function is for Leadville devices only
151*fcf3ce44SJohn Forte  * It takes as input the actual path on which to issue the LIP and issues it
152*fcf3ce44SJohn Forte  *
153*fcf3ce44SJohn Forte  * INPUT :
154*fcf3ce44SJohn Forte  * Path to the FCA devctl node.
155*fcf3ce44SJohn Forte  *
156*fcf3ce44SJohn Forte  * For example,
157*fcf3ce44SJohn Forte  * /devices/pci@6,2000/pci@2/SUNW,qlc@4/fp@0,0:devctl
158*fcf3ce44SJohn Forte  *
159*fcf3ce44SJohn Forte  * No SCSI_VHCI paths will work. No checks are done and we'll let the ioctl
160*fcf3ce44SJohn Forte  * handle any failures if it is passed in.
161*fcf3ce44SJohn Forte  *
162*fcf3ce44SJohn Forte  * RETURNS:
163*fcf3ce44SJohn Forte  * 0 on Success
164*fcf3ce44SJohn Forte  * non-zero otherwise
165*fcf3ce44SJohn Forte  */
166*fcf3ce44SJohn Forte static int
issue_lip(char * fp_path,int verbose)167*fcf3ce44SJohn Forte issue_lip(char *fp_path, int verbose)
168*fcf3ce44SJohn Forte {
169*fcf3ce44SJohn Forte 	int		fp_fd;
170*fcf3ce44SJohn Forte 	la_wwn_t	wwn;
171*fcf3ce44SJohn Forte 	fcio_t		fcio;
172*fcf3ce44SJohn Forte 
173*fcf3ce44SJohn Forte 	/*
174*fcf3ce44SJohn Forte 	 * open fp path with exclusive path, otherwise,
175*fcf3ce44SJohn Forte 	 * FCIO_RESET_LINK ioctl will fail with permission
176*fcf3ce44SJohn Forte 	 * denied error.
177*fcf3ce44SJohn Forte 	 */
178*fcf3ce44SJohn Forte 	if ((fp_fd = g_object_open(fp_path, O_RDONLY | O_EXCL)) < 0) {
179*fcf3ce44SJohn Forte 		return (L_OPEN_PATH_FAIL);
180*fcf3ce44SJohn Forte 	}
181*fcf3ce44SJohn Forte 
182*fcf3ce44SJohn Forte 	if (verbose) {
183*fcf3ce44SJohn Forte 		(void) fprintf(stdout, MSGSTR(11001,
184*fcf3ce44SJohn Forte 			" Reinitializing the loop at:  %s\n"), fp_path);
185*fcf3ce44SJohn Forte 	}
186*fcf3ce44SJohn Forte 
187*fcf3ce44SJohn Forte 	fcio.fcio_cmd = FCIO_RESET_LINK;
188*fcf3ce44SJohn Forte 	fcio.fcio_xfer = FCIO_XFER_WRITE;
189*fcf3ce44SJohn Forte 	/*
190*fcf3ce44SJohn Forte 	 * Reset the local loop here (fcio_ibuf = 0).
191*fcf3ce44SJohn Forte 	 * Reset a remote loop on the Fabric by
192*fcf3ce44SJohn Forte 	 * passing its node wwn (fcio_len = sizeof(nwwn)
193*fcf3ce44SJohn Forte 	 * and fcio_ibuf = (caddr_t)&nwwn) to the port driver.
194*fcf3ce44SJohn Forte 	 */
195*fcf3ce44SJohn Forte 	(void) bzero((caddr_t)&wwn, sizeof (wwn));
196*fcf3ce44SJohn Forte 	fcio.fcio_ilen = sizeof (wwn);
197*fcf3ce44SJohn Forte 	fcio.fcio_ibuf = (caddr_t)&wwn;
198*fcf3ce44SJohn Forte 	if (g_issue_fcio_ioctl(fp_fd, &fcio, verbose) != 0) {
199*fcf3ce44SJohn Forte 		I_DPRINTF(" issue_lip: FCIO_RESET_LINK"
200*fcf3ce44SJohn Forte 			" ioctl failed: %s\n", fp_path);
201*fcf3ce44SJohn Forte 		(void) close(fp_fd);
202*fcf3ce44SJohn Forte 		return (L_FCIO_RESET_LINK_FAIL);
203*fcf3ce44SJohn Forte 	}
204*fcf3ce44SJohn Forte 	(void) close(fp_fd);
205*fcf3ce44SJohn Forte 	return (0);
206*fcf3ce44SJohn Forte }
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte /*
209*fcf3ce44SJohn Forte  * Issues the LIP (Loop Intialization Protocol)
210*fcf3ce44SJohn Forte  * on a nexus path (in case of socal) or on an
211*fcf3ce44SJohn Forte  * fp path (in case of fabric).
212*fcf3ce44SJohn Forte  *
213*fcf3ce44SJohn Forte  * RETURNS:
214*fcf3ce44SJohn Forte  *	0	 O.K.
215*fcf3ce44SJohn Forte  *	non-zero otherwise
216*fcf3ce44SJohn Forte  */
217*fcf3ce44SJohn Forte int
g_force_lip(char * path_phys,int verbose)218*fcf3ce44SJohn Forte g_force_lip(char *path_phys, int verbose)
219*fcf3ce44SJohn Forte {
220*fcf3ce44SJohn Forte int		fd, err = 0, i = 0, pathcnt = 0;
221*fcf3ce44SJohn Forte char		nexus_path[MAXPATHLEN], *nexus_path_ptr;
222*fcf3ce44SJohn Forte char		*charPtr, fp_path[MAXPATHLEN];
223*fcf3ce44SJohn Forte struct stat	stbuf;
224*fcf3ce44SJohn Forte uint_t		dev_type;
225*fcf3ce44SJohn Forte mp_pathlist_t	pathlist;
226*fcf3ce44SJohn Forte mp_pathinfo_t	*pinfop;
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte 	/* return invalid path if path_phys NULL */
229*fcf3ce44SJohn Forte 	if (path_phys == NULL) {
230*fcf3ce44SJohn Forte 		return (L_INVALID_PATH);
231*fcf3ce44SJohn Forte 	}
232*fcf3ce44SJohn Forte 
233*fcf3ce44SJohn Forte 	/* Make a copy of the arg passed in ... we'll need it down */
234*fcf3ce44SJohn Forte 	(void) strcpy(fp_path, path_phys);
235*fcf3ce44SJohn Forte 
236*fcf3ce44SJohn Forte 	if (strstr(path_phys, SCSI_VHCI) != NULL) {
237*fcf3ce44SJohn Forte 
238*fcf3ce44SJohn Forte 		/*
239*fcf3ce44SJohn Forte 		 * Its an MPXIO device path
240*fcf3ce44SJohn Forte 		 *
241*fcf3ce44SJohn Forte 		 * First, Get a list of all the pHCI for the given vHCI
242*fcf3ce44SJohn Forte 		 * Then issue a LIP on all the pHCI FCAs that are in the
244*fcf3ce44SJohn Forte 		 * states.
245*fcf3ce44SJohn Forte 		 */
246*fcf3ce44SJohn Forte 		if (g_get_pathlist(fp_path, &pathlist)) {
247*fcf3ce44SJohn Forte 			return (L_INVALID_PATH);
248*fcf3ce44SJohn Forte 		}
249*fcf3ce44SJohn Forte 		for (i = 0; i < pathlist.path_count; i++) {
250*fcf3ce44SJohn Forte 			pinfop = &pathlist.path_info[i];
251*fcf3ce44SJohn Forte 			if ((pinfop->path_state ==
252*fcf3ce44SJohn Forte 				MDI_PATHINFO_STATE_ONLINE) ||
253*fcf3ce44SJohn Forte 				    (pinfop->path_state ==
254*fcf3ce44SJohn Forte 					MDI_PATHINFO_STATE_STANDBY)) {
255*fcf3ce44SJohn Forte 				pathcnt++;
256*fcf3ce44SJohn Forte 				sprintf(fp_path, "%s%s",
257*fcf3ce44SJohn Forte 						pinfop->path_hba, FC_CTLR);
258*fcf3ce44SJohn Forte 				if (issue_lip(fp_path, verbose) != 0) {
259*fcf3ce44SJohn Forte 					err++;
260*fcf3ce44SJohn Forte 				}
261*fcf3ce44SJohn Forte 			}
262*fcf3ce44SJohn Forte 		}
263*fcf3ce44SJohn Forte 		free(pathlist.path_info);
264*fcf3ce44SJohn Forte 		if (err == 0)
265*fcf3ce44SJohn Forte 			return (0);
266*fcf3ce44SJohn Forte 		if (err == pathcnt)
267*fcf3ce44SJohn Forte 			return (L_FCIO_FORCE_LIP_FAIL);
268*fcf3ce44SJohn Forte 		return (L_FCIO_FORCE_LIP_PARTIAL_FAIL);
269*fcf3ce44SJohn Forte 	}
270*fcf3ce44SJohn Forte 
271*fcf3ce44SJohn Forte 	/* Non-MPXIO case */
272*fcf3ce44SJohn Forte 
273*fcf3ce44SJohn Forte 	if ((dev_type = g_get_path_type(fp_path)) == 0) {
274*fcf3ce44SJohn Forte 		return (L_INVALID_PATH);
275*fcf3ce44SJohn Forte 	}
276*fcf3ce44SJohn Forte 
277*fcf3ce44SJohn Forte 	if (dev_type & FC_FCA_MASK) {
278*fcf3ce44SJohn Forte 		if (strstr(fp_path, DRV_NAME_SSD) ||
279*fcf3ce44SJohn Forte 			strstr(fp_path, SES_NAME) ||
280*fcf3ce44SJohn Forte 			strstr(fp_path, DRV_NAME_ST)) {
281*fcf3ce44SJohn Forte 			if ((charPtr = strrchr(fp_path, '/')) == NULL) {
282*fcf3ce44SJohn Forte 				return (L_INVALID_PATH);
283*fcf3ce44SJohn Forte 			}
284*fcf3ce44SJohn Forte 			*charPtr = '\0';
285*fcf3ce44SJohn Forte 			/* append devctl to the path */
286*fcf3ce44SJohn Forte 			(void) strcat(fp_path, FC_CTLR);
287*fcf3ce44SJohn Forte 		} else {
288*fcf3ce44SJohn Forte 			/* should have fp transport node to continue. */
289*fcf3ce44SJohn Forte 			if (!(dev_type & FC_XPORT_MASK)) {
290*fcf3ce44SJohn Forte 				return (L_INVALID_PATH_TYPE);
291*fcf3ce44SJohn Forte 			}
292*fcf3ce44SJohn Forte 			if (stat(fp_path, &stbuf) < 0) {
293*fcf3ce44SJohn Forte 				return (L_LSTAT_ERROR);
294*fcf3ce44SJohn Forte 			}
295*fcf3ce44SJohn Forte 			if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
296*fcf3ce44SJohn Forte 				/* append devctl to the path */
297*fcf3ce44SJohn Forte 				(void) strcat(fp_path, FC_CTLR);
298*fcf3ce44SJohn Forte 			}
299*fcf3ce44SJohn Forte 		}
300*fcf3ce44SJohn Forte 		return (issue_lip(fp_path, verbose));
301*fcf3ce44SJohn Forte 
302*fcf3ce44SJohn Forte 	} else {	/* for fc4 devices */
303*fcf3ce44SJohn Forte 		if ((err = g_get_nexus_path(path_phys,
304*fcf3ce44SJohn Forte 					&nexus_path_ptr)) != 0)
305*fcf3ce44SJohn Forte 			return (err);
306*fcf3ce44SJohn Forte 
307*fcf3ce44SJohn Forte 		(void) strcpy(nexus_path, nexus_path_ptr);
308*fcf3ce44SJohn Forte 		(void) g_destroy_data(nexus_path_ptr);
309*fcf3ce44SJohn Forte 		P_DPRINTF("  g_force_lip: Force lip on:"
310*fcf3ce44SJohn Forte 			" Path %s\n", nexus_path);
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte 		/* open driver */
313*fcf3ce44SJohn Forte 		if ((fd = g_object_open(nexus_path,
314*fcf3ce44SJohn Forte 				O_NDELAY | O_RDONLY)) == -1)
315*fcf3ce44SJohn Forte 			return (L_OPEN_PATH_FAIL);
316*fcf3ce44SJohn Forte 
317*fcf3ce44SJohn Forte 		if (verbose) {
318*fcf3ce44SJohn Forte 			(void) fprintf(stdout,
319*fcf3ce44SJohn Forte 					MSGSTR(11000,
320*fcf3ce44SJohn Forte 					"  Forcing lip (Loop Initialization "
321*fcf3ce44SJohn Forte 					"Protocol)"
322*fcf3ce44SJohn Forte 					"\n  on loop at: %s\n"), nexus_path);
323*fcf3ce44SJohn Forte 		}
324*fcf3ce44SJohn Forte 		if (ioctl(fd, FCIO_FORCE_LIP) != 0) {
325*fcf3ce44SJohn Forte 			I_DPRINTF("  FCIO_FORCE_LIP ioctl failed.\n");
326*fcf3ce44SJohn Forte 			(void) close(fd);
327*fcf3ce44SJohn Forte 			return (L_FCIO_FORCE_LIP_FAIL);
328*fcf3ce44SJohn Forte 		}
329*fcf3ce44SJohn Forte 		(void) close(fd);
330*fcf3ce44SJohn Forte 	}
331*fcf3ce44SJohn Forte 	return (0);
332*fcf3ce44SJohn Forte }
333*fcf3ce44SJohn Forte 
334*fcf3ce44SJohn Forte 
335*fcf3ce44SJohn Forte 
336*fcf3ce44SJohn Forte /*
337*fcf3ce44SJohn Forte  * Takes one or more drives offline.
338*fcf3ce44SJohn Forte  * If the force flag is supplied then: (1) don't pass the exclusive flag
339*fcf3ce44SJohn Forte  * to the acquire routine and (2) allow the offline to fail
340*fcf3ce44SJohn Forte  * If any acquire fails, print an error message and continue.
341*fcf3ce44SJohn Forte  *
342*fcf3ce44SJohn Forte  * RETURNS:
343*fcf3ce44SJohn Forte  *	0		iff each offline succeeds
344*fcf3ce44SJohn Forte  *	non-zero	otherwise
345*fcf3ce44SJohn Forte  */
346*fcf3ce44SJohn Forte int
g_offline_drive(struct dlist * dl,int force_flag)347*fcf3ce44SJohn Forte g_offline_drive(struct dlist *dl, int force_flag)
348*fcf3ce44SJohn Forte {
349*fcf3ce44SJohn Forte devctl_hdl_t		devhdl;
350*fcf3ce44SJohn Forte 
351*fcf3ce44SJohn Forte 
352*fcf3ce44SJohn Forte 	/* for each drive attempt to take it offline */
353*fcf3ce44SJohn Forte 	for (; dl != NULL; dl = dl->next) {
354*fcf3ce44SJohn Forte 
355*fcf3ce44SJohn Forte 		/* attempt to acquire the device */
356*fcf3ce44SJohn Forte 		if ((devhdl = devctl_device_acquire(dl->dev_path,
357*fcf3ce44SJohn Forte 				force_flag ? 0 : DC_EXCL)) == NULL) {
358*fcf3ce44SJohn Forte 			if (errno != EBUSY) {
359*fcf3ce44SJohn Forte 				P_DPRINTF("%s: Could not acquire"
360*fcf3ce44SJohn Forte 					" the device: %s\n\n",
361*fcf3ce44SJohn Forte 					strerror(errno), dl->dev_path);
362*fcf3ce44SJohn Forte 				continue;
363*fcf3ce44SJohn Forte 			}
364*fcf3ce44SJohn Forte 		}
365*fcf3ce44SJohn Forte 		/* attempt to offline the drive */
366*fcf3ce44SJohn Forte 		if ((devctl_device_offline(devhdl) != 0) && !force_flag) {
367*fcf3ce44SJohn Forte 			(void) devctl_release(devhdl);
368*fcf3ce44SJohn Forte 			return (L_DEV_BUSY);
369*fcf3ce44SJohn Forte 		}
370*fcf3ce44SJohn Forte 
371*fcf3ce44SJohn Forte 		/* offline succeeded -- release handle acquired above */
372*fcf3ce44SJohn Forte 		(void) devctl_release(devhdl);
373*fcf3ce44SJohn Forte 	}
374*fcf3ce44SJohn Forte 
375*fcf3ce44SJohn Forte 	return (0);
376*fcf3ce44SJohn Forte }
377*fcf3ce44SJohn Forte 
378*fcf3ce44SJohn Forte 
379*fcf3ce44SJohn Forte 
380*fcf3ce44SJohn Forte /*
381*fcf3ce44SJohn Forte  * Brings one or more drives online.
382*fcf3ce44SJohn Forte  * If the force flag is supplied then: (1) don't pass the exclusive
383*fcf3ce44SJohn Forte  * flag to the acquire routine and (2) allow the offline to fail
384*fcf3ce44SJohn Forte  * If any acquire fails, continue with the next device.
385*fcf3ce44SJohn Forte  *
386*fcf3ce44SJohn Forte  * RETURNS:
387*fcf3ce44SJohn Forte  *	None.
388*fcf3ce44SJohn Forte  */
389*fcf3ce44SJohn Forte void
g_online_drive(struct dlist * dl,int force_flag)390*fcf3ce44SJohn Forte g_online_drive(struct dlist *dl, int force_flag)
391*fcf3ce44SJohn Forte {
392*fcf3ce44SJohn Forte devctl_hdl_t		devhdl;
393*fcf3ce44SJohn Forte 
394*fcf3ce44SJohn Forte 
395*fcf3ce44SJohn Forte 	while (dl != NULL) {
396*fcf3ce44SJohn Forte 		if ((devhdl = devctl_device_acquire(dl->dev_path,
397*fcf3ce44SJohn Forte 					force_flag ? 0 : DC_EXCL)) != NULL) {
398*fcf3ce44SJohn Forte 			(void) devctl_device_online(devhdl);
399*fcf3ce44SJohn Forte 			(void) devctl_release(devhdl);
400*fcf3ce44SJohn Forte 		}
401*fcf3ce44SJohn Forte 		dl = dl->next;
402*fcf3ce44SJohn Forte 	}
403*fcf3ce44SJohn Forte }
404*fcf3ce44SJohn Forte 
405*fcf3ce44SJohn Forte 
406*fcf3ce44SJohn Forte 
407*fcf3ce44SJohn Forte void
g_ll_to_str(uchar_t * wwn_ll,char * wwn_str)408*fcf3ce44SJohn Forte g_ll_to_str(uchar_t *wwn_ll, char	*wwn_str)
409*fcf3ce44SJohn Forte {
410*fcf3ce44SJohn Forte int	j, k, fnib, snib;
411*fcf3ce44SJohn Forte uchar_t	c;
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	for (j = 0, k = 0; j < 8; j++) {
414*fcf3ce44SJohn Forte 		c = wwn_ll[j];
415*fcf3ce44SJohn Forte 		fnib = ((int)(c & 0xf0) >> 4);
416*fcf3ce44SJohn Forte 		snib = (c & 0x0f);
417*fcf3ce44SJohn Forte 		if (fnib >= 0 && fnib <= 9)
418*fcf3ce44SJohn Forte 			wwn_str[k++] = '0' + fnib;
419*fcf3ce44SJohn Forte 		else if (fnib >= 10 && fnib <= 15)
420*fcf3ce44SJohn Forte 			wwn_str[k++] = 'a' + fnib - 10;
421*fcf3ce44SJohn Forte 		if (snib >= 0 && snib <= 9)
422*fcf3ce44SJohn Forte 			wwn_str[k++] = '0' + snib;
423*fcf3ce44SJohn Forte 		else if (snib >= 10 && snib <= 15)
424*fcf3ce44SJohn Forte 			wwn_str[k++] = 'a' + snib - 10;
425*fcf3ce44SJohn Forte 	}
426*fcf3ce44SJohn Forte 	wwn_str[k] = '\0';
427*fcf3ce44SJohn Forte }
428*fcf3ce44SJohn Forte 
429*fcf3ce44SJohn Forte 
430*fcf3ce44SJohn Forte 
431*fcf3ce44SJohn Forte /*
432*fcf3ce44SJohn Forte  * Creates a list of nexus paths for each
433*fcf3ce44SJohn Forte  * hotpluggable device and sends the list to g_force_lip(),
434*fcf3ce44SJohn Forte  * which forces the LIP on each nexus path in the list.
435*fcf3ce44SJohn Forte  *
436*fcf3ce44SJohn Forte  * RETURNS:
437*fcf3ce44SJohn Forte  *	None.
438*fcf3ce44SJohn Forte  */
439*fcf3ce44SJohn Forte int
g_forcelip_all(struct hotplug_disk_list * disk_list)440*fcf3ce44SJohn Forte g_forcelip_all(struct hotplug_disk_list *disk_list)
441*fcf3ce44SJohn Forte {
442*fcf3ce44SJohn Forte char		*p;
443*fcf3ce44SJohn Forte int		len, ndevs = 0, err = 0;
444*fcf3ce44SJohn Forte struct	dlist	*dl;
445*fcf3ce44SJohn Forte struct loop_list {	/* adp_name holds full dev path for MPXIO devices */
446*fcf3ce44SJohn Forte 		char adp_name[MAXPATHLEN];
447*fcf3ce44SJohn Forte 		struct loop_list *next;
448*fcf3ce44SJohn Forte 		struct loop_list *prev;
449*fcf3ce44SJohn Forte 	} *llist_head, *llist_tail, *llist, *llist1;
450*fcf3ce44SJohn Forte 
451*fcf3ce44SJohn Forte 	llist_head = llist_tail = NULL;
452*fcf3ce44SJohn Forte 
453*fcf3ce44SJohn Forte 	while (disk_list) {
454*fcf3ce44SJohn Forte 		if (disk_list->dev_location == SENA) {
455*fcf3ce44SJohn Forte 			dl = disk_list->seslist;
456*fcf3ce44SJohn Forte 		} else {
457*fcf3ce44SJohn Forte 			dl = disk_list->dlhead;
458*fcf3ce44SJohn Forte 		}
459*fcf3ce44SJohn Forte 		while (dl != NULL) {
460*fcf3ce44SJohn Forte 			if (strstr(dl->dev_path, SCSI_VHCI) == NULL) {
461*fcf3ce44SJohn Forte 				/* non-MPXIO device path */
462*fcf3ce44SJohn Forte 				if (disk_list->dev_location == SENA) {
463*fcf3ce44SJohn Forte 				    p = strstr(dl->dev_path, SLASH_SES);
464*fcf3ce44SJohn Forte 				} else {
465*fcf3ce44SJohn Forte 				    p = strstr(dl->dev_path, SLSH_DRV_NAME_SSD);
466*fcf3ce44SJohn Forte 				    if (p == NULL) {
467*fcf3ce44SJohn Forte 					p = strstr(dl->dev_path,
468*fcf3ce44SJohn Forte 							SLSH_DRV_NAME_ST);
469*fcf3ce44SJohn Forte 				    }
470*fcf3ce44SJohn Forte 				}
471*fcf3ce44SJohn Forte 				if (p == NULL) {
472*fcf3ce44SJohn Forte 					P_DPRINTF(
473*fcf3ce44SJohn Forte 					"  g_forcelip_all: Not able to do"
474*fcf3ce44SJohn Forte 					" LIP on this path because path "
475*fcf3ce44SJohn Forte 					"invalid.\n  Path: %s\n", dl->dev_path);
476*fcf3ce44SJohn Forte 					dl = dl->next;
477*fcf3ce44SJohn Forte 					continue;
478*fcf3ce44SJohn Forte 				}
479*fcf3ce44SJohn Forte 				len = strlen(dl->dev_path) - strlen(p);
480*fcf3ce44SJohn Forte 			} else {
481*fcf3ce44SJohn Forte 				/* MPXIO path */
482*fcf3ce44SJohn Forte 				len = strlen(dl->dev_path);
483*fcf3ce44SJohn Forte 			}
484*fcf3ce44SJohn Forte 
485*fcf3ce44SJohn Forte 			/*
486*fcf3ce44SJohn Forte 			 * Avoid issuing forcelip
487*fcf3ce44SJohn Forte 			 * on the same HA more than once
488*fcf3ce44SJohn Forte 			 */
489*fcf3ce44SJohn Forte 			if (llist_head != NULL) {
490*fcf3ce44SJohn Forte 				for (llist1 = llist_head; llist1 != NULL;
491*fcf3ce44SJohn Forte 						llist1 = llist1->next) {
492*fcf3ce44SJohn Forte 					if (strncmp(llist1->adp_name,
493*fcf3ce44SJohn Forte 						dl->dev_path, len) == 0) {
494*fcf3ce44SJohn Forte 						break;
495*fcf3ce44SJohn Forte 					}
496*fcf3ce44SJohn Forte 				}
497*fcf3ce44SJohn Forte 				if (llist1 != NULL) {
498*fcf3ce44SJohn Forte 					dl = dl->next;
499*fcf3ce44SJohn Forte 					continue;
500*fcf3ce44SJohn Forte 				}
501*fcf3ce44SJohn Forte 			}
502*fcf3ce44SJohn Forte 			if ((llist = (struct loop_list *)
503*fcf3ce44SJohn Forte 				g_zalloc(sizeof (struct loop_list))) == NULL)
504*fcf3ce44SJohn Forte 				return (L_MALLOC_FAILED);
505*fcf3ce44SJohn Forte 			(void) strncpy(llist->adp_name, dl->dev_path, len);
506*fcf3ce44SJohn Forte 			llist->adp_name[len] = '\0';
507*fcf3ce44SJohn Forte 			ndevs++;
508*fcf3ce44SJohn Forte 
509*fcf3ce44SJohn Forte 			if (llist_head == NULL) {
510*fcf3ce44SJohn Forte 				llist_head = llist_tail = llist;
511*fcf3ce44SJohn Forte 			} else {
512*fcf3ce44SJohn Forte 				llist->prev = llist_tail;
513*fcf3ce44SJohn Forte 				llist_tail = llist_tail->next = llist;
514*fcf3ce44SJohn Forte 			}
515*fcf3ce44SJohn Forte 			dl = dl->next;
516*fcf3ce44SJohn Forte 		}
517*fcf3ce44SJohn Forte 		disk_list = disk_list->next;
518*fcf3ce44SJohn Forte 	}
519*fcf3ce44SJohn Forte 
520*fcf3ce44SJohn Forte 	while (llist_head) {
521*fcf3ce44SJohn Forte 		if ((err = g_force_lip(llist_head->adp_name, 0)) != 0) {
522*fcf3ce44SJohn Forte 			(void) g_destroy_data(llist);
523*fcf3ce44SJohn Forte 			(void) g_destroy_data(llist_head);
524*fcf3ce44SJohn Forte 			return (err);
525*fcf3ce44SJohn Forte 		}
526*fcf3ce44SJohn Forte 		llist = llist_head;
527*fcf3ce44SJohn Forte 		llist_head = llist_head->next;
528*fcf3ce44SJohn Forte 		(void) g_destroy_data((char *)llist);
529*fcf3ce44SJohn Forte 	}
530*fcf3ce44SJohn Forte 	(void) sleep(ndevs*10);
531*fcf3ce44SJohn Forte 	return (0);
532*fcf3ce44SJohn Forte }