1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
225295a27aSJack Meng  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
2461dfa509SRick McNeal  */
2561dfa509SRick McNeal 
2661dfa509SRick McNeal /*
2761dfa509SRick McNeal  * Copyright 2019 Nexenta Systems, Inc.
28*3fe80ca4SDan Cross  * Copyright 2023 Oxide Computer Company
2961dfa509SRick McNeal  */
3061dfa509SRick McNeal 
3161dfa509SRick McNeal /*
32fcf3ce44SJohn Forte  * iSCSI logical unit interfaces
33fcf3ce44SJohn Forte  */
34fcf3ce44SJohn Forte 
35fcf3ce44SJohn Forte #include "iscsi.h"
366cefaae1SJack Meng #include <sys/bootprops.h>
37c60a6da3Sbing zhao - Sun Microsystems - Beijing China #include <sys/sysevent/eventdefs.h>
38c60a6da3Sbing zhao - Sun Microsystems - Beijing China #include <sys/sysevent/dev.h>
39fcf3ce44SJohn Forte 
40fcf3ce44SJohn Forte /* tpgt bytes in string form */
41fcf3ce44SJohn Forte #define	TPGT_EXT_SIZE	5
42fcf3ce44SJohn Forte 
43fcf3ce44SJohn Forte /* logical unit number bytes in string form */
44fcf3ce44SJohn Forte #define	LUN_EXT_SIZE	10
45fcf3ce44SJohn Forte 
46fcf3ce44SJohn Forte /*
47fcf3ce44SJohn Forte  * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
48fcf3ce44SJohn Forte  * ',' + max str form of logical unit number (4 bytes).
49fcf3ce44SJohn Forte  */
50fcf3ce44SJohn Forte #define	ADDR_EXT_SIZE	(1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
51fcf3ce44SJohn Forte 
52fcf3ce44SJohn Forte /* internal interfaces */
53fcf3ce44SJohn Forte static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
54fcf3ce44SJohn Forte     uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
55fcf3ce44SJohn Forte static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
56fcf3ce44SJohn Forte     uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
57fcf3ce44SJohn Forte 
58fcf3ce44SJohn Forte extern dev_info_t	*scsi_vhci_dip;
596cefaae1SJack Meng extern ib_boot_prop_t   *iscsiboot_prop;
60fcf3ce44SJohn Forte 
61fcf3ce44SJohn Forte /*
62fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
63fcf3ce44SJohn Forte  * | External Connection Interfaces					|
64fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
65fcf3ce44SJohn Forte  */
66fcf3ce44SJohn Forte 
67fcf3ce44SJohn Forte 
68fcf3ce44SJohn Forte /*
69fcf3ce44SJohn Forte  * iscsi_lun_create - This function will create a lun mapping.
70fcf3ce44SJohn Forte  * logic specific to MPxIO vs. NDI node creation is switched
71fcf3ce44SJohn Forte  * out to a helper function.
72fcf3ce44SJohn Forte  */
73fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_create(iscsi_sess_t * isp,uint16_t lun_num,uint8_t lun_addr_type,struct scsi_inquiry * inq,char * guid)74fcf3ce44SJohn Forte iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
75fcf3ce44SJohn Forte     struct scsi_inquiry *inq, char *guid)
76fcf3ce44SJohn Forte {
77fcf3ce44SJohn Forte 	iscsi_status_t		rtn		= ISCSI_STATUS_INTERNAL_ERROR;
78fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp		= NULL;
79fcf3ce44SJohn Forte 	iscsi_lun_t		*ilp		= NULL;
80fcf3ce44SJohn Forte 	iscsi_lun_t		*ilp_tmp	= NULL;
81fcf3ce44SJohn Forte 	char			*addr		= NULL;
826cefaae1SJack Meng 	uint16_t		boot_lun_num	= 0;
836cefaae1SJack Meng 	uint64_t		*lun_num_ptr	= NULL;
84b7a38285Sbing zhao - Sun Microsystems - Beijing China 	uint32_t		oid_tmp		= 0;
85fcf3ce44SJohn Forte 
86fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
87fcf3ce44SJohn Forte 	ihp = isp->sess_hba;
88fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
89fcf3ce44SJohn Forte 
90b7a38285Sbing zhao - Sun Microsystems - Beijing China 	mutex_enter(&iscsi_oid_mutex);
91b7a38285Sbing zhao - Sun Microsystems - Beijing China 	oid_tmp = iscsi_oid++;
92b7a38285Sbing zhao - Sun Microsystems - Beijing China 	mutex_exit(&iscsi_oid_mutex);
93b7a38285Sbing zhao - Sun Microsystems - Beijing China 
94b7a38285Sbing zhao - Sun Microsystems - Beijing China 	rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
95b7a38285Sbing zhao - Sun Microsystems - Beijing China 	/*
96b7a38285Sbing zhao - Sun Microsystems - Beijing China 	 * Check whether it has already existed in the list.
97b7a38285Sbing zhao - Sun Microsystems - Beijing China 	 */
98b7a38285Sbing zhao - Sun Microsystems - Beijing China 	for (ilp_tmp = isp->sess_lun_list; ilp_tmp != NULL;
99b7a38285Sbing zhao - Sun Microsystems - Beijing China 	    ilp_tmp = ilp_tmp->lun_next) {
100b7a38285Sbing zhao - Sun Microsystems - Beijing China 		if (ilp_tmp->lun_num == lun_num) {
101b7a38285Sbing zhao - Sun Microsystems - Beijing China 			/*
102b7a38285Sbing zhao - Sun Microsystems - Beijing China 			 * The logic unit has already existed in the list,
103b7a38285Sbing zhao - Sun Microsystems - Beijing China 			 * return with success.
104b7a38285Sbing zhao - Sun Microsystems - Beijing China 			 */
105b7a38285Sbing zhao - Sun Microsystems - Beijing China 			rw_exit(&isp->sess_lun_list_rwlock);
106b7a38285Sbing zhao - Sun Microsystems - Beijing China 			return (ISCSI_STATUS_SUCCESS);
107b7a38285Sbing zhao - Sun Microsystems - Beijing China 		}
108b7a38285Sbing zhao - Sun Microsystems - Beijing China 	}
109b7a38285Sbing zhao - Sun Microsystems - Beijing China 
110fcf3ce44SJohn Forte 	addr = kmem_zalloc((strlen((char *)isp->sess_name) +
111fcf3ce44SJohn Forte 	    ADDR_EXT_SIZE + 1), KM_SLEEP);
112fcf3ce44SJohn Forte 	(void) snprintf(addr,
113fcf3ce44SJohn Forte 	    (strlen((char *)isp->sess_name) +
114fcf3ce44SJohn Forte 	    ADDR_EXT_SIZE + 1),
115fcf3ce44SJohn Forte 	    "%02X%02X%s%04X,%d", isp->sess_isid[4],
116fcf3ce44SJohn Forte 	    isp->sess_isid[5], isp->sess_name,
1176cefaae1SJack Meng 	    isp->sess_tpgt_nego & 0xFFFF, lun_num);
118fcf3ce44SJohn Forte 
119fcf3ce44SJohn Forte 	/* allocate space for lun struct */
120fcf3ce44SJohn Forte 	ilp = kmem_zalloc(sizeof (iscsi_lun_t), KM_SLEEP);
121fcf3ce44SJohn Forte 	ilp->lun_sig = ISCSI_SIG_LUN;
12291dae09cSbing zhao - Sun Microsystems - Beijing China 	ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
12391dae09cSbing zhao - Sun Microsystems - Beijing China 	ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
124fcf3ce44SJohn Forte 
125fcf3ce44SJohn Forte 	/* initialize common LU information */
126fcf3ce44SJohn Forte 	ilp->lun_num	    = lun_num;
127fcf3ce44SJohn Forte 	ilp->lun_addr_type  = lun_addr_type;
128fcf3ce44SJohn Forte 	ilp->lun_sess	    = isp;
129fcf3ce44SJohn Forte 	ilp->lun_addr	    = addr;
130c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	ilp->lun_type	    = inq->inq_dtype & DTYPE_MASK;
131b7a38285Sbing zhao - Sun Microsystems - Beijing China 	ilp->lun_oid	    = oid_tmp;
13261dfa509SRick McNeal 	/*
13361dfa509SRick McNeal 	 * Setting refcnt to 1 is the first hold for the LUN structure.
13461dfa509SRick McNeal 	 */
13561dfa509SRick McNeal 	ilp->lun_refcnt	    = 1;
13661dfa509SRick McNeal 	mutex_init(&ilp->lun_mutex, NULL, MUTEX_DRIVER, NULL);
137fcf3ce44SJohn Forte 
138fcf3ce44SJohn Forte 	bcopy(inq->inq_vid, ilp->lun_vid, sizeof (inq->inq_vid));
139fcf3ce44SJohn Forte 	bcopy(inq->inq_pid, ilp->lun_pid, sizeof (inq->inq_pid));
140fcf3ce44SJohn Forte 
141fcf3ce44SJohn Forte 	/* store GUID if valid one exists */
142fcf3ce44SJohn Forte 	if (guid != NULL) {
143fcf3ce44SJohn Forte 		ilp->lun_guid_size = strlen(guid) + 1;
144fcf3ce44SJohn Forte 		ilp->lun_guid = kmem_zalloc(ilp->lun_guid_size, KM_SLEEP);
145fcf3ce44SJohn Forte 		(void) strcpy(ilp->lun_guid, guid);
146fcf3ce44SJohn Forte 	} else {
147fcf3ce44SJohn Forte 		ilp->lun_guid_size = 0;
148fcf3ce44SJohn Forte 		ilp->lun_guid = NULL;
149fcf3ce44SJohn Forte 	}
150fcf3ce44SJohn Forte 
151fcf3ce44SJohn Forte 	/*
152fcf3ce44SJohn Forte 	 * We need to add the lun to our lists now because during the
153fcf3ce44SJohn Forte 	 * lun creation we will get called back into multiple times
154fcf3ce44SJohn Forte 	 * depending on the createion type.  These callbacks will
155fcf3ce44SJohn Forte 	 * occur via our tran_init_lun, tran_get_name, tran_get_bus_addr,
156fcf3ce44SJohn Forte 	 * tran_init_pkt, tran_start.
157fcf3ce44SJohn Forte 	 */
158fcf3ce44SJohn Forte 	if (isp->sess_lun_list == NULL) {
159fcf3ce44SJohn Forte 		isp->sess_lun_list = ilp;
160fcf3ce44SJohn Forte 	} else {
161fcf3ce44SJohn Forte 		ilp->lun_next = isp->sess_lun_list;
162fcf3ce44SJohn Forte 		isp->sess_lun_list = ilp;
163fcf3ce44SJohn Forte 	}
164fcf3ce44SJohn Forte 
165fcf3ce44SJohn Forte 	/* Attempt to create a scsi_vhci binding if GUID is available */
166fcf3ce44SJohn Forte 	if ((ihp->hba_mpxio_enabled == B_TRUE) &&
167fcf3ce44SJohn Forte 	    (guid != NULL)) {
168fcf3ce44SJohn Forte 		rtn = iscsi_lun_virt_create(isp, lun_num, ilp, inq);
169fcf3ce44SJohn Forte 	}
170fcf3ce44SJohn Forte 	if (!ISCSI_SUCCESS(rtn)) {
171fcf3ce44SJohn Forte 		/* unable to bind under scsi_vhci, failback to ndi */
172fcf3ce44SJohn Forte 		rtn = iscsi_lun_phys_create(isp, lun_num, ilp, inq);
173fcf3ce44SJohn Forte 	}
174fcf3ce44SJohn Forte 
175fcf3ce44SJohn Forte 	/*
176fcf3ce44SJohn Forte 	 * If NOT successful we need to remove the lun from the
177fcf3ce44SJohn Forte 	 * session and free any related resources.
178fcf3ce44SJohn Forte 	 */
179fcf3ce44SJohn Forte 	if (!ISCSI_SUCCESS(rtn)) {
180fcf3ce44SJohn Forte 		if (ilp == isp->sess_lun_list) {
181fcf3ce44SJohn Forte 			/* if head, set head to our next */
182fcf3ce44SJohn Forte 			isp->sess_lun_list = ilp->lun_next;
183fcf3ce44SJohn Forte 		} else {
184fcf3ce44SJohn Forte 			/* if not head, set prev lun's next to our next */
185fcf3ce44SJohn Forte 			for (ilp_tmp = isp->sess_lun_list; ilp_tmp;
186fcf3ce44SJohn Forte 			    ilp_tmp = ilp_tmp->lun_next) {
187fcf3ce44SJohn Forte 				if (ilp_tmp->lun_next == ilp) {
188fcf3ce44SJohn Forte 					ilp_tmp->lun_next = ilp->lun_next;
189fcf3ce44SJohn Forte 					break;
190fcf3ce44SJohn Forte 				}
191fcf3ce44SJohn Forte 			}
192fcf3ce44SJohn Forte 		}
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte 		kmem_free(ilp->lun_addr,
195fcf3ce44SJohn Forte 		    (strlen((char *)isp->sess_name) +
196fcf3ce44SJohn Forte 		    ADDR_EXT_SIZE + 1));
197fcf3ce44SJohn Forte 		ilp->lun_addr = NULL;
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 		if (ilp->lun_guid != NULL) {
200fcf3ce44SJohn Forte 			kmem_free(ilp->lun_guid, ilp->lun_guid_size);
201fcf3ce44SJohn Forte 			ilp->lun_guid = NULL;
202fcf3ce44SJohn Forte 		}
20361dfa509SRick McNeal 		mutex_destroy(&ilp->lun_mutex);
204fcf3ce44SJohn Forte 		kmem_free(ilp, sizeof (iscsi_lun_t));
205fcf3ce44SJohn Forte 	} else {
20691dae09cSbing zhao - Sun Microsystems - Beijing China 		ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
20791dae09cSbing zhao - Sun Microsystems - Beijing China 		ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
208fcf3ce44SJohn Forte 		ilp->lun_time_online = ddi_get_time();
2096cefaae1SJack Meng 
2106cefaae1SJack Meng 		/* Check whether this is the required LUN for iscsi boot */
2116cefaae1SJack Meng 		if (iscsiboot_prop != NULL && isp->sess_boot == B_TRUE &&
2126cefaae1SJack Meng 		    iscsiboot_prop->boot_tgt.lun_online == 0) {
2136cefaae1SJack Meng 			lun_num_ptr =
2146cefaae1SJack Meng 			    (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
2156cefaae1SJack Meng 			boot_lun_num = (uint16_t)(*lun_num_ptr);
2166cefaae1SJack Meng 			if (boot_lun_num == ilp->lun_num) {
2176cefaae1SJack Meng 				/*
2186cefaae1SJack Meng 				 * During iscsi boot, the boot lun has been
2196cefaae1SJack Meng 				 * online, we should set the "online flag".
2206cefaae1SJack Meng 				 */
2216cefaae1SJack Meng 				iscsiboot_prop->boot_tgt.lun_online = 1;
2226cefaae1SJack Meng 			}
2236cefaae1SJack Meng 		}
224fcf3ce44SJohn Forte 	}
225fcf3ce44SJohn Forte 	rw_exit(&isp->sess_lun_list_rwlock);
226fcf3ce44SJohn Forte 
227fcf3ce44SJohn Forte 	return (rtn);
228fcf3ce44SJohn Forte }
229fcf3ce44SJohn Forte 
23061dfa509SRick McNeal void
iscsi_lun_hold(iscsi_lun_t * ilp)23161dfa509SRick McNeal iscsi_lun_hold(iscsi_lun_t *ilp)
23261dfa509SRick McNeal {
23361dfa509SRick McNeal 	mutex_enter(&ilp->lun_mutex);
23461dfa509SRick McNeal 	/*
23561dfa509SRick McNeal 	 * By design lun_refcnt should never be zero when this routine
23661dfa509SRick McNeal 	 * is called. When the LUN is created the refcnt is set to 1.
23761dfa509SRick McNeal 	 * If iscsi_lun_rele is called and the refcnt goes to zero the
23861dfa509SRick McNeal 	 * structure will be freed so this method shouldn't be called
23961dfa509SRick McNeal 	 * afterwards.
24061dfa509SRick McNeal 	 */
24161dfa509SRick McNeal 	ASSERT(ilp->lun_refcnt > 0);
24261dfa509SRick McNeal 	ilp->lun_refcnt++;
24361dfa509SRick McNeal 	mutex_exit(&ilp->lun_mutex);
24461dfa509SRick McNeal }
24561dfa509SRick McNeal 
24661dfa509SRick McNeal void
iscsi_lun_rele(iscsi_lun_t * ilp)24761dfa509SRick McNeal iscsi_lun_rele(iscsi_lun_t *ilp)
24861dfa509SRick McNeal {
24961dfa509SRick McNeal 	ASSERT(ilp != NULL);
25061dfa509SRick McNeal 
25161dfa509SRick McNeal 	mutex_enter(&ilp->lun_mutex);
25261dfa509SRick McNeal 	ASSERT(ilp->lun_refcnt > 0);
25361dfa509SRick McNeal 	if (--ilp->lun_refcnt == 0) {
25461dfa509SRick McNeal 		iscsi_sess_t		*isp;
25561dfa509SRick McNeal 
25661dfa509SRick McNeal 		isp = ilp->lun_sess;
25761dfa509SRick McNeal 		ASSERT(isp != NULL);
25861dfa509SRick McNeal 
25961dfa509SRick McNeal 		/* ---- release its memory ---- */
26061dfa509SRick McNeal 		kmem_free(ilp->lun_addr, (strlen((char *)isp->sess_name) +
26161dfa509SRick McNeal 		    ADDR_EXT_SIZE + 1));
26261dfa509SRick McNeal 
26361dfa509SRick McNeal 		if (ilp->lun_guid != NULL) {
26461dfa509SRick McNeal 			kmem_free(ilp->lun_guid, ilp->lun_guid_size);
26561dfa509SRick McNeal 		}
26661dfa509SRick McNeal 		mutex_destroy(&ilp->lun_mutex);
26761dfa509SRick McNeal 		kmem_free(ilp, sizeof (iscsi_lun_t));
26861dfa509SRick McNeal 	} else {
26961dfa509SRick McNeal 		mutex_exit(&ilp->lun_mutex);
27061dfa509SRick McNeal 	}
27161dfa509SRick McNeal }
27261dfa509SRick McNeal 
27361dfa509SRick McNeal /*
27461dfa509SRick McNeal  * iscsi_lun_cmd_cancel -- as the name implies, cancel all commands for the lun
27561dfa509SRick McNeal  *
27661dfa509SRick McNeal  * This code is similar to the timeout function with a lot less checking of
27761dfa509SRick McNeal  * state before sending the ABORT event for commands on the pending queue.
27861dfa509SRick McNeal  *
27961dfa509SRick McNeal  * This function is only used by iscsi_lun_destroy().
28061dfa509SRick McNeal  */
28161dfa509SRick McNeal static void
iscsi_lun_cmd_cancel(iscsi_lun_t * ilp)28261dfa509SRick McNeal iscsi_lun_cmd_cancel(iscsi_lun_t *ilp)
28361dfa509SRick McNeal {
28461dfa509SRick McNeal 	iscsi_sess_t	*isp;
28561dfa509SRick McNeal 	iscsi_cmd_t	*icmdp, *nicmdp;
28661dfa509SRick McNeal 
28761dfa509SRick McNeal 	isp = ilp->lun_sess;
28861dfa509SRick McNeal 	rw_enter(&isp->sess_state_rwlock, RW_READER);
28961dfa509SRick McNeal 	mutex_enter(&isp->sess_queue_pending.mutex);
29061dfa509SRick McNeal 	for (icmdp = isp->sess_queue_pending.head;
29161dfa509SRick McNeal 	    icmdp; icmdp = nicmdp) {
29261dfa509SRick McNeal 		nicmdp = icmdp->cmd_next;
29361dfa509SRick McNeal 
29461dfa509SRick McNeal 		/*
29561dfa509SRick McNeal 		 * For commands on the pending queue we can go straight
29661dfa509SRick McNeal 		 * to and abort request which will free the command
29761dfa509SRick McNeal 		 * and call back to the complete function.
29861dfa509SRick McNeal 		 */
29961dfa509SRick McNeal 		iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4, isp);
30061dfa509SRick McNeal 	}
30161dfa509SRick McNeal 	mutex_exit(&isp->sess_queue_pending.mutex);
30261dfa509SRick McNeal 	rw_exit(&isp->sess_state_rwlock);
30361dfa509SRick McNeal }
30461dfa509SRick McNeal 
305fcf3ce44SJohn Forte /*
306fcf3ce44SJohn Forte  * iscsi_lun_destroy - offline and remove lun
307fcf3ce44SJohn Forte  *
308fcf3ce44SJohn Forte  * This interface is called when a name service change has
309fcf3ce44SJohn Forte  * occured and the storage is no longer available to this
310fcf3ce44SJohn Forte  * initiator.  This function will offline and free the
311fcf3ce44SJohn Forte  * solaris node resources.  Then it will free all iscsi lun
312fcf3ce44SJohn Forte  * resources.
313fcf3ce44SJohn Forte  *
314fcf3ce44SJohn Forte  * This function can fail with ISCSI_STATUS_BUSY if the
315fcf3ce44SJohn Forte  * logical unit is in use.  The user should unmount or
316fcf3ce44SJohn Forte  * close the device and perform the nameservice operation
317fcf3ce44SJohn Forte  * again if this occurs.
318fcf3ce44SJohn Forte  */
319fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_destroy(iscsi_hba_t * ihp,iscsi_lun_t * ilp)320fcf3ce44SJohn Forte iscsi_lun_destroy(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
321fcf3ce44SJohn Forte {
322fcf3ce44SJohn Forte 	iscsi_status_t		status		= ISCSI_STATUS_SUCCESS;
323fcf3ce44SJohn Forte 	iscsi_sess_t		*isp		= NULL;
324fcf3ce44SJohn Forte 	iscsi_lun_t		*t_ilp		= NULL;
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 	ASSERT(ilp != NULL);
327fcf3ce44SJohn Forte 	isp = ilp->lun_sess;
328fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
329fcf3ce44SJohn Forte 
33061dfa509SRick McNeal 	/* flush all outstanding commands first */
33161dfa509SRick McNeal 	iscsi_lun_cmd_cancel(ilp);
33261dfa509SRick McNeal 
333fcf3ce44SJohn Forte 	/* attempt to offline and free solaris node */
334fcf3ce44SJohn Forte 	status = iscsi_lun_offline(ihp, ilp, B_TRUE);
335fcf3ce44SJohn Forte 
336fcf3ce44SJohn Forte 	/* If we successfully unplumbed the lun remove it from our lists */
337fcf3ce44SJohn Forte 	if (ISCSI_SUCCESS(status)) {
338fcf3ce44SJohn Forte 		if (isp->sess_lun_list == ilp) {
339fcf3ce44SJohn Forte 			/* target first item in list */
340fcf3ce44SJohn Forte 			isp->sess_lun_list = ilp->lun_next;
341fcf3ce44SJohn Forte 		} else {
342fcf3ce44SJohn Forte 			/*
343fcf3ce44SJohn Forte 			 * search session list for ilp pointing
344fcf3ce44SJohn Forte 			 * to lun being removed.  Then
345fcf3ce44SJohn Forte 			 * update that luns next pointer.
346fcf3ce44SJohn Forte 			 */
347fcf3ce44SJohn Forte 			t_ilp = isp->sess_lun_list;
348fcf3ce44SJohn Forte 			while (t_ilp->lun_next != NULL) {
349fcf3ce44SJohn Forte 				if (t_ilp->lun_next == ilp) {
350fcf3ce44SJohn Forte 					break;
351fcf3ce44SJohn Forte 				}
352fcf3ce44SJohn Forte 				t_ilp = t_ilp->lun_next;
353fcf3ce44SJohn Forte 			}
354fcf3ce44SJohn Forte 			if (t_ilp->lun_next == ilp) {
355fcf3ce44SJohn Forte 				t_ilp->lun_next = ilp->lun_next;
356fcf3ce44SJohn Forte 			} else {
357fcf3ce44SJohn Forte 				/* couldn't find session */
358fcf3ce44SJohn Forte 				ASSERT(FALSE);
359fcf3ce44SJohn Forte 			}
360fcf3ce44SJohn Forte 		}
361fcf3ce44SJohn Forte 
36261dfa509SRick McNeal 		iscsi_lun_rele(ilp);
363fcf3ce44SJohn Forte 	}
364fcf3ce44SJohn Forte 
365fcf3ce44SJohn Forte 	return (status);
366fcf3ce44SJohn Forte }
367fcf3ce44SJohn Forte 
368fcf3ce44SJohn Forte /*
369fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
370fcf3ce44SJohn Forte  * | External Logical Unit Interfaces					|
371fcf3ce44SJohn Forte  * +--------------------------------------------------------------------+
372fcf3ce44SJohn Forte  */
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte /*
375fcf3ce44SJohn Forte  * iscsi_lun_virt_create - Creates solaris logical unit via MDI
376fcf3ce44SJohn Forte  */
377fcf3ce44SJohn Forte static iscsi_status_t
iscsi_lun_virt_create(iscsi_sess_t * isp,uint16_t lun_num,iscsi_lun_t * ilp,struct scsi_inquiry * inq)378fcf3ce44SJohn Forte iscsi_lun_virt_create(iscsi_sess_t *isp, uint16_t lun_num, iscsi_lun_t *ilp,
379fcf3ce44SJohn Forte     struct scsi_inquiry *inq)
380fcf3ce44SJohn Forte {
381fcf3ce44SJohn Forte 	iscsi_status_t		rtn		= ISCSI_STATUS_INTERNAL_ERROR;
382fcf3ce44SJohn Forte 	int			mdi_rtn		= MDI_FAILURE;
383fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp		= NULL;
384fcf3ce44SJohn Forte 	mdi_pathinfo_t		*pip		= NULL;
385fcf3ce44SJohn Forte 	char			*nodename	= NULL;
386fcf3ce44SJohn Forte 	char			**compatible	= NULL;
387fcf3ce44SJohn Forte 	int			ncompatible	= 0;
388fcf3ce44SJohn Forte 
389fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
390fcf3ce44SJohn Forte 	ASSERT(ilp != NULL);
391fcf3ce44SJohn Forte 	ihp = isp->sess_hba;
392fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
393fcf3ce44SJohn Forte 
394fcf3ce44SJohn Forte 	/*
395fcf3ce44SJohn Forte 	 * Generate compatible property
396fcf3ce44SJohn Forte 	 */
397fcf3ce44SJohn Forte 	scsi_hba_nodename_compatible_get(inq, "vhci",
398fcf3ce44SJohn Forte 	    inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
399fcf3ce44SJohn Forte 
400fcf3ce44SJohn Forte 	/* if nodename can't be determined then print a message and skip it */
401fcf3ce44SJohn Forte 	if (nodename == NULL) {
402fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "iscsi driver found no compatible driver "
403fcf3ce44SJohn Forte 		    "for %s lun %d dtype:0x%02x", isp->sess_name, lun_num,
404fcf3ce44SJohn Forte 		    inq->inq_dtype);
405fcf3ce44SJohn Forte 		return (ISCSI_STATUS_INTERNAL_ERROR);
406fcf3ce44SJohn Forte 	}
407fcf3ce44SJohn Forte 
408fcf3ce44SJohn Forte 	/*
409fcf3ce44SJohn Forte 	 *
410fcf3ce44SJohn Forte 	 */
411*3fe80ca4SDan Cross 	ndi_devi_enter(scsi_vhci_dip);
412fcf3ce44SJohn Forte 	mdi_rtn = mdi_pi_alloc_compatible(ihp->hba_dip, nodename,
413fcf3ce44SJohn Forte 	    ilp->lun_guid, ilp->lun_addr, compatible, ncompatible,
414fcf3ce44SJohn Forte 	    0, &pip);
415fcf3ce44SJohn Forte 
416fcf3ce44SJohn Forte 	if (mdi_rtn == MDI_SUCCESS) {
417fcf3ce44SJohn Forte 		mdi_pi_set_phci_private(pip, (caddr_t)ilp);
418fcf3ce44SJohn Forte 
419fcf3ce44SJohn Forte 		if (mdi_prop_update_string(pip, MDI_GUID,
420fcf3ce44SJohn Forte 		    ilp->lun_guid) != DDI_SUCCESS) {
421fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
422fcf3ce44SJohn Forte 			    "property for %s lun %d (MDI_GUID)",
423fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
424fcf3ce44SJohn Forte 			mdi_rtn = MDI_FAILURE;
425fcf3ce44SJohn Forte 			goto virt_create_done;
426fcf3ce44SJohn Forte 		}
427fcf3ce44SJohn Forte 
428fcf3ce44SJohn Forte 		if (mdi_prop_update_int(pip, TARGET_PROP,
429fcf3ce44SJohn Forte 		    isp->sess_oid) != DDI_SUCCESS) {
430fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
431fcf3ce44SJohn Forte 			    "property for %s lun %d (TARGET_PROP)",
432fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
433fcf3ce44SJohn Forte 			mdi_rtn = MDI_FAILURE;
434fcf3ce44SJohn Forte 			goto virt_create_done;
435fcf3ce44SJohn Forte 		}
436fcf3ce44SJohn Forte 
437fcf3ce44SJohn Forte 		if (mdi_prop_update_int(pip, LUN_PROP,
438fcf3ce44SJohn Forte 		    ilp->lun_num) != DDI_SUCCESS) {
439fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
440fcf3ce44SJohn Forte 			    "property for %s lun %d (LUN_PROP)",
441fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
442fcf3ce44SJohn Forte 			mdi_rtn = MDI_FAILURE;
443fcf3ce44SJohn Forte 			goto virt_create_done;
444fcf3ce44SJohn Forte 		}
445fcf3ce44SJohn Forte 
446fcf3ce44SJohn Forte 		if (mdi_prop_update_string_array(pip, "compatible",
447fcf3ce44SJohn Forte 		    compatible, ncompatible) !=
448fcf3ce44SJohn Forte 		    DDI_PROP_SUCCESS) {
449fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
450fcf3ce44SJohn Forte 			    "property for %s lun %d (COMPATIBLE)",
451fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
452fcf3ce44SJohn Forte 			mdi_rtn = MDI_FAILURE;
453fcf3ce44SJohn Forte 			goto virt_create_done;
454fcf3ce44SJohn Forte 		}
455fcf3ce44SJohn Forte 
456fcf3ce44SJohn Forte 		mdi_rtn = mdi_pi_online(pip, 0);
457fcf3ce44SJohn Forte 		if (mdi_rtn == MDI_NOT_SUPPORTED) {
458fcf3ce44SJohn Forte 			mdi_rtn = MDI_FAILURE;
459fcf3ce44SJohn Forte 			goto virt_create_done;
460fcf3ce44SJohn Forte 		}
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte 		ilp->lun_pip = pip;
463fcf3ce44SJohn Forte 		ilp->lun_dip = NULL;
464fcf3ce44SJohn Forte 
465fcf3ce44SJohn Forte virt_create_done:
466fcf3ce44SJohn Forte 
467fcf3ce44SJohn Forte 		if (pip && mdi_rtn != MDI_SUCCESS) {
468fcf3ce44SJohn Forte 			ilp->lun_pip = NULL;
469fcf3ce44SJohn Forte 			ilp->lun_dip = NULL;
470fcf3ce44SJohn Forte 			(void) mdi_prop_remove(pip, NULL);
471fcf3ce44SJohn Forte 			(void) mdi_pi_free(pip, 0);
472fcf3ce44SJohn Forte 		} else {
473fcf3ce44SJohn Forte 			rtn = ISCSI_STATUS_SUCCESS;
474fcf3ce44SJohn Forte 		}
475fcf3ce44SJohn Forte 	}
476*3fe80ca4SDan Cross 	ndi_devi_exit(scsi_vhci_dip);
477fcf3ce44SJohn Forte 
478fcf3ce44SJohn Forte 	scsi_hba_nodename_compatible_free(nodename, compatible);
479fcf3ce44SJohn Forte 
480fcf3ce44SJohn Forte 	return (rtn);
481fcf3ce44SJohn Forte }
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 
484fcf3ce44SJohn Forte /*
485fcf3ce44SJohn Forte  * iscsi_lun_phys_create - creates solaris logical unit via NDI
486fcf3ce44SJohn Forte  */
487fcf3ce44SJohn Forte static iscsi_status_t
iscsi_lun_phys_create(iscsi_sess_t * isp,uint16_t lun_num,iscsi_lun_t * ilp,struct scsi_inquiry * inq)488fcf3ce44SJohn Forte iscsi_lun_phys_create(iscsi_sess_t *isp, uint16_t lun_num,
489fcf3ce44SJohn Forte     iscsi_lun_t *ilp, struct scsi_inquiry *inq)
490fcf3ce44SJohn Forte {
491fcf3ce44SJohn Forte 	iscsi_status_t		rtn		= ISCSI_STATUS_INTERNAL_ERROR;
492fcf3ce44SJohn Forte 	int			ndi_rtn		= NDI_FAILURE;
493fcf3ce44SJohn Forte 	iscsi_hba_t		*ihp		= NULL;
494fcf3ce44SJohn Forte 	dev_info_t		*lun_dip	= NULL;
495fcf3ce44SJohn Forte 	char			*nodename	= NULL;
496fcf3ce44SJohn Forte 	char			**compatible	= NULL;
497fcf3ce44SJohn Forte 	int			ncompatible	= 0;
498fcf3ce44SJohn Forte 	char			*scsi_binding_set = NULL;
499fcf3ce44SJohn Forte 	char			instance[32];
500fcf3ce44SJohn Forte 
501fcf3ce44SJohn Forte 	ASSERT(isp != NULL);
502fcf3ce44SJohn Forte 	ASSERT(ilp != NULL);
503fcf3ce44SJohn Forte 	ihp = isp->sess_hba;
504fcf3ce44SJohn Forte 	ASSERT(ihp != NULL);
505fcf3ce44SJohn Forte 	ASSERT(inq != NULL);
506fcf3ce44SJohn Forte 
507fcf3ce44SJohn Forte 	/* get the 'scsi-binding-set' property */
508fcf3ce44SJohn Forte 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, isp->sess_hba->hba_dip,
509fcf3ce44SJohn Forte 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
510fcf3ce44SJohn Forte 	    &scsi_binding_set) != DDI_PROP_SUCCESS) {
511fcf3ce44SJohn Forte 		scsi_binding_set = NULL;
512fcf3ce44SJohn Forte 	}
513fcf3ce44SJohn Forte 
514fcf3ce44SJohn Forte 	/* generate compatible property */
515fcf3ce44SJohn Forte 	scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
516fcf3ce44SJohn Forte 	    inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
517fcf3ce44SJohn Forte 	if (scsi_binding_set)
518fcf3ce44SJohn Forte 		ddi_prop_free(scsi_binding_set);
519fcf3ce44SJohn Forte 
520fcf3ce44SJohn Forte 	/* if nodename can't be determined then print a message and skip it */
521fcf3ce44SJohn Forte 	if (nodename == NULL) {
522fcf3ce44SJohn Forte 		cmn_err(CE_WARN, "iscsi driver found no compatible driver "
523fcf3ce44SJohn Forte 		    "for %s lun %d", isp->sess_name, lun_num);
524fcf3ce44SJohn Forte 		return (ISCSI_STATUS_INTERNAL_ERROR);
525fcf3ce44SJohn Forte 	}
526fcf3ce44SJohn Forte 
527*3fe80ca4SDan Cross 	ndi_devi_enter(ihp->hba_dip);
528fcf3ce44SJohn Forte 
529fcf3ce44SJohn Forte 	ndi_rtn = ndi_devi_alloc(ihp->hba_dip, nodename,
530fcf3ce44SJohn Forte 	    DEVI_SID_NODEID, &lun_dip);
531fcf3ce44SJohn Forte 
532fcf3ce44SJohn Forte 	/* if lun alloc success, set props */
533fcf3ce44SJohn Forte 	if (ndi_rtn == NDI_SUCCESS) {
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 		if (ndi_prop_update_int(DDI_DEV_T_NONE,
536fcf3ce44SJohn Forte 		    lun_dip, TARGET_PROP, (int)isp->sess_oid) !=
537fcf3ce44SJohn Forte 		    DDI_PROP_SUCCESS) {
538fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
539fcf3ce44SJohn Forte 			    "property for %s lun %d (TARGET_PROP)",
540fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
541fcf3ce44SJohn Forte 			ndi_rtn = NDI_FAILURE;
542fcf3ce44SJohn Forte 			goto phys_create_done;
543fcf3ce44SJohn Forte 		}
544fcf3ce44SJohn Forte 
545fcf3ce44SJohn Forte 		if (ndi_prop_update_int(DDI_DEV_T_NONE,
546fcf3ce44SJohn Forte 		    lun_dip, LUN_PROP, (int)ilp->lun_num) !=
547fcf3ce44SJohn Forte 		    DDI_PROP_SUCCESS) {
548fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
549fcf3ce44SJohn Forte 			    "property for %s lun %d (LUN_PROP)",
550fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
551fcf3ce44SJohn Forte 			ndi_rtn = NDI_FAILURE;
552fcf3ce44SJohn Forte 			goto phys_create_done;
553fcf3ce44SJohn Forte 		}
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 		if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
556fcf3ce44SJohn Forte 		    lun_dip, "compatible", compatible, ncompatible)
557fcf3ce44SJohn Forte 		    != DDI_PROP_SUCCESS) {
558fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to create "
559fcf3ce44SJohn Forte 			    "property for %s lun %d (COMPATIBLE)",
560fcf3ce44SJohn Forte 			    isp->sess_name, lun_num);
561fcf3ce44SJohn Forte 			ndi_rtn = NDI_FAILURE;
562fcf3ce44SJohn Forte 			goto phys_create_done;
563fcf3ce44SJohn Forte 		}
564fcf3ce44SJohn Forte 
565fcf3ce44SJohn Forte phys_create_done:
566fcf3ce44SJohn Forte 		/* If props were setup ok, online the lun */
567fcf3ce44SJohn Forte 		if (ndi_rtn == NDI_SUCCESS) {
568fcf3ce44SJohn Forte 			/* Try to online the new node */
569fcf3ce44SJohn Forte 			ndi_rtn = ndi_devi_online(lun_dip, 0);
570fcf3ce44SJohn Forte 		}
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte 		/* If success set rtn flag, else unwire alloc'd lun */
573fcf3ce44SJohn Forte 		if (ndi_rtn == NDI_SUCCESS) {
574fcf3ce44SJohn Forte 			rtn = ISCSI_STATUS_SUCCESS;
575fcf3ce44SJohn Forte 			/*
576fcf3ce44SJohn Forte 			 * Assign the instance number for the dev_link
577fcf3ce44SJohn Forte 			 * generator.  This will ensure the link name is
578fcf3ce44SJohn Forte 			 * unique and persistent across reboots.
579fcf3ce44SJohn Forte 			 */
580fcf3ce44SJohn Forte 			(void) snprintf(instance, 32, "%d",
581fcf3ce44SJohn Forte 			    ddi_get_instance(lun_dip));
582fcf3ce44SJohn Forte 			(void) ndi_prop_update_string(DDI_DEV_T_NONE,
583fcf3ce44SJohn Forte 			    lun_dip, NDI_GUID, instance);
584fcf3ce44SJohn Forte 		} else {
585fcf3ce44SJohn Forte 			cmn_err(CE_WARN, "iscsi driver unable to online "
586fcf3ce44SJohn Forte 			    "%s lun %d", isp->sess_name, lun_num);
587fcf3ce44SJohn Forte 			ndi_prop_remove_all(lun_dip);
588fcf3ce44SJohn Forte 			(void) ndi_devi_free(lun_dip);
589fcf3ce44SJohn Forte 		}
590fcf3ce44SJohn Forte 
591fcf3ce44SJohn Forte 	}
592*3fe80ca4SDan Cross 	ndi_devi_exit(ihp->hba_dip);
593fcf3ce44SJohn Forte 
594fcf3ce44SJohn Forte 	ilp->lun_dip = lun_dip;
595fcf3ce44SJohn Forte 	ilp->lun_pip = NULL;
596fcf3ce44SJohn Forte 
597fcf3ce44SJohn Forte 	scsi_hba_nodename_compatible_free(nodename, compatible);
598fcf3ce44SJohn Forte 
599fcf3ce44SJohn Forte 	return (rtn);
600fcf3ce44SJohn Forte }
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte 
603fcf3ce44SJohn Forte /*
604fcf3ce44SJohn Forte  * iscsi_lun_online - _di_online logical unit
605fcf3ce44SJohn Forte  *
606fcf3ce44SJohn Forte  * This is called after a path has recovered it will cause
607fcf3ce44SJohn Forte  * an offline path to become online/active again.
608fcf3ce44SJohn Forte  */
609fcf3ce44SJohn Forte void
iscsi_lun_online(iscsi_hba_t * ihp,iscsi_lun_t * ilp)610fcf3ce44SJohn Forte iscsi_lun_online(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
611fcf3ce44SJohn Forte {
6126cefaae1SJack Meng 	int			rval		= 0;
6136cefaae1SJack Meng 	uint64_t		*lun_num_ptr	= NULL;
6146cefaae1SJack Meng 	uint16_t		boot_lun_num	= 0;
6156cefaae1SJack Meng 	iscsi_sess_t		*isp		= NULL;
616c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	boolean_t		online		= B_FALSE;
617c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	nvlist_t		*attr_list	= NULL;
618c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	char			*pathname	= NULL;
619c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	dev_info_t		*lun_dip	= NULL;
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte 	ASSERT(ilp != NULL);
622fcf3ce44SJohn Forte 	ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
623fcf3ce44SJohn Forte 
624fcf3ce44SJohn Forte 	if (ilp->lun_pip != NULL) {
625*3fe80ca4SDan Cross 		ndi_devi_enter(scsi_vhci_dip);
626fcf3ce44SJohn Forte 		rval =  mdi_pi_online(ilp->lun_pip, 0);
627*3fe80ca4SDan Cross 		ndi_devi_exit(scsi_vhci_dip);
628fcf3ce44SJohn Forte 		if (rval == MDI_SUCCESS) {
62991dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
63091dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
631fcf3ce44SJohn Forte 			ilp->lun_time_online = ddi_get_time();
632c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			online = B_TRUE;
633fcf3ce44SJohn Forte 		}
634fcf3ce44SJohn Forte 
635fcf3ce44SJohn Forte 	} else if (ilp->lun_dip != NULL) {
636*3fe80ca4SDan Cross 		ndi_devi_enter(ihp->hba_dip);
637fcf3ce44SJohn Forte 		rval =  ndi_devi_online(ilp->lun_dip, 0);
638*3fe80ca4SDan Cross 		ndi_devi_exit(ihp->hba_dip);
639fcf3ce44SJohn Forte 		if (rval == NDI_SUCCESS) {
64091dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
64191dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
642fcf3ce44SJohn Forte 			ilp->lun_time_online = ddi_get_time();
643c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			online = B_TRUE;
644fcf3ce44SJohn Forte 		}
645fcf3ce44SJohn Forte 	}
6466cefaae1SJack Meng 
6476cefaae1SJack Meng 	/* Check whether this is the required LUN for iscsi boot */
6486cefaae1SJack Meng 	if (iscsiboot_prop != NULL &&
6496cefaae1SJack Meng 	    iscsiboot_prop->boot_tgt.lun_online == 0) {
6506cefaae1SJack Meng 		isp = ilp->lun_sess;
6516cefaae1SJack Meng 		if (isp->sess_boot == B_TRUE) {
6526cefaae1SJack Meng 			lun_num_ptr =
6536cefaae1SJack Meng 			    (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
6546cefaae1SJack Meng 			boot_lun_num = (uint16_t)(*lun_num_ptr);
6556cefaae1SJack Meng 			if (boot_lun_num == ilp->lun_num) {
6566cefaae1SJack Meng 				/*
6576cefaae1SJack Meng 				 * During iscsi boot, the boot lun has been
6586cefaae1SJack Meng 				 * online, we should set the "online flag".
6596cefaae1SJack Meng 				 */
6606cefaae1SJack Meng 				iscsiboot_prop->boot_tgt.lun_online = 1;
6616cefaae1SJack Meng 			}
6626cefaae1SJack Meng 		}
6636cefaae1SJack Meng 	}
664c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
665c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	/*
666c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	 * If the LUN has been online and it is a disk,
667c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	 * send out a system event.
668c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	 */
669c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	if (online == B_TRUE && ilp->lun_type == DTYPE_DIRECT) {
670c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
671c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		    DDI_SUCCESS) {
672c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			return;
673c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		}
674c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
675c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		if (ilp->lun_pip != NULL) {
676c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			lun_dip = mdi_pi_get_client(ilp->lun_pip);
677c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		} else {
678c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			lun_dip = ilp->lun_dip;
679c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		}
680c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
681c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
682c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		(void) ddi_pathname(lun_dip, pathname);
683c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
684c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
685c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		    DDI_SUCCESS) {
686c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			nvlist_free(attr_list);
687c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			kmem_free(pathname, MAXNAMELEN + 1);
688c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			return;
689c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		}
690c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		iscsi_send_sysevent(ihp, EC_DEV_ADD, ESC_DISK, attr_list);
691c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		kmem_free(pathname, MAXNAMELEN + 1);
692c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		nvlist_free(attr_list);
693c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	}
694fcf3ce44SJohn Forte }
695fcf3ce44SJohn Forte 
696fcf3ce44SJohn Forte /*
697fcf3ce44SJohn Forte  * iscsi_lun_offline - attempt _di_offline [and optional _di_free]
698fcf3ce44SJohn Forte  *
699fcf3ce44SJohn Forte  * This function is called via two paths.  When a transport
700fcf3ce44SJohn Forte  * path has failed it will be called to offline the logical
701fcf3ce44SJohn Forte  * unit.  When nameservice access has been removed it will
702fcf3ce44SJohn Forte  * be called to both offline and free the logical unit.
703fcf3ce44SJohn Forte  * (This operates soley on the solaris node states.
704fcf3ce44SJohn Forte  * iscsi_lun_destroy() should be called when attempting
705fcf3ce44SJohn Forte  * to free all iscsi lun resources.)
706fcf3ce44SJohn Forte  *
707fcf3ce44SJohn Forte  * This function can fail with ISCSI_STATUS_BUSY if the
708fcf3ce44SJohn Forte  * logical unit is in use.  The user should unmount or
709fcf3ce44SJohn Forte  * close the device and perform the nameservice operation
710fcf3ce44SJohn Forte  * again if this occurs.
71191dae09cSbing zhao - Sun Microsystems - Beijing China  *
71291dae09cSbing zhao - Sun Microsystems - Beijing China  * If we fail to offline a LUN that we don't want to destroy,
71391dae09cSbing zhao - Sun Microsystems - Beijing China  * we will mark it with invalid state. If this LUN still
71491dae09cSbing zhao - Sun Microsystems - Beijing China  * exists on the target, we can have another chance to online
71591dae09cSbing zhao - Sun Microsystems - Beijing China  * it again when we do the LUN enumeration.
716fcf3ce44SJohn Forte  */
717fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_offline(iscsi_hba_t * ihp,iscsi_lun_t * ilp,boolean_t lun_free)718fcf3ce44SJohn Forte iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
719fcf3ce44SJohn Forte {
720c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	iscsi_status_t		status		= ISCSI_STATUS_SUCCESS;
72161dfa509SRick McNeal 	dev_info_t		*cdip;
722c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	char			*pathname	= NULL;
723c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	boolean_t		offline		= B_FALSE;
724c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	nvlist_t		*attr_list	= NULL;
725fcf3ce44SJohn Forte 
726fcf3ce44SJohn Forte 	ASSERT(ilp != NULL);
727fcf3ce44SJohn Forte 	ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
728fcf3ce44SJohn Forte 
72961dfa509SRick McNeal 	if (ilp->lun_pip == NULL)
730fcf3ce44SJohn Forte 		cdip = ilp->lun_dip;
73161dfa509SRick McNeal 	else
732fcf3ce44SJohn Forte 		cdip = mdi_pi_get_client(ilp->lun_pip);
733fcf3ce44SJohn Forte 
734c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
735c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
736c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		(void) ddi_pathname(cdip, pathname);
737c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	}
738c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
739fcf3ce44SJohn Forte 	/* Attempt to offline the logical units */
740fcf3ce44SJohn Forte 	if (ilp->lun_pip != NULL) {
741fcf3ce44SJohn Forte 		/* virt/mdi */
742*3fe80ca4SDan Cross 		ndi_devi_enter(scsi_vhci_dip);
74361dfa509SRick McNeal 		if (mdi_pi_offline(ilp->lun_pip, 0) == MDI_SUCCESS) {
74491dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
74591dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
746fcf3ce44SJohn Forte 			if (lun_free == B_TRUE) {
747fcf3ce44SJohn Forte 				(void) mdi_prop_remove(ilp->lun_pip, NULL);
748fcf3ce44SJohn Forte 				(void) mdi_pi_free(ilp->lun_pip, 0);
749fcf3ce44SJohn Forte 			}
750c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			offline = B_TRUE;
751fcf3ce44SJohn Forte 		} else {
7525295a27aSJack Meng 			status = ISCSI_STATUS_BUSY;
75391dae09cSbing zhao - Sun Microsystems - Beijing China 			if (lun_free == B_FALSE) {
75491dae09cSbing zhao - Sun Microsystems - Beijing China 				ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
755c60a6da3Sbing zhao - Sun Microsystems - Beijing China 				offline = B_TRUE;
75691dae09cSbing zhao - Sun Microsystems - Beijing China 			}
757fcf3ce44SJohn Forte 		}
758*3fe80ca4SDan Cross 		ndi_devi_exit(scsi_vhci_dip);
759fcf3ce44SJohn Forte 
760fcf3ce44SJohn Forte 	} else  {
761fcf3ce44SJohn Forte 		/* phys/ndi */
76261dfa509SRick McNeal 		int flags = NDI_DEVFS_CLEAN;
76361dfa509SRick McNeal 
764*3fe80ca4SDan Cross 		ndi_devi_enter(ihp->hba_dip);
76561dfa509SRick McNeal 		if (lun_free == B_TRUE &&
76661dfa509SRick McNeal 		    (ilp->lun_state & ISCSI_LUN_STATE_ONLINE))
76761dfa509SRick McNeal 			flags |= NDI_DEVI_REMOVE;
76861dfa509SRick McNeal 		if (ndi_devi_offline(ilp->lun_dip, flags) != NDI_SUCCESS) {
7695295a27aSJack Meng 			status = ISCSI_STATUS_BUSY;
77091dae09cSbing zhao - Sun Microsystems - Beijing China 			if (lun_free == B_FALSE) {
77191dae09cSbing zhao - Sun Microsystems - Beijing China 				ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
772c60a6da3Sbing zhao - Sun Microsystems - Beijing China 				offline = B_TRUE;
77391dae09cSbing zhao - Sun Microsystems - Beijing China 			}
774fcf3ce44SJohn Forte 		} else {
77591dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
77691dae09cSbing zhao - Sun Microsystems - Beijing China 			ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
777c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			offline = B_TRUE;
778fcf3ce44SJohn Forte 		}
779*3fe80ca4SDan Cross 		ndi_devi_exit(ihp->hba_dip);
780c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	}
781c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
782c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	if (offline == B_TRUE && pathname != NULL &&
783c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	    ilp->lun_type == DTYPE_DIRECT) {
784c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
785c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		    DDI_SUCCESS) {
786c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			kmem_free(pathname, MAXNAMELEN + 1);
787c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			return (status);
788c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		}
789c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
790c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
791c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		    DDI_SUCCESS) {
792c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			nvlist_free(attr_list);
793c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			kmem_free(pathname, MAXNAMELEN + 1);
794c60a6da3Sbing zhao - Sun Microsystems - Beijing China 			return (status);
795c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		}
796fcf3ce44SJohn Forte 
797c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		iscsi_send_sysevent(ihp, EC_DEV_REMOVE, ESC_DISK, attr_list);
798c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		nvlist_free(attr_list);
799fcf3ce44SJohn Forte 	}
800c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
801c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	if (pathname != NULL) {
802c60a6da3Sbing zhao - Sun Microsystems - Beijing China 		kmem_free(pathname, MAXNAMELEN + 1);
803c60a6da3Sbing zhao - Sun Microsystems - Beijing China 	}
804c60a6da3Sbing zhao - Sun Microsystems - Beijing China 
805fcf3ce44SJohn Forte 	return (status);
806fcf3ce44SJohn Forte }
807