xref: /titanic_41/usr/src/uts/sun/io/scsi/adapters/sf.c (revision 89b43686db1fe9681d80a7cf5662730cb9378cae)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
25  */
26 
27 /*
28  * sf - Solaris Fibre Channel driver
29  *
30  * This module implements some of the Fibre Channel FC-4 layer, converting
31  * from FC frames to SCSI and back.  (Note: no sequence management is done
32  * here, though.)
33  */
34 
35 #if defined(lint) && !defined(DEBUG)
36 #define	DEBUG	1
37 #endif
38 
39 /*
40  * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
41  * Need to use the ugly RAID LUN mappings in FCP Annex D
42  * to prevent SCSA from barfing.  This *REALLY* needs to
43  * be addressed by the standards committee.
44  */
45 #define	RAID_LUNS	1
46 
47 #ifdef DEBUG
48 static int sfdebug = 0;
49 #include <sys/debug.h>
50 
51 #define	SF_DEBUG(level, args) \
52 	if (sfdebug >= (level)) sf_log args
53 #else
54 #define	SF_DEBUG(level, args)
55 #endif
56 
57 static int sf_bus_config_debug = 0;
58 
59 /* Why do I have to do this? */
60 #define	offsetof(s, m)  (size_t)(&(((s *)0)->m))
61 
62 #include <sys/scsi/scsi.h>
63 #include <sys/fc4/fcal.h>
64 #include <sys/fc4/fcp.h>
65 #include <sys/fc4/fcal_linkapp.h>
66 #include <sys/socal_cq_defs.h>
67 #include <sys/fc4/fcal_transport.h>
68 #include <sys/fc4/fcio.h>
69 #include <sys/scsi/adapters/sfvar.h>
70 #include <sys/scsi/impl/scsi_reset_notify.h>
71 #include <sys/stat.h>
72 #include <sys/varargs.h>
73 #include <sys/var.h>
74 #include <sys/thread.h>
75 #include <sys/proc.h>
76 #include <sys/kstat.h>
77 #include <sys/devctl.h>
78 #include <sys/scsi/targets/ses.h>
79 #include <sys/callb.h>
80 
81 static int sf_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
82 static int sf_attach(dev_info_t *, ddi_attach_cmd_t);
83 static int sf_detach(dev_info_t *, ddi_detach_cmd_t);
84 static void sf_softstate_unlink(struct sf *);
85 static int sf_scsi_bus_config(dev_info_t *parent, uint_t flag,
86     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
87 static int sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
88     ddi_bus_config_op_t op, void *arg);
89 static int sf_scsi_tgt_init(dev_info_t *, dev_info_t *,
90     scsi_hba_tran_t *, struct scsi_device *);
91 static void sf_scsi_tgt_free(dev_info_t *, dev_info_t *,
92     scsi_hba_tran_t *, struct scsi_device *);
93 static int sf_pkt_alloc_extern(struct sf *, struct sf_pkt *,
94     int, int, int);
95 static void sf_pkt_destroy_extern(struct sf *, struct sf_pkt *);
96 static struct scsi_pkt *sf_scsi_init_pkt(struct scsi_address *,
97     struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
98 static void sf_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
99 static void sf_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
100 static void sf_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
101 static int sf_scsi_reset_notify(struct scsi_address *, int,
102     void (*)(caddr_t), caddr_t);
103 static int sf_scsi_get_name(struct scsi_device *, char *, int);
104 static int sf_scsi_get_bus_addr(struct scsi_device *, char *, int);
105 static int sf_add_cr_pool(struct sf *);
106 static int sf_cr_alloc(struct sf *, struct sf_pkt *, int (*)());
107 static void sf_cr_free(struct sf_cr_pool *, struct sf_pkt *);
108 static void sf_crpool_free(struct sf *);
109 static int sf_kmem_cache_constructor(void *, void *, int);
110 static void sf_kmem_cache_destructor(void *, void *);
111 static void sf_statec_callback(void *, int);
112 static int sf_login(struct sf *, uchar_t, uchar_t, uint_t, int);
113 static int sf_els_transport(struct sf *, struct sf_els_hdr *);
114 static void sf_els_callback(struct fcal_packet *);
115 static int sf_do_prli(struct sf *, struct sf_els_hdr *, struct la_els_logi *);
116 static int sf_do_adisc(struct sf *, struct sf_els_hdr *);
117 static int sf_do_reportlun(struct sf *, struct sf_els_hdr *,
118     struct sf_target *);
119 static void sf_reportlun_callback(struct fcal_packet *);
120 static int sf_do_inquiry(struct sf *, struct sf_els_hdr *,
121     struct sf_target *);
122 static void sf_inq_callback(struct fcal_packet *);
123 static struct fcal_packet *sf_els_alloc(struct sf *, uchar_t, int, int,
124     int, caddr_t *, caddr_t *);
125 static void sf_els_free(struct fcal_packet *);
126 static struct sf_target *sf_create_target(struct sf *,
127     struct sf_els_hdr *, int, int64_t);
128 #ifdef RAID_LUNS
129 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int);
130 #else
131 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int64_t);
132 #endif
133 static void sf_finish_init(struct sf *, int);
134 static void sf_offline_target(struct sf *, struct sf_target *);
135 static void sf_create_devinfo(struct sf *, struct sf_target *, int);
136 static int sf_create_props(dev_info_t *, struct sf_target *, int);
137 static int sf_commoncap(struct scsi_address *, char *, int, int, int);
138 static int sf_getcap(struct scsi_address *, char *, int);
139 static int sf_setcap(struct scsi_address *, char *, int, int);
140 static int sf_abort(struct scsi_address *, struct scsi_pkt *);
141 static int sf_reset(struct scsi_address *, int);
142 static void sf_abort_all(struct sf *, struct sf_target *, int, int, int);
143 static int sf_start(struct scsi_address *, struct scsi_pkt *);
144 static int sf_start_internal(struct sf *, struct sf_pkt *);
145 static void sf_fill_ids(struct sf *, struct sf_pkt *, struct sf_target *);
146 static int sf_prepare_pkt(struct sf *, struct sf_pkt *, struct sf_target *);
147 static int sf_dopoll(struct sf *, struct sf_pkt *);
148 static void sf_cmd_callback(struct fcal_packet *);
149 static void sf_throttle(struct sf *);
150 static void sf_watch(void *);
151 static void sf_throttle_start(struct sf *);
152 static void sf_check_targets(struct sf *);
153 static void sf_check_reset_delay(void *);
154 static int sf_target_timeout(struct sf *, struct sf_pkt *);
155 static void sf_force_lip(struct sf *);
156 static void sf_unsol_els_callback(void *, soc_response_t *, caddr_t);
157 static struct sf_els_hdr *sf_els_timeout(struct sf *, struct sf_els_hdr *);
158 /*PRINTFLIKE3*/
159 static void sf_log(struct sf *, int, const char *, ...);
160 static int sf_kstat_update(kstat_t *, int);
161 static int sf_open(dev_t *, int, int, cred_t *);
162 static int sf_close(dev_t, int, int, cred_t *);
163 static int sf_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
164 static struct sf_target *sf_get_target_from_dip(struct sf *, dev_info_t *);
165 static int sf_bus_get_eventcookie(dev_info_t *, dev_info_t *, char *,
166     ddi_eventcookie_t *);
167 static int sf_bus_add_eventcall(dev_info_t *, dev_info_t *,
168     ddi_eventcookie_t, void (*)(), void *, ddi_callback_id_t *cb_id);
169 static int sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id);
170 static int sf_bus_post_event(dev_info_t *, dev_info_t *,
171     ddi_eventcookie_t, void *);
172 
173 static void sf_hp_daemon(void *);
174 
175 /*
176  * this is required to be able to supply a control node
177  * where ioctls can be executed
178  */
179 struct cb_ops sf_cb_ops = {
180 	sf_open,			/* open */
181 	sf_close,			/* close */
182 	nodev,				/* strategy */
183 	nodev,				/* print */
184 	nodev,				/* dump */
185 	nodev,				/* read */
186 	nodev,				/* write */
187 	sf_ioctl,			/* ioctl */
188 	nodev,				/* devmap */
189 	nodev,				/* mmap */
190 	nodev,				/* segmap */
191 	nochpoll,			/* poll */
192 	ddi_prop_op,			/* cb_prop_op */
193 	0,				/* streamtab  */
194 	D_MP | D_NEW | D_HOTPLUG	/* driver flags */
195 
196 };
197 
198 /*
199  * autoconfiguration routines.
200  */
201 static struct dev_ops sf_ops = {
202 	DEVO_REV,		/* devo_rev, */
203 	0,			/* refcnt  */
204 	sf_info,		/* info */
205 	nulldev,		/* identify */
206 	nulldev,		/* probe */
207 	sf_attach,		/* attach */
208 	sf_detach,		/* detach */
209 	nodev,			/* reset */
210 	&sf_cb_ops,		/* driver operations */
211 	NULL,			/* bus operations */
212 	NULL,			/* power management */
213 	ddi_quiesce_not_supported,	/* devo_quiesce */
214 };
215 
216 #define	SF_NAME	"FC-AL FCP Nexus Driver"	/* Name of the module. */
217 static	char	sf_version[] = "1.72 08/19/2008"; /* version of the module */
218 
219 static struct modldrv modldrv = {
220 	&mod_driverops, /* Type of module. This one is a driver */
221 	SF_NAME,
222 	&sf_ops,	/* driver ops */
223 };
224 
225 static struct modlinkage modlinkage = {
226 	MODREV_1, (void *)&modldrv, NULL
227 };
228 
229 /* XXXXXX The following is here to handle broken targets -- remove it later */
230 static int sf_reportlun_forever = 0;
231 /* XXXXXX */
232 static int sf_lip_on_plogo = 0;
233 static int sf_els_retries = SF_ELS_RETRIES;
234 static struct sf *sf_head = NULL;
235 static int sf_target_scan_cnt = 4;
236 static int sf_pkt_scan_cnt = 5;
237 static int sf_pool_scan_cnt = 1800;
238 static void *sf_state = NULL;
239 static int sf_watchdog_init = 0;
240 static int sf_watchdog_time = 0;
241 static int sf_watchdog_timeout = 1;
242 static int sf_watchdog_tick;
243 static int sf_watch_running = 0;
244 static timeout_id_t sf_watchdog_id;
245 static timeout_id_t sf_reset_timeout_id;
246 static int sf_max_targets = SF_MAX_TARGETS;
247 static kmutex_t sf_global_mutex;
248 static int sf_core = 0;
249 int *sf_token = NULL; /* Must not be static or lint complains. */
250 static kcondvar_t sf_watch_cv;
251 extern pri_t minclsyspri;
252 static ddi_eventcookie_t	sf_insert_eid;
253 static ddi_eventcookie_t	sf_remove_eid;
254 
255 static ndi_event_definition_t	sf_event_defs[] = {
256 { SF_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL, 0 },
257 { SF_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT, 0 }
258 };
259 
260 #define	SF_N_NDI_EVENTS	\
261 	(sizeof (sf_event_defs) / sizeof (ndi_event_definition_t))
262 
263 #ifdef DEBUG
264 static int sf_lip_flag = 1;		/* bool: to allow LIPs */
265 static int sf_reset_flag = 1;		/* bool: to allow reset after LIP */
266 static int sf_abort_flag = 0;		/* bool: to do just one abort */
267 #endif
268 
269 extern int64_t ddi_get_lbolt64(void);
270 
271 /*
272  * for converting between target number (switch) and hard address/AL_PA
273  */
274 static uchar_t sf_switch_to_alpa[] = {
275 	0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
276 	0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
277 	0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
278 	0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
279 	0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
280 	0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
281 	0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
282 	0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
283 	0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
284 	0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
285 	0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
286 	0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
287 	0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
288 };
289 
290 static uchar_t sf_alpa_to_switch[] = {
291 	0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
292 	0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
293 	0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
294 	0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
295 	0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
296 	0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
297 	0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
298 	0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
299 	0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
300 	0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
301 	0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
302 	0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
303 	0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
304 	0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
305 	0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
306 	0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
307 	0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
308 	0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
309 	0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
310 	0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
311 	0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
312 	0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
313 	0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
314 	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 };
316 
317 /*
318  * these macros call the proper transport-layer function given
319  * a particular transport
320  */
321 #define	soc_transport(a, b, c, d) (*a->fcal_ops->fcal_transport)(b, c, d)
322 #define	soc_transport_poll(a, b, c, d)\
323 	(*a->fcal_ops->fcal_transport_poll)(b, c, d)
324 #define	soc_get_lilp_map(a, b, c, d, e)\
325 	(*a->fcal_ops->fcal_lilp_map)(b, c, d, e)
326 #define	soc_force_lip(a, b, c, d, e)\
327 	(*a->fcal_ops->fcal_force_lip)(b, c, d, e)
328 #define	soc_abort(a, b, c, d, e)\
329 	(*a->fcal_ops->fcal_abort_cmd)(b, c, d, e)
330 #define	soc_force_reset(a, b, c, d)\
331 	(*a->fcal_ops->fcal_force_reset)(b, c, d)
332 #define	soc_add_ulp(a, b, c, d, e, f, g, h)\
333 	(*a->fcal_ops->fcal_add_ulp)(b, c, d, e, f, g, h)
334 #define	soc_remove_ulp(a, b, c, d, e)\
335 	(*a->fcal_ops->fcal_remove_ulp)(b, c, d, e)
336 #define	soc_take_core(a, b) (*a->fcal_ops->fcal_take_core)(b)
337 
338 
339 /* power management property defines (should be in a common include file?) */
340 #define	PM_HARDWARE_STATE_PROP		"pm-hardware-state"
341 #define	PM_NEEDS_SUSPEND_RESUME		"needs-suspend-resume"
342 
343 
344 /* node properties */
345 #define	NODE_WWN_PROP			"node-wwn"
346 #define	PORT_WWN_PROP			"port-wwn"
347 #define	LIP_CNT_PROP			"lip-count"
348 #define	TARGET_PROP			"target"
349 #define	LUN_PROP			"lun"
350 
351 
352 /*
353  * initialize this driver and install this module
354  */
355 int
_init(void)356 _init(void)
357 {
358 	int	i;
359 
360 	i = ddi_soft_state_init(&sf_state, sizeof (struct sf),
361 	    SF_INIT_ITEMS);
362 	if (i != 0)
363 		return (i);
364 
365 	if ((i = scsi_hba_init(&modlinkage)) != 0) {
366 		ddi_soft_state_fini(&sf_state);
367 		return (i);
368 	}
369 
370 	mutex_init(&sf_global_mutex, NULL, MUTEX_DRIVER, NULL);
371 	sf_watch_running = 0;
372 	cv_init(&sf_watch_cv, NULL, CV_DRIVER, NULL);
373 
374 	if ((i = mod_install(&modlinkage)) != 0) {
375 		mutex_destroy(&sf_global_mutex);
376 		cv_destroy(&sf_watch_cv);
377 		scsi_hba_fini(&modlinkage);
378 		ddi_soft_state_fini(&sf_state);
379 		return (i);
380 	}
381 
382 	return (i);
383 }
384 
385 
386 /*
387  * remove this driver module from the system
388  */
389 int
_fini(void)390 _fini(void)
391 {
392 	int	i;
393 
394 	if ((i = mod_remove(&modlinkage)) == 0) {
395 		scsi_hba_fini(&modlinkage);
396 		mutex_destroy(&sf_global_mutex);
397 		cv_destroy(&sf_watch_cv);
398 		ddi_soft_state_fini(&sf_state);
399 	}
400 	return (i);
401 }
402 
403 
404 int
_info(struct modinfo * modinfop)405 _info(struct modinfo *modinfop)
406 {
407 	return (mod_info(&modlinkage, modinfop));
408 }
409 
410 /*
411  * Given the device number return the devinfo pointer or instance
412  */
413 /*ARGSUSED*/
414 static int
sf_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)415 sf_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
416 {
417 	int		instance = SF_MINOR2INST(getminor((dev_t)arg));
418 	struct sf	*sf;
419 
420 	switch (infocmd) {
421 	case DDI_INFO_DEVT2DEVINFO:
422 		sf = ddi_get_soft_state(sf_state, instance);
423 		if (sf != NULL)
424 			*result = sf->sf_dip;
425 		else {
426 			*result = NULL;
427 			return (DDI_FAILURE);
428 		}
429 		break;
430 
431 	case DDI_INFO_DEVT2INSTANCE:
432 		*result = (void *)(uintptr_t)instance;
433 		break;
434 	default:
435 		return (DDI_FAILURE);
436 	}
437 	return (DDI_SUCCESS);
438 }
439 
440 /*
441  * either attach or resume this driver
442  */
443 static int
sf_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)444 sf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
445 {
446 	int instance;
447 	int mutex_initted = FALSE;
448 	uint_t ccount;
449 	size_t i, real_size;
450 	struct fcal_transport *handle;
451 	char buf[64];
452 	struct sf *sf, *tsf;
453 	scsi_hba_tran_t *tran = NULL;
454 	int	handle_bound = FALSE;
455 	kthread_t *tp;
456 
457 
458 	switch ((int)cmd) {
459 
460 	case DDI_RESUME:
461 
462 		/*
463 		 * we've previously been SF_STATE_OFFLINEd by a DDI_SUSPEND,
464 		 * so time to undo that and get going again by forcing a
465 		 * lip
466 		 */
467 
468 		instance = ddi_get_instance(dip);
469 
470 		sf = ddi_get_soft_state(sf_state, instance);
471 		SF_DEBUG(2, (sf, CE_CONT,
472 		    "sf_attach: DDI_RESUME for sf%d\n", instance));
473 		if (sf == NULL) {
474 			cmn_err(CE_WARN, "sf%d: bad soft state", instance);
475 			return (DDI_FAILURE);
476 		}
477 
478 		/*
479 		 * clear suspended flag so that normal operations can resume
480 		 */
481 		mutex_enter(&sf->sf_mutex);
482 		sf->sf_state &= ~SF_STATE_SUSPENDED;
483 		mutex_exit(&sf->sf_mutex);
484 
485 		/*
486 		 * force a login by setting our state to offline
487 		 */
488 		sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
489 		sf->sf_state = SF_STATE_OFFLINE;
490 
491 		/*
492 		 * call transport routine to register state change and
493 		 * ELS callback routines (to register us as a ULP)
494 		 */
495 		soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
496 		    sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
497 		    sf_statec_callback, sf_unsol_els_callback, NULL, sf);
498 
499 		/*
500 		 * call transport routine to force loop initialization
501 		 */
502 		(void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
503 		    sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
504 
505 		/*
506 		 * increment watchdog init flag, setting watchdog timeout
507 		 * if we are the first (since somebody has to do it)
508 		 */
509 		mutex_enter(&sf_global_mutex);
510 		if (!sf_watchdog_init++) {
511 			mutex_exit(&sf_global_mutex);
512 			sf_watchdog_id = timeout(sf_watch,
513 			    (caddr_t)0, sf_watchdog_tick);
514 		} else {
515 			mutex_exit(&sf_global_mutex);
516 		}
517 
518 		return (DDI_SUCCESS);
519 
520 	case DDI_ATTACH:
521 
522 		/*
523 		 * this instance attaching for the first time
524 		 */
525 
526 		instance = ddi_get_instance(dip);
527 
528 		if (ddi_soft_state_zalloc(sf_state, instance) !=
529 		    DDI_SUCCESS) {
530 			cmn_err(CE_WARN, "sf%d: failed to allocate soft state",
531 			    instance);
532 			return (DDI_FAILURE);
533 		}
534 
535 		sf = ddi_get_soft_state(sf_state, instance);
536 		SF_DEBUG(4, (sf, CE_CONT,
537 		    "sf_attach: DDI_ATTACH for sf%d\n", instance));
538 		if (sf == NULL) {
539 			/* this shouldn't happen since we just allocated it */
540 			cmn_err(CE_WARN, "sf%d: bad soft state", instance);
541 			return (DDI_FAILURE);
542 		}
543 
544 		/*
545 		 * from this point on, if there's an error, we must de-allocate
546 		 * soft state before returning DDI_FAILURE
547 		 */
548 
549 		if ((handle = ddi_get_parent_data(dip)) == NULL) {
550 			cmn_err(CE_WARN,
551 			    "sf%d: failed to obtain transport handle",
552 			    instance);
553 			goto fail;
554 		}
555 
556 		/* fill in our soft state structure */
557 		sf->sf_dip = dip;
558 		sf->sf_state = SF_STATE_INIT;
559 		sf->sf_throttle = handle->fcal_cmdmax;
560 		sf->sf_sochandle = handle;
561 		sf->sf_socp = handle->fcal_handle;
562 		sf->sf_check_n_close = 0;
563 
564 		/* create a command/response buffer pool for this instance */
565 		if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
566 			cmn_err(CE_WARN,
567 			    "sf%d: failed to allocate command/response pool",
568 			    instance);
569 			goto fail;
570 		}
571 
572 		/* create a a cache for this instance */
573 		(void) sprintf(buf, "sf%d_cache", instance);
574 		sf->sf_pkt_cache = kmem_cache_create(buf,
575 		    sizeof (fcal_packet_t) + sizeof (struct sf_pkt) +
576 		    scsi_pkt_size(), 8,
577 		    sf_kmem_cache_constructor, sf_kmem_cache_destructor,
578 		    NULL, NULL, NULL, 0);
579 		if (sf->sf_pkt_cache == NULL) {
580 			cmn_err(CE_WARN, "sf%d: failed to allocate kmem cache",
581 			    instance);
582 			goto fail;
583 		}
584 
585 		/* set up a handle and allocate memory for DMA */
586 		if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->
587 		    fcal_dmaattr, DDI_DMA_DONTWAIT, NULL, &sf->
588 		    sf_lilp_dmahandle) != DDI_SUCCESS) {
589 			cmn_err(CE_WARN,
590 			    "sf%d: failed to allocate dma handle for lilp map",
591 			    instance);
592 			goto fail;
593 		}
594 		i = sizeof (struct fcal_lilp_map) + 1;
595 		if (ddi_dma_mem_alloc(sf->sf_lilp_dmahandle,
596 		    i, sf->sf_sochandle->
597 		    fcal_accattr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
598 		    (caddr_t *)&sf->sf_lilp_map, &real_size,
599 		    &sf->sf_lilp_acchandle) != DDI_SUCCESS) {
600 			cmn_err(CE_WARN, "sf%d: failed to allocate lilp map",
601 			    instance);
602 			goto fail;
603 		}
604 		if (real_size < i) {
605 			/* no error message ??? */
606 			goto fail;		/* trouble allocating memory */
607 		}
608 
609 		/*
610 		 * set up the address for the DMA transfers (getting a cookie)
611 		 */
612 		if (ddi_dma_addr_bind_handle(sf->sf_lilp_dmahandle, NULL,
613 		    (caddr_t)sf->sf_lilp_map, real_size,
614 		    DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
615 		    &sf->sf_lilp_dmacookie, &ccount) != DDI_DMA_MAPPED) {
616 			cmn_err(CE_WARN,
617 			    "sf%d: failed to bind dma handle for lilp map",
618 			    instance);
619 			goto fail;
620 		}
621 		handle_bound = TRUE;
622 		/* ensure only one cookie was allocated */
623 		if (ccount != 1) {
624 			goto fail;
625 		}
626 
627 		/* ensure LILP map and DMA cookie addresses are even?? */
628 		sf->sf_lilp_map = (struct fcal_lilp_map *)(((uintptr_t)sf->
629 		    sf_lilp_map + 1) & ~1);
630 		sf->sf_lilp_dmacookie.dmac_address = (sf->
631 		    sf_lilp_dmacookie.dmac_address + 1) & ~1;
632 
633 		/* set up all of our mutexes and condition variables */
634 		mutex_init(&sf->sf_mutex, NULL, MUTEX_DRIVER, NULL);
635 		mutex_init(&sf->sf_cmd_mutex, NULL, MUTEX_DRIVER, NULL);
636 		mutex_init(&sf->sf_cr_mutex, NULL, MUTEX_DRIVER, NULL);
637 		mutex_init(&sf->sf_hp_daemon_mutex, NULL, MUTEX_DRIVER, NULL);
638 		cv_init(&sf->sf_cr_cv, NULL, CV_DRIVER, NULL);
639 		cv_init(&sf->sf_hp_daemon_cv, NULL, CV_DRIVER, NULL);
640 
641 		mutex_initted = TRUE;
642 
643 		/* create our devctl minor node */
644 		if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
645 		    SF_INST2DEVCTL_MINOR(instance),
646 		    DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
647 			cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
648 			    " for devctl", instance);
649 			goto fail;
650 		}
651 
652 		/* create fc minor node */
653 		if (ddi_create_minor_node(dip, "fc", S_IFCHR,
654 		    SF_INST2FC_MINOR(instance), DDI_NT_FC_ATTACHMENT_POINT,
655 		    0) != DDI_SUCCESS) {
656 			cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
657 			    " for fc", instance);
658 			goto fail;
659 		}
660 		/* allocate a SCSI transport structure */
661 		tran = scsi_hba_tran_alloc(dip, 0);
662 		if (tran == NULL) {
663 			/* remove all minor nodes created */
664 			ddi_remove_minor_node(dip, NULL);
665 			cmn_err(CE_WARN, "sf%d: scsi_hba_tran_alloc failed",
666 			    instance);
667 			goto fail;
668 		}
669 
670 		/* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
671 		scsi_size_clean(dip);		/* SCSI_SIZE_CLEAN_VERIFY ok */
672 
673 		/* save ptr to new transport structure and fill it in */
674 		sf->sf_tran = tran;
675 
676 		tran->tran_hba_private		= sf;
677 		tran->tran_tgt_private		= NULL;
678 		tran->tran_tgt_init		= sf_scsi_tgt_init;
679 		tran->tran_tgt_probe		= NULL;
680 		tran->tran_tgt_free		= sf_scsi_tgt_free;
681 
682 		tran->tran_start		= sf_start;
683 		tran->tran_abort		= sf_abort;
684 		tran->tran_reset		= sf_reset;
685 		tran->tran_getcap		= sf_getcap;
686 		tran->tran_setcap		= sf_setcap;
687 		tran->tran_init_pkt		= sf_scsi_init_pkt;
688 		tran->tran_destroy_pkt		= sf_scsi_destroy_pkt;
689 		tran->tran_dmafree		= sf_scsi_dmafree;
690 		tran->tran_sync_pkt		= sf_scsi_sync_pkt;
691 		tran->tran_reset_notify		= sf_scsi_reset_notify;
692 
693 		/*
694 		 * register event notification routines with scsa
695 		 */
696 		tran->tran_get_eventcookie	= sf_bus_get_eventcookie;
697 		tran->tran_add_eventcall	= sf_bus_add_eventcall;
698 		tran->tran_remove_eventcall	= sf_bus_remove_eventcall;
699 		tran->tran_post_event		= sf_bus_post_event;
700 
701 		/*
702 		 * register bus configure/unconfigure
703 		 */
704 		tran->tran_bus_config		= sf_scsi_bus_config;
705 		tran->tran_bus_unconfig		= sf_scsi_bus_unconfig;
706 
707 		/*
708 		 * allocate an ndi event handle
709 		 */
710 		sf->sf_event_defs = (ndi_event_definition_t *)
711 		    kmem_zalloc(sizeof (sf_event_defs), KM_SLEEP);
712 
713 		bcopy(sf_event_defs, sf->sf_event_defs,
714 		    sizeof (sf_event_defs));
715 
716 		(void) ndi_event_alloc_hdl(dip, NULL,
717 		    &sf->sf_event_hdl, NDI_SLEEP);
718 
719 		sf->sf_events.ndi_events_version = NDI_EVENTS_REV1;
720 		sf->sf_events.ndi_n_events = SF_N_NDI_EVENTS;
721 		sf->sf_events.ndi_event_defs = sf->sf_event_defs;
722 
723 		if (ndi_event_bind_set(sf->sf_event_hdl,
724 		    &sf->sf_events, NDI_SLEEP) != NDI_SUCCESS) {
725 			goto fail;
726 		}
727 
728 		tran->tran_get_name		= sf_scsi_get_name;
729 		tran->tran_get_bus_addr		= sf_scsi_get_bus_addr;
730 
731 		/* setup and attach SCSI hba transport */
732 		if (scsi_hba_attach_setup(dip, sf->sf_sochandle->
733 		    fcal_dmaattr, tran, SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
734 			cmn_err(CE_WARN, "sf%d: scsi_hba_attach_setup failed",
735 			    instance);
736 			goto fail;
737 		}
738 
739 		/* set up kstats */
740 		if ((sf->sf_ksp = kstat_create("sf", instance, "statistics",
741 		    "controller", KSTAT_TYPE_RAW, sizeof (struct sf_stats),
742 		    KSTAT_FLAG_VIRTUAL)) == NULL) {
743 			cmn_err(CE_WARN, "sf%d: failed to create kstat",
744 			    instance);
745 		} else {
746 			sf->sf_stats.version = 2;
747 			(void) sprintf(sf->sf_stats.drvr_name,
748 			"%s: %s", SF_NAME, sf_version);
749 			sf->sf_ksp->ks_data = (void *)&sf->sf_stats;
750 			sf->sf_ksp->ks_private = sf;
751 			sf->sf_ksp->ks_update = sf_kstat_update;
752 			kstat_install(sf->sf_ksp);
753 		}
754 
755 		/* create the hotplug thread */
756 		mutex_enter(&sf->sf_hp_daemon_mutex);
757 		tp = thread_create(NULL, 0,
758 		    (void (*)())sf_hp_daemon, sf, 0, &p0, TS_RUN, minclsyspri);
759 		sf->sf_hp_tid = tp->t_did;
760 		mutex_exit(&sf->sf_hp_daemon_mutex);
761 
762 		/* add this soft state instance to the head of the list */
763 		mutex_enter(&sf_global_mutex);
764 		sf->sf_next = sf_head;
765 		tsf = sf_head;
766 		sf_head = sf;
767 
768 		/*
769 		 * find entry in list that has the same FC-AL handle (if any)
770 		 */
771 		while (tsf != NULL) {
772 			if (tsf->sf_socp == sf->sf_socp) {
773 				break;		/* found matching entry */
774 			}
775 			tsf = tsf->sf_next;
776 		}
777 
778 		if (tsf != NULL) {
779 			/* if we found a matching entry keep track of it */
780 			sf->sf_sibling = tsf;
781 		}
782 
783 		/*
784 		 * increment watchdog init flag, setting watchdog timeout
785 		 * if we are the first (since somebody has to do it)
786 		 */
787 		if (!sf_watchdog_init++) {
788 			mutex_exit(&sf_global_mutex);
789 			sf_watchdog_tick = sf_watchdog_timeout *
790 			    drv_usectohz(1000000);
791 			sf_watchdog_id = timeout(sf_watch,
792 			    NULL, sf_watchdog_tick);
793 		} else {
794 			mutex_exit(&sf_global_mutex);
795 		}
796 
797 		if (tsf != NULL) {
798 			/*
799 			 * set up matching entry to be our sibling
800 			 */
801 			mutex_enter(&tsf->sf_mutex);
802 			tsf->sf_sibling = sf;
803 			mutex_exit(&tsf->sf_mutex);
804 		}
805 
806 		/*
807 		 * create this property so that PM code knows we want
808 		 * to be suspended at PM time
809 		 */
810 		(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
811 		    PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
812 
813 		/* log the fact that we have a new device */
814 		ddi_report_dev(dip);
815 
816 		/*
817 		 * force a login by setting our state to offline
818 		 */
819 		sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
820 		sf->sf_state = SF_STATE_OFFLINE;
821 
822 		/*
823 		 * call transport routine to register state change and
824 		 * ELS callback routines (to register us as a ULP)
825 		 */
826 		soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
827 		    sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
828 		    sf_statec_callback, sf_unsol_els_callback, NULL, sf);
829 
830 		/*
831 		 * call transport routine to force loop initialization
832 		 */
833 		(void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
834 		    sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
835 		sf->sf_reset_time = ddi_get_lbolt64();
836 		return (DDI_SUCCESS);
837 
838 	default:
839 		return (DDI_FAILURE);
840 	}
841 
842 fail:
843 	cmn_err(CE_WARN, "sf%d: failed to attach", instance);
844 
845 	/*
846 	 * Unbind and free event set
847 	 */
848 	if (sf->sf_event_hdl) {
849 		(void) ndi_event_unbind_set(sf->sf_event_hdl,
850 		    &sf->sf_events, NDI_SLEEP);
851 		(void) ndi_event_free_hdl(sf->sf_event_hdl);
852 	}
853 
854 	if (sf->sf_event_defs) {
855 		kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
856 	}
857 
858 	if (sf->sf_tran != NULL) {
859 		scsi_hba_tran_free(sf->sf_tran);
860 	}
861 	while (sf->sf_cr_pool != NULL) {
862 		sf_crpool_free(sf);
863 	}
864 	if (sf->sf_lilp_dmahandle != NULL) {
865 		if (handle_bound) {
866 			(void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
867 		}
868 		ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
869 	}
870 	if (sf->sf_pkt_cache != NULL) {
871 		kmem_cache_destroy(sf->sf_pkt_cache);
872 	}
873 	if (sf->sf_lilp_map != NULL) {
874 		ddi_dma_mem_free(&sf->sf_lilp_acchandle);
875 	}
876 	if (sf->sf_ksp != NULL) {
877 		kstat_delete(sf->sf_ksp);
878 	}
879 	if (mutex_initted) {
880 		mutex_destroy(&sf->sf_mutex);
881 		mutex_destroy(&sf->sf_cmd_mutex);
882 		mutex_destroy(&sf->sf_cr_mutex);
883 		mutex_destroy(&sf->sf_hp_daemon_mutex);
884 		cv_destroy(&sf->sf_cr_cv);
885 		cv_destroy(&sf->sf_hp_daemon_cv);
886 	}
887 	mutex_enter(&sf_global_mutex);
888 
889 	/*
890 	 * kill off the watchdog if we are the last instance
891 	 */
892 	if (!--sf_watchdog_init) {
893 		timeout_id_t tid = sf_watchdog_id;
894 		mutex_exit(&sf_global_mutex);
895 		(void) untimeout(tid);
896 	} else {
897 		mutex_exit(&sf_global_mutex);
898 	}
899 
900 	ddi_soft_state_free(sf_state, instance);
901 
902 	if (tran != NULL) {
903 		/* remove all minor nodes */
904 		ddi_remove_minor_node(dip, NULL);
905 	}
906 
907 	return (DDI_FAILURE);
908 }
909 
910 
911 /* ARGSUSED */
912 static int
sf_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)913 sf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
914 {
915 	struct sf		*sf;
916 	int			instance;
917 	int			i;
918 	struct sf_target	*target;
919 	timeout_id_t		tid;
920 
921 
922 
923 	/* NO OTHER THREADS ARE RUNNING */
924 
925 	instance = ddi_get_instance(dip);
926 
927 	if ((sf = ddi_get_soft_state(sf_state, instance)) == NULL) {
928 		cmn_err(CE_WARN, "sf_detach, sf%d: bad soft state", instance);
929 		return (DDI_FAILURE);
930 	}
931 
932 	switch (cmd) {
933 
934 	case DDI_SUSPEND:
935 		/*
936 		 * suspend our instance
937 		 */
938 
939 		SF_DEBUG(2, (sf, CE_CONT,
940 		    "sf_detach: DDI_SUSPEND for sf%d\n", instance));
941 		/*
942 		 * There is a race condition in socal where while doing
943 		 * callbacks if a ULP removes it self from the callback list
944 		 * the for loop in socal may panic as cblist is junk and
945 		 * while trying to get cblist->next the system will panic.
946 		 */
947 
948 		/* call transport to remove our unregister our callbacks */
949 		soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
950 		    sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
951 
952 		/*
953 		 * begin process of clearing outstanding commands
954 		 * by issuing a lip
955 		 */
956 		sf_force_lip(sf);
957 
958 		/*
959 		 * toggle the device OFFLINE in order to cause
960 		 * outstanding commands to drain
961 		 */
962 		mutex_enter(&sf->sf_mutex);
963 		sf->sf_lip_cnt++;
964 		sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
965 		sf->sf_state = (SF_STATE_OFFLINE | SF_STATE_SUSPENDED);
966 		for (i = 0; i < sf_max_targets; i++) {
967 			target = sf->sf_targets[i];
968 			if (target != NULL) {
969 				struct sf_target *ntarget;
970 
971 				mutex_enter(&target->sft_mutex);
972 				if (!(target->sft_state & SF_TARGET_OFFLINE)) {
973 					target->sft_state |=
974 					    (SF_TARGET_BUSY | SF_TARGET_MARK);
975 				}
976 				/* do this for all LUNs as well */
977 				for (ntarget = target->sft_next_lun;
978 				    ntarget;
979 				    ntarget = ntarget->sft_next_lun) {
980 					mutex_enter(&ntarget->sft_mutex);
981 					if (!(ntarget->sft_state &
982 					    SF_TARGET_OFFLINE)) {
983 						ntarget->sft_state |=
984 						    (SF_TARGET_BUSY |
985 						    SF_TARGET_MARK);
986 					}
987 					mutex_exit(&ntarget->sft_mutex);
988 				}
989 				mutex_exit(&target->sft_mutex);
990 			}
991 		}
992 		mutex_exit(&sf->sf_mutex);
993 		mutex_enter(&sf_global_mutex);
994 
995 		/*
996 		 * kill off the watchdog if we are the last instance
997 		 */
998 		if (!--sf_watchdog_init) {
999 			tid = sf_watchdog_id;
1000 			mutex_exit(&sf_global_mutex);
1001 			(void) untimeout(tid);
1002 		} else {
1003 			mutex_exit(&sf_global_mutex);
1004 		}
1005 
1006 		return (DDI_SUCCESS);
1007 
1008 	case DDI_DETACH:
1009 		/*
1010 		 * detach this instance
1011 		 */
1012 
1013 		SF_DEBUG(2, (sf, CE_CONT,
1014 		    "sf_detach: DDI_DETACH for sf%d\n", instance));
1015 
1016 		/* remove this "sf" from the list of sf softstates */
1017 		sf_softstate_unlink(sf);
1018 
1019 		/*
1020 		 * prior to taking any DDI_DETACH actions, toggle the
1021 		 * device OFFLINE in order to cause outstanding
1022 		 * commands to drain
1023 		 */
1024 		mutex_enter(&sf->sf_mutex);
1025 		sf->sf_lip_cnt++;
1026 		sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
1027 		sf->sf_state = SF_STATE_OFFLINE;
1028 		for (i = 0; i < sf_max_targets; i++) {
1029 			target = sf->sf_targets[i];
1030 			if (target != NULL) {
1031 				struct sf_target *ntarget;
1032 
1033 				mutex_enter(&target->sft_mutex);
1034 				if (!(target->sft_state & SF_TARGET_OFFLINE)) {
1035 					target->sft_state |=
1036 					    (SF_TARGET_BUSY | SF_TARGET_MARK);
1037 				}
1038 				for (ntarget = target->sft_next_lun;
1039 				    ntarget;
1040 				    ntarget = ntarget->sft_next_lun) {
1041 					mutex_enter(&ntarget->sft_mutex);
1042 					if (!(ntarget->sft_state &
1043 					    SF_TARGET_OFFLINE)) {
1044 						ntarget->sft_state |=
1045 						    (SF_TARGET_BUSY |
1046 						    SF_TARGET_MARK);
1047 					}
1048 					mutex_exit(&ntarget->sft_mutex);
1049 				}
1050 				mutex_exit(&target->sft_mutex);
1051 			}
1052 		}
1053 		mutex_exit(&sf->sf_mutex);
1054 
1055 		/* call transport to remove and unregister our callbacks */
1056 		soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
1057 		    sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
1058 
1059 		/*
1060 		 * kill off the watchdog if we are the last instance
1061 		 */
1062 		mutex_enter(&sf_global_mutex);
1063 		if (!--sf_watchdog_init) {
1064 			tid = sf_watchdog_id;
1065 			mutex_exit(&sf_global_mutex);
1066 			(void) untimeout(tid);
1067 		} else {
1068 			mutex_exit(&sf_global_mutex);
1069 		}
1070 
1071 		/* signal sf_hp_daemon() to exit and wait for exit */
1072 		mutex_enter(&sf->sf_hp_daemon_mutex);
1073 		ASSERT(sf->sf_hp_tid);
1074 		sf->sf_hp_exit = 1;		/* flag exit */
1075 		cv_signal(&sf->sf_hp_daemon_cv);
1076 		mutex_exit(&sf->sf_hp_daemon_mutex);
1077 		thread_join(sf->sf_hp_tid);	/* wait for hotplug to exit */
1078 
1079 		/*
1080 		 * Unbind and free event set
1081 		 */
1082 		if (sf->sf_event_hdl) {
1083 			(void) ndi_event_unbind_set(sf->sf_event_hdl,
1084 			    &sf->sf_events, NDI_SLEEP);
1085 			(void) ndi_event_free_hdl(sf->sf_event_hdl);
1086 		}
1087 
1088 		if (sf->sf_event_defs) {
1089 			kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
1090 		}
1091 
1092 		/* detach this instance of the HBA driver */
1093 		(void) scsi_hba_detach(dip);
1094 		scsi_hba_tran_free(sf->sf_tran);
1095 
1096 		/* deallocate/unbind DMA handle for lilp map */
1097 		if (sf->sf_lilp_map != NULL) {
1098 			(void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
1099 			if (sf->sf_lilp_dmahandle != NULL) {
1100 				ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
1101 			}
1102 			ddi_dma_mem_free(&sf->sf_lilp_acchandle);
1103 		}
1104 
1105 		/*
1106 		 * the kmem cache must be destroyed before free'ing
1107 		 * up the crpools
1108 		 *
1109 		 * our finagle of "ntot" and "nfree"
1110 		 * causes an ASSERT failure in "sf_cr_free()"
1111 		 * if the kmem cache is free'd after invoking
1112 		 * "sf_crpool_free()".
1113 		 */
1114 		kmem_cache_destroy(sf->sf_pkt_cache);
1115 
1116 		SF_DEBUG(2, (sf, CE_CONT,
1117 		    "sf_detach: sf_crpool_free() for instance 0x%x\n",
1118 		    instance));
1119 		while (sf->sf_cr_pool != NULL) {
1120 			/*
1121 			 * set ntot to nfree for this particular entry
1122 			 *
1123 			 * this causes sf_crpool_free() to update
1124 			 * the cr_pool list when deallocating this entry
1125 			 */
1126 			sf->sf_cr_pool->ntot = sf->sf_cr_pool->nfree;
1127 			sf_crpool_free(sf);
1128 		}
1129 
1130 		/*
1131 		 * now that the cr_pool's are gone it's safe
1132 		 * to destroy all softstate mutex's and cv's
1133 		 */
1134 		mutex_destroy(&sf->sf_mutex);
1135 		mutex_destroy(&sf->sf_cmd_mutex);
1136 		mutex_destroy(&sf->sf_cr_mutex);
1137 		mutex_destroy(&sf->sf_hp_daemon_mutex);
1138 		cv_destroy(&sf->sf_cr_cv);
1139 		cv_destroy(&sf->sf_hp_daemon_cv);
1140 
1141 		/* remove all minor nodes from the device tree */
1142 		ddi_remove_minor_node(dip, NULL);
1143 
1144 		/* remove properties created during attach() */
1145 		ddi_prop_remove_all(dip);
1146 
1147 		/* remove kstat's if present */
1148 		if (sf->sf_ksp != NULL) {
1149 			kstat_delete(sf->sf_ksp);
1150 		}
1151 
1152 		SF_DEBUG(2, (sf, CE_CONT,
1153 		    "sf_detach: ddi_soft_state_free() for instance 0x%x\n",
1154 		    instance));
1155 		ddi_soft_state_free(sf_state, instance);
1156 		return (DDI_SUCCESS);
1157 
1158 	default:
1159 		SF_DEBUG(2, (sf, CE_CONT, "sf_detach: sf%d unknown cmd %x\n",
1160 		    instance, (int)cmd));
1161 		return (DDI_FAILURE);
1162 	}
1163 }
1164 
1165 
1166 /*
1167  * sf_softstate_unlink() - remove an sf instance from the list of softstates
1168  */
1169 static void
sf_softstate_unlink(struct sf * sf)1170 sf_softstate_unlink(struct sf *sf)
1171 {
1172 	struct sf	*sf_ptr;
1173 	struct sf	*sf_found_sibling;
1174 	struct sf	*sf_reposition = NULL;
1175 
1176 
1177 	mutex_enter(&sf_global_mutex);
1178 	while (sf_watch_running) {
1179 		/* Busy working the list -- wait */
1180 		cv_wait(&sf_watch_cv, &sf_global_mutex);
1181 	}
1182 	if ((sf_found_sibling = sf->sf_sibling) != NULL) {
1183 		/*
1184 		 * we have a sibling so NULL out its reference to us
1185 		 */
1186 		mutex_enter(&sf_found_sibling->sf_mutex);
1187 		sf_found_sibling->sf_sibling = NULL;
1188 		mutex_exit(&sf_found_sibling->sf_mutex);
1189 	}
1190 
1191 	/* remove our instance from the global list */
1192 	if (sf == sf_head) {
1193 		/* we were at at head of the list */
1194 		sf_head = sf->sf_next;
1195 	} else {
1196 		/* find us in the list */
1197 		for (sf_ptr = sf_head;
1198 		    sf_ptr != NULL;
1199 		    sf_ptr = sf_ptr->sf_next) {
1200 			if (sf_ptr == sf) {
1201 				break;
1202 			}
1203 			/* remember this place */
1204 			sf_reposition = sf_ptr;
1205 		}
1206 		ASSERT(sf_ptr == sf);
1207 		ASSERT(sf_reposition != NULL);
1208 
1209 		sf_reposition->sf_next = sf_ptr->sf_next;
1210 	}
1211 	mutex_exit(&sf_global_mutex);
1212 }
1213 
1214 
1215 static int
sf_scsi_bus_config(dev_info_t * parent,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)1216 sf_scsi_bus_config(dev_info_t *parent, uint_t flag,
1217     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
1218 {
1219 	int64_t		reset_delay;
1220 	struct sf	*sf;
1221 
1222 	sf = ddi_get_soft_state(sf_state, ddi_get_instance(parent));
1223 	ASSERT(sf);
1224 
1225 	reset_delay = (int64_t)(USEC_TO_TICK(SF_INIT_WAIT_TIMEOUT)) -
1226 	    (ddi_get_lbolt64() - sf->sf_reset_time);
1227 	if (reset_delay < 0)
1228 		reset_delay = 0;
1229 
1230 	if (sf_bus_config_debug)
1231 		flag |= NDI_DEVI_DEBUG;
1232 
1233 	return (ndi_busop_bus_config(parent, flag, op,
1234 	    arg, childp, (clock_t)reset_delay));
1235 }
1236 
1237 static int
sf_scsi_bus_unconfig(dev_info_t * parent,uint_t flag,ddi_bus_config_op_t op,void * arg)1238 sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
1239     ddi_bus_config_op_t op, void *arg)
1240 {
1241 	if (sf_bus_config_debug)
1242 		flag |= NDI_DEVI_DEBUG;
1243 
1244 	return (ndi_busop_bus_unconfig(parent, flag, op, arg));
1245 }
1246 
1247 
1248 /*
1249  * called by transport to initialize a SCSI target
1250  */
1251 /* ARGSUSED */
1252 static int
sf_scsi_tgt_init(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)1253 sf_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1254     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1255 {
1256 #ifdef RAID_LUNS
1257 	int lun;
1258 #else
1259 	int64_t lun;
1260 #endif
1261 	struct sf_target *target;
1262 	struct sf *sf = (struct sf *)hba_tran->tran_hba_private;
1263 	int i, t_len;
1264 	unsigned int lip_cnt;
1265 	unsigned char wwn[FC_WWN_SIZE];
1266 
1267 
1268 	/* get and validate our SCSI target ID */
1269 	i = sd->sd_address.a_target;
1270 	if (i >= sf_max_targets) {
1271 		return (DDI_NOT_WELL_FORMED);
1272 	}
1273 
1274 	/* get our port WWN property */
1275 	t_len = sizeof (wwn);
1276 	if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1277 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
1278 	    (caddr_t)&wwn, &t_len) != DDI_SUCCESS) {
1279 		/* no port WWN property - ignore the OBP stub node */
1280 		return (DDI_NOT_WELL_FORMED);
1281 	}
1282 
1283 	/* get our LIP count property */
1284 	t_len = sizeof (lip_cnt);
1285 	if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1286 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, LIP_CNT_PROP,
1287 	    (caddr_t)&lip_cnt, &t_len) != DDI_SUCCESS) {
1288 		return (DDI_FAILURE);
1289 	}
1290 	/* and our LUN property */
1291 	t_len = sizeof (lun);
1292 	if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1293 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
1294 	    (caddr_t)&lun, &t_len) != DDI_SUCCESS) {
1295 		return (DDI_FAILURE);
1296 	}
1297 
1298 	/* find the target structure for this instance */
1299 	mutex_enter(&sf->sf_mutex);
1300 	if ((target = sf_lookup_target(sf, wwn, lun)) == NULL) {
1301 		mutex_exit(&sf->sf_mutex);
1302 		return (DDI_FAILURE);
1303 	}
1304 
1305 	mutex_enter(&target->sft_mutex);
1306 	if ((sf->sf_lip_cnt == lip_cnt) && !(target->sft_state
1307 	    & SF_TARGET_INIT_DONE)) {
1308 		/*
1309 		 * set links between HBA transport and target structures
1310 		 * and set done flag
1311 		 */
1312 		hba_tran->tran_tgt_private = target;
1313 		target->sft_tran = hba_tran;
1314 		target->sft_state |= SF_TARGET_INIT_DONE;
1315 	} else {
1316 		/* already initialized ?? */
1317 		mutex_exit(&target->sft_mutex);
1318 		mutex_exit(&sf->sf_mutex);
1319 		return (DDI_FAILURE);
1320 	}
1321 	mutex_exit(&target->sft_mutex);
1322 	mutex_exit(&sf->sf_mutex);
1323 
1324 	return (DDI_SUCCESS);
1325 }
1326 
1327 
1328 /*
1329  * called by transport to free a target
1330  */
1331 /* ARGSUSED */
1332 static void
sf_scsi_tgt_free(dev_info_t * hba_dip,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)1333 sf_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1334     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1335 {
1336 	struct sf_target *target = hba_tran->tran_tgt_private;
1337 
1338 	if (target != NULL) {
1339 		mutex_enter(&target->sft_mutex);
1340 		target->sft_tran = NULL;
1341 		target->sft_state &= ~SF_TARGET_INIT_DONE;
1342 		mutex_exit(&target->sft_mutex);
1343 	}
1344 }
1345 
1346 
1347 /*
1348  * allocator for non-std size cdb/pkt_private/status -- return TRUE iff
1349  * success, else return FALSE
1350  */
1351 /*ARGSUSED*/
1352 static int
sf_pkt_alloc_extern(struct sf * sf,struct sf_pkt * cmd,int tgtlen,int statuslen,int kf)1353 sf_pkt_alloc_extern(struct sf *sf, struct sf_pkt *cmd,
1354     int tgtlen, int statuslen, int kf)
1355 {
1356 	caddr_t scbp, tgt;
1357 	int failure = FALSE;
1358 	struct scsi_pkt *pkt = CMD2PKT(cmd);
1359 
1360 
1361 	tgt = scbp = NULL;
1362 
1363 	if (tgtlen > PKT_PRIV_LEN) {
1364 		if ((tgt = kmem_zalloc(tgtlen, kf)) == NULL) {
1365 			failure = TRUE;
1366 		} else {
1367 			cmd->cmd_flags |= CFLAG_PRIVEXTERN;
1368 			pkt->pkt_private = tgt;
1369 		}
1370 	}
1371 	if (statuslen > EXTCMDS_STATUS_SIZE) {
1372 		if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
1373 			failure = TRUE;
1374 		} else {
1375 			cmd->cmd_flags |= CFLAG_SCBEXTERN;
1376 			pkt->pkt_scbp = (opaque_t)scbp;
1377 		}
1378 	}
1379 	if (failure) {
1380 		sf_pkt_destroy_extern(sf, cmd);
1381 	}
1382 	return (failure);
1383 }
1384 
1385 
1386 /*
1387  * deallocator for non-std size cdb/pkt_private/status
1388  */
1389 static void
sf_pkt_destroy_extern(struct sf * sf,struct sf_pkt * cmd)1390 sf_pkt_destroy_extern(struct sf *sf, struct sf_pkt *cmd)
1391 {
1392 	struct scsi_pkt *pkt = CMD2PKT(cmd);
1393 
1394 	if (cmd->cmd_flags & CFLAG_FREE) {
1395 		cmn_err(CE_PANIC,
1396 		    "sf_scsi_impl_pktfree: freeing free packet");
1397 		_NOTE(NOT_REACHED)
1398 		/* NOTREACHED */
1399 	}
1400 	if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
1401 		kmem_free((caddr_t)pkt->pkt_scbp,
1402 		    (size_t)cmd->cmd_scblen);
1403 	}
1404 	if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
1405 		kmem_free((caddr_t)pkt->pkt_private,
1406 		    (size_t)cmd->cmd_privlen);
1407 	}
1408 
1409 	cmd->cmd_flags = CFLAG_FREE;
1410 	kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
1411 }
1412 
1413 
1414 /*
1415  * create or initialize a SCSI packet -- called internally and
1416  * by the transport
1417  */
1418 static struct scsi_pkt *
sf_scsi_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)1419 sf_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1420     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
1421     int flags, int (*callback)(), caddr_t arg)
1422 {
1423 	int kf;
1424 	int failure = FALSE;
1425 	struct sf_pkt *cmd;
1426 	struct sf *sf = ADDR2SF(ap);
1427 	struct sf_target *target = ADDR2TARGET(ap);
1428 	struct sf_pkt	*new_cmd = NULL;
1429 	struct fcal_packet	*fpkt;
1430 	fc_frame_header_t	*hp;
1431 	struct fcp_cmd *fcmd;
1432 
1433 
1434 	/*
1435 	 * If we've already allocated a pkt once,
1436 	 * this request is for dma allocation only.
1437 	 */
1438 	if (pkt == NULL) {
1439 
1440 		/*
1441 		 * First step of sf_scsi_init_pkt:  pkt allocation
1442 		 */
1443 		if (cmdlen > FCP_CDB_SIZE) {
1444 			return (NULL);
1445 		}
1446 
1447 		kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
1448 
1449 		if ((cmd = kmem_cache_alloc(sf->sf_pkt_cache, kf)) != NULL) {
1450 			/*
1451 			 * Selective zeroing of the pkt.
1452 			 */
1453 
1454 			cmd->cmd_flags = 0;
1455 			cmd->cmd_forw = 0;
1456 			cmd->cmd_back = 0;
1457 			cmd->cmd_next = 0;
1458 			cmd->cmd_pkt = (struct scsi_pkt *)((char *)cmd +
1459 			    sizeof (struct sf_pkt) + sizeof (struct
1460 			    fcal_packet));
1461 			cmd->cmd_fp_pkt = (struct fcal_packet *)((char *)cmd +
1462 			    sizeof (struct sf_pkt));
1463 			cmd->cmd_fp_pkt->fcal_pkt_private = (opaque_t)cmd;
1464 			cmd->cmd_state = SF_STATE_IDLE;
1465 			cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
1466 			cmd->cmd_pkt->pkt_scbp = (opaque_t)cmd->cmd_scsi_scb;
1467 			cmd->cmd_pkt->pkt_comp	= NULL;
1468 			cmd->cmd_pkt->pkt_flags	= 0;
1469 			cmd->cmd_pkt->pkt_time	= 0;
1470 			cmd->cmd_pkt->pkt_resid	= 0;
1471 			cmd->cmd_pkt->pkt_reason = 0;
1472 			cmd->cmd_cdblen = (uchar_t)cmdlen;
1473 			cmd->cmd_scblen		= statuslen;
1474 			cmd->cmd_privlen	= tgtlen;
1475 			cmd->cmd_pkt->pkt_address = *ap;
1476 
1477 			/* zero pkt_private */
1478 			(int *)(cmd->cmd_pkt->pkt_private =
1479 			    cmd->cmd_pkt_private);
1480 			bzero((caddr_t)cmd->cmd_pkt->pkt_private,
1481 			    PKT_PRIV_LEN);
1482 		} else {
1483 			failure = TRUE;
1484 		}
1485 
1486 		if (failure ||
1487 		    (tgtlen > PKT_PRIV_LEN) ||
1488 		    (statuslen > EXTCMDS_STATUS_SIZE)) {
1489 			if (!failure) {
1490 				/* need to allocate more space */
1491 				failure = sf_pkt_alloc_extern(sf, cmd,
1492 				    tgtlen, statuslen, kf);
1493 			}
1494 			if (failure) {
1495 				return (NULL);
1496 			}
1497 		}
1498 
1499 		fpkt = cmd->cmd_fp_pkt;
1500 		if (cmd->cmd_block == NULL) {
1501 
1502 			/* allocate cmd/response pool buffers */
1503 			if (sf_cr_alloc(sf, cmd, callback) == DDI_FAILURE) {
1504 				sf_pkt_destroy_extern(sf, cmd);
1505 				return (NULL);
1506 			}
1507 
1508 			/* fill in the FC-AL packet */
1509 			fpkt->fcal_pkt_cookie = sf->sf_socp;
1510 			fpkt->fcal_pkt_comp = sf_cmd_callback;
1511 			fpkt->fcal_pkt_flags = 0;
1512 			fpkt->fcal_magic = FCALP_MAGIC;
1513 			fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
1514 			    (ushort_t)(SOC_FC_HEADER |
1515 			    sf->sf_sochandle->fcal_portno);
1516 			fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
1517 			fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
1518 			fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
1519 			fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
1520 			fpkt->fcal_socal_request.sr_dataseg[0].fc_base =
1521 			    (uint32_t)cmd->cmd_dmac;
1522 			fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
1523 			    sizeof (struct fcp_cmd);
1524 			fpkt->fcal_socal_request.sr_dataseg[1].fc_base =
1525 			    (uint32_t)cmd->cmd_rsp_dmac;
1526 			fpkt->fcal_socal_request.sr_dataseg[1].fc_count =
1527 			    FCP_MAX_RSP_IU_SIZE;
1528 
1529 			/* Fill in the Fabric Channel Header */
1530 			hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
1531 			hp->r_ctl = R_CTL_COMMAND;
1532 			hp->type = TYPE_SCSI_FCP;
1533 			hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
1534 			hp->reserved1 = 0;
1535 			hp->seq_id = 0;
1536 			hp->df_ctl  = 0;
1537 			hp->seq_cnt = 0;
1538 			hp->ox_id = 0xffff;
1539 			hp->rx_id = 0xffff;
1540 			hp->ro = 0;
1541 
1542 			/* Establish the LUN */
1543 			bcopy((caddr_t)&target->sft_lun.b,
1544 			    (caddr_t)&cmd->cmd_block->fcp_ent_addr,
1545 			    FCP_LUN_SIZE);
1546 			*((int32_t *)&cmd->cmd_block->fcp_cntl) = 0;
1547 		}
1548 		cmd->cmd_pkt->pkt_cdbp = cmd->cmd_block->fcp_cdb;
1549 
1550 		mutex_enter(&target->sft_pkt_mutex);
1551 
1552 		target->sft_pkt_tail->cmd_forw = cmd;
1553 		cmd->cmd_back = target->sft_pkt_tail;
1554 		cmd->cmd_forw = (struct sf_pkt *)&target->sft_pkt_head;
1555 		target->sft_pkt_tail = cmd;
1556 
1557 		mutex_exit(&target->sft_pkt_mutex);
1558 		new_cmd = cmd;		/* for later cleanup if needed */
1559 	} else {
1560 		/* pkt already exists -- just a request for DMA allocation */
1561 		cmd = PKT2CMD(pkt);
1562 		fpkt = cmd->cmd_fp_pkt;
1563 	}
1564 
1565 	/* zero cdb (bzero is too slow) */
1566 	bzero((caddr_t)cmd->cmd_pkt->pkt_cdbp, cmdlen);
1567 
1568 	/*
1569 	 * Second step of sf_scsi_init_pkt:  dma allocation
1570 	 * Set up dma info
1571 	 */
1572 	if ((bp != NULL) && (bp->b_bcount != 0)) {
1573 		int cmd_flags, dma_flags;
1574 		int rval = 0;
1575 		uint_t dmacookie_count;
1576 
1577 		/* there is a buffer and some data to transfer */
1578 
1579 		/* set up command and DMA flags */
1580 		cmd_flags = cmd->cmd_flags;
1581 		if (bp->b_flags & B_READ) {
1582 			/* a read */
1583 			cmd_flags &= ~CFLAG_DMASEND;
1584 			dma_flags = DDI_DMA_READ;
1585 		} else {
1586 			/* a write */
1587 			cmd_flags |= CFLAG_DMASEND;
1588 			dma_flags = DDI_DMA_WRITE;
1589 		}
1590 		if (flags & PKT_CONSISTENT) {
1591 			cmd_flags |= CFLAG_CMDIOPB;
1592 			dma_flags |= DDI_DMA_CONSISTENT;
1593 		}
1594 
1595 		/* ensure we have a DMA handle */
1596 		if (cmd->cmd_dmahandle == NULL) {
1597 			rval = ddi_dma_alloc_handle(sf->sf_dip,
1598 			    sf->sf_sochandle->fcal_dmaattr, callback, arg,
1599 			    &cmd->cmd_dmahandle);
1600 		}
1601 
1602 		if (rval == 0) {
1603 			/* bind our DMA handle to our buffer */
1604 			rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
1605 			    dma_flags, callback, arg, &cmd->cmd_dmacookie,
1606 			    &dmacookie_count);
1607 		}
1608 
1609 		if (rval != 0) {
1610 			/* DMA failure */
1611 			SF_DEBUG(2, (sf, CE_CONT, "ddi_dma_buf.. failed\n"));
1612 			switch (rval) {
1613 			case DDI_DMA_NORESOURCES:
1614 				bioerror(bp, 0);
1615 				break;
1616 			case DDI_DMA_BADATTR:
1617 			case DDI_DMA_NOMAPPING:
1618 				bioerror(bp, EFAULT);
1619 				break;
1620 			case DDI_DMA_TOOBIG:
1621 			default:
1622 				bioerror(bp, EINVAL);
1623 				break;
1624 			}
1625 			/* clear valid flag */
1626 			cmd->cmd_flags = cmd_flags & ~CFLAG_DMAVALID;
1627 			if (new_cmd != NULL) {
1628 				/* destroy packet if we just created it */
1629 				sf_scsi_destroy_pkt(ap, new_cmd->cmd_pkt);
1630 			}
1631 			return (NULL);
1632 		}
1633 
1634 		ASSERT(dmacookie_count == 1);
1635 		/* set up amt to transfer and set valid flag */
1636 		cmd->cmd_dmacount = bp->b_bcount;
1637 		cmd->cmd_flags = cmd_flags | CFLAG_DMAVALID;
1638 
1639 		ASSERT(cmd->cmd_dmahandle != NULL);
1640 	}
1641 
1642 	/* set up FC-AL packet */
1643 	fcmd = cmd->cmd_block;
1644 
1645 	if (cmd->cmd_flags & CFLAG_DMAVALID) {
1646 		if (cmd->cmd_flags & CFLAG_DMASEND) {
1647 			/* DMA write */
1648 			fcmd->fcp_cntl.cntl_read_data = 0;
1649 			fcmd->fcp_cntl.cntl_write_data = 1;
1650 			fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
1651 			    CQ_TYPE_IO_WRITE;
1652 		} else {
1653 			/* DMA read */
1654 			fcmd->fcp_cntl.cntl_read_data = 1;
1655 			fcmd->fcp_cntl.cntl_write_data = 0;
1656 			fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
1657 			    CQ_TYPE_IO_READ;
1658 		}
1659 		fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
1660 		    (uint32_t)cmd->cmd_dmacookie.dmac_address;
1661 		fpkt->fcal_socal_request.sr_dataseg[2].fc_count =
1662 		    cmd->cmd_dmacookie.dmac_size;
1663 		fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
1664 		fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
1665 		    cmd->cmd_dmacookie.dmac_size;
1666 		fcmd->fcp_data_len = cmd->cmd_dmacookie.dmac_size;
1667 	} else {
1668 		/* not a read or write */
1669 		fcmd->fcp_cntl.cntl_read_data = 0;
1670 		fcmd->fcp_cntl.cntl_write_data = 0;
1671 		fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
1672 		fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
1673 		fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
1674 		    sizeof (struct fcp_cmd);
1675 		fcmd->fcp_data_len = 0;
1676 	}
1677 	fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
1678 
1679 	return (cmd->cmd_pkt);
1680 }
1681 
1682 
1683 /*
1684  * destroy a SCSI packet -- called internally and by the transport
1685  */
1686 static void
sf_scsi_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)1687 sf_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1688 {
1689 	struct sf_pkt *cmd = PKT2CMD(pkt);
1690 	struct sf *sf = ADDR2SF(ap);
1691 	struct sf_target *target = ADDR2TARGET(ap);
1692 	struct fcal_packet	*fpkt = cmd->cmd_fp_pkt;
1693 
1694 
1695 	if (cmd->cmd_flags & CFLAG_DMAVALID) {
1696 		/* DMA was set up -- clean up */
1697 		(void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
1698 		cmd->cmd_flags ^= CFLAG_DMAVALID;
1699 	}
1700 
1701 	/* take this packet off the doubly-linked list */
1702 	mutex_enter(&target->sft_pkt_mutex);
1703 	cmd->cmd_back->cmd_forw = cmd->cmd_forw;
1704 	cmd->cmd_forw->cmd_back = cmd->cmd_back;
1705 	mutex_exit(&target->sft_pkt_mutex);
1706 
1707 	fpkt->fcal_pkt_flags = 0;
1708 	/* free the packet */
1709 	if ((cmd->cmd_flags &
1710 	    (CFLAG_FREE | CFLAG_PRIVEXTERN | CFLAG_SCBEXTERN)) == 0) {
1711 		/* just a regular packet */
1712 		ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
1713 		cmd->cmd_flags = CFLAG_FREE;
1714 		kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
1715 	} else {
1716 		/* a packet with extra memory */
1717 		sf_pkt_destroy_extern(sf, cmd);
1718 	}
1719 }
1720 
1721 
1722 /*
1723  * called by transport to unbind DMA handle
1724  */
1725 /* ARGSUSED */
1726 static void
sf_scsi_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)1727 sf_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1728 {
1729 	struct sf_pkt *cmd = PKT2CMD(pkt);
1730 
1731 
1732 	if (cmd->cmd_flags & CFLAG_DMAVALID) {
1733 		(void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
1734 		cmd->cmd_flags ^= CFLAG_DMAVALID;
1735 	}
1736 
1737 }
1738 
1739 
1740 /*
1741  * called by transport to synchronize CPU and I/O views of memory
1742  */
1743 /* ARGSUSED */
1744 static void
sf_scsi_sync_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)1745 sf_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1746 {
1747 	struct sf_pkt *cmd = PKT2CMD(pkt);
1748 
1749 
1750 	if (cmd->cmd_flags & CFLAG_DMAVALID) {
1751 		if (ddi_dma_sync(cmd->cmd_dmahandle, (off_t)0, (size_t)0,
1752 		    (cmd->cmd_flags & CFLAG_DMASEND) ?
1753 		    DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU) !=
1754 		    DDI_SUCCESS) {
1755 			cmn_err(CE_WARN, "sf: sync pkt failed");
1756 		}
1757 	}
1758 }
1759 
1760 
1761 /*
1762  * routine for reset notification setup, to register or cancel. -- called
1763  * by transport
1764  */
1765 static int
sf_scsi_reset_notify(struct scsi_address * ap,int flag,void (* callback)(caddr_t),caddr_t arg)1766 sf_scsi_reset_notify(struct scsi_address *ap, int flag,
1767     void (*callback)(caddr_t), caddr_t arg)
1768 {
1769 	struct sf	*sf = ADDR2SF(ap);
1770 
1771 	return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
1772 	    &sf->sf_mutex, &sf->sf_reset_notify_listf));
1773 }
1774 
1775 
1776 /*
1777  * called by transport to get port WWN property (except sun4u)
1778  */
1779 /* ARGSUSED */
1780 static int
sf_scsi_get_name(struct scsi_device * sd,char * name,int len)1781 sf_scsi_get_name(struct scsi_device *sd, char *name, int len)
1782 {
1783 	char tbuf[(FC_WWN_SIZE*2)+1];
1784 	unsigned char wwn[FC_WWN_SIZE];
1785 	int i, lun;
1786 	dev_info_t *tgt_dip;
1787 
1788 	tgt_dip = sd->sd_dev;
1789 	i = sizeof (wwn);
1790 	if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1791 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
1792 	    (caddr_t)&wwn, &i) != DDI_SUCCESS) {
1793 		name[0] = '\0';
1794 		return (0);
1795 	}
1796 	i = sizeof (lun);
1797 	if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1798 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
1799 	    (caddr_t)&lun, &i) != DDI_SUCCESS) {
1800 		name[0] = '\0';
1801 		return (0);
1802 	}
1803 	for (i = 0; i < FC_WWN_SIZE; i++)
1804 		(void) sprintf(&tbuf[i << 1], "%02x", wwn[i]);
1805 	(void) sprintf(name, "w%s,%x", tbuf, lun);
1806 	return (1);
1807 }
1808 
1809 
1810 /*
1811  * called by transport to get target soft AL-PA (except sun4u)
1812  */
1813 /* ARGSUSED */
1814 static int
sf_scsi_get_bus_addr(struct scsi_device * sd,char * name,int len)1815 sf_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
1816 {
1817 	struct sf_target *target = ADDR2TARGET(&sd->sd_address);
1818 
1819 	if (target == NULL)
1820 		return (0);
1821 
1822 	(void) sprintf(name, "%x", target->sft_al_pa);
1823 	return (1);
1824 }
1825 
1826 
1827 /*
1828  * add to the command/response buffer pool for this sf instance
1829  */
1830 static int
sf_add_cr_pool(struct sf * sf)1831 sf_add_cr_pool(struct sf *sf)
1832 {
1833 	int		cmd_buf_size;
1834 	size_t		real_cmd_buf_size;
1835 	int		rsp_buf_size;
1836 	size_t		real_rsp_buf_size;
1837 	uint_t		i, ccount;
1838 	struct sf_cr_pool	*ptr;
1839 	struct sf_cr_free_elem *cptr;
1840 	caddr_t	dptr, eptr;
1841 	ddi_dma_cookie_t	cmd_cookie;
1842 	ddi_dma_cookie_t	rsp_cookie;
1843 	int		cmd_bound = FALSE, rsp_bound = FALSE;
1844 
1845 
1846 	/* allocate room for the pool */
1847 	if ((ptr = kmem_zalloc(sizeof (struct sf_cr_pool), KM_NOSLEEP)) ==
1848 	    NULL) {
1849 		return (DDI_FAILURE);
1850 	}
1851 
1852 	/* allocate a DMA handle for the command pool */
1853 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
1854 	    DDI_DMA_DONTWAIT, NULL, &ptr->cmd_dma_handle) != DDI_SUCCESS) {
1855 		goto fail;
1856 	}
1857 
1858 	/*
1859 	 * Get a piece of memory in which to put commands
1860 	 */
1861 	cmd_buf_size = (sizeof (struct fcp_cmd) * SF_ELEMS_IN_POOL + 7) & ~7;
1862 	if (ddi_dma_mem_alloc(ptr->cmd_dma_handle, cmd_buf_size,
1863 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
1864 	    DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->cmd_base,
1865 	    &real_cmd_buf_size, &ptr->cmd_acc_handle) != DDI_SUCCESS) {
1866 		goto fail;
1867 	}
1868 
1869 	/* bind the DMA handle to an address */
1870 	if (ddi_dma_addr_bind_handle(ptr->cmd_dma_handle, NULL,
1871 	    ptr->cmd_base, real_cmd_buf_size,
1872 	    DDI_DMA_WRITE | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
1873 	    NULL, &cmd_cookie, &ccount) != DDI_DMA_MAPPED) {
1874 		goto fail;
1875 	}
1876 	cmd_bound = TRUE;
1877 	/* ensure only one cookie was allocated */
1878 	if (ccount != 1) {
1879 		goto fail;
1880 	}
1881 
1882 	/* allocate a DMA handle for the response pool */
1883 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
1884 	    DDI_DMA_DONTWAIT, NULL, &ptr->rsp_dma_handle) != DDI_SUCCESS) {
1885 		goto fail;
1886 	}
1887 
1888 	/*
1889 	 * Get a piece of memory in which to put responses
1890 	 */
1891 	rsp_buf_size = FCP_MAX_RSP_IU_SIZE * SF_ELEMS_IN_POOL;
1892 	if (ddi_dma_mem_alloc(ptr->rsp_dma_handle, rsp_buf_size,
1893 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
1894 	    DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->rsp_base,
1895 	    &real_rsp_buf_size, &ptr->rsp_acc_handle) != DDI_SUCCESS) {
1896 		goto fail;
1897 	}
1898 
1899 	/* bind the DMA handle to an address */
1900 	if (ddi_dma_addr_bind_handle(ptr->rsp_dma_handle, NULL,
1901 	    ptr->rsp_base, real_rsp_buf_size,
1902 	    DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
1903 	    NULL, &rsp_cookie, &ccount) != DDI_DMA_MAPPED) {
1904 		goto fail;
1905 	}
1906 	rsp_bound = TRUE;
1907 	/* ensure only one cookie was allocated */
1908 	if (ccount != 1) {
1909 		goto fail;
1910 	}
1911 
1912 	/*
1913 	 * Generate a (cmd/rsp structure) free list
1914 	 */
1915 	/* ensure ptr points to start of long word (8-byte block) */
1916 	dptr = (caddr_t)((uintptr_t)(ptr->cmd_base) + 7 & ~7);
1917 	/* keep track of actual size after moving pointer */
1918 	real_cmd_buf_size -= (dptr - ptr->cmd_base);
1919 	eptr = ptr->rsp_base;
1920 
1921 	/* set actual total number of entries */
1922 	ptr->ntot = min((real_cmd_buf_size / sizeof (struct fcp_cmd)),
1923 	    (real_rsp_buf_size / FCP_MAX_RSP_IU_SIZE));
1924 	ptr->nfree = ptr->ntot;
1925 	ptr->free = (struct sf_cr_free_elem *)ptr->cmd_base;
1926 	ptr->sf = sf;
1927 
1928 	/* set up DMA for each pair of entries */
1929 	i = 0;
1930 	while (i < ptr->ntot) {
1931 		cptr = (struct sf_cr_free_elem *)dptr;
1932 		dptr += sizeof (struct fcp_cmd);
1933 
1934 		cptr->next = (struct sf_cr_free_elem *)dptr;
1935 		cptr->rsp = eptr;
1936 
1937 		cptr->cmd_dmac = cmd_cookie.dmac_address +
1938 		    (uint32_t)((caddr_t)cptr - ptr->cmd_base);
1939 
1940 		cptr->rsp_dmac = rsp_cookie.dmac_address +
1941 		    (uint32_t)((caddr_t)eptr - ptr->rsp_base);
1942 
1943 		eptr += FCP_MAX_RSP_IU_SIZE;
1944 		i++;
1945 	}
1946 
1947 	/* terminate the list */
1948 	cptr->next = NULL;
1949 
1950 	/* add this list at front of current one */
1951 	mutex_enter(&sf->sf_cr_mutex);
1952 	ptr->next = sf->sf_cr_pool;
1953 	sf->sf_cr_pool = ptr;
1954 	sf->sf_cr_pool_cnt++;
1955 	mutex_exit(&sf->sf_cr_mutex);
1956 
1957 	return (DDI_SUCCESS);
1958 
1959 fail:
1960 	/* we failed so clean up */
1961 	if (ptr->cmd_dma_handle != NULL) {
1962 		if (cmd_bound) {
1963 			(void) ddi_dma_unbind_handle(ptr->cmd_dma_handle);
1964 		}
1965 		ddi_dma_free_handle(&ptr->cmd_dma_handle);
1966 	}
1967 
1968 	if (ptr->rsp_dma_handle != NULL) {
1969 		if (rsp_bound) {
1970 			(void) ddi_dma_unbind_handle(ptr->rsp_dma_handle);
1971 		}
1972 		ddi_dma_free_handle(&ptr->rsp_dma_handle);
1973 	}
1974 
1975 	if (ptr->cmd_base != NULL) {
1976 		ddi_dma_mem_free(&ptr->cmd_acc_handle);
1977 	}
1978 
1979 	if (ptr->rsp_base != NULL) {
1980 		ddi_dma_mem_free(&ptr->rsp_acc_handle);
1981 	}
1982 
1983 	kmem_free((caddr_t)ptr, sizeof (struct sf_cr_pool));
1984 	return (DDI_FAILURE);
1985 }
1986 
1987 
1988 /*
1989  * allocate a command/response buffer from the pool, allocating more
1990  * in the pool as needed
1991  */
1992 static int
sf_cr_alloc(struct sf * sf,struct sf_pkt * cmd,int (* func)())1993 sf_cr_alloc(struct sf *sf, struct sf_pkt *cmd, int (*func)())
1994 {
1995 	struct sf_cr_pool *ptr;
1996 	struct sf_cr_free_elem *cptr;
1997 
1998 
1999 	mutex_enter(&sf->sf_cr_mutex);
2000 
2001 try_again:
2002 
2003 	/* find a free buffer in the existing pool */
2004 	ptr = sf->sf_cr_pool;
2005 	while (ptr != NULL) {
2006 		if (ptr->nfree != 0) {
2007 			ptr->nfree--;
2008 			break;
2009 		} else {
2010 			ptr = ptr->next;
2011 		}
2012 	}
2013 
2014 	/* did we find a free buffer ? */
2015 	if (ptr != NULL) {
2016 		/* we found a free buffer -- take it off the free list */
2017 		cptr = ptr->free;
2018 		ptr->free = cptr->next;
2019 		mutex_exit(&sf->sf_cr_mutex);
2020 		/* set up the command to use the buffer pair */
2021 		cmd->cmd_block = (struct fcp_cmd *)cptr;
2022 		cmd->cmd_dmac = cptr->cmd_dmac;
2023 		cmd->cmd_rsp_dmac = cptr->rsp_dmac;
2024 		cmd->cmd_rsp_block = (struct fcp_rsp *)cptr->rsp;
2025 		cmd->cmd_cr_pool = ptr;
2026 		return (DDI_SUCCESS);		/* success */
2027 	}
2028 
2029 	/* no free buffer available -- can we allocate more ? */
2030 	if (sf->sf_cr_pool_cnt < SF_CR_POOL_MAX) {
2031 		/* we need to allocate more buffer pairs */
2032 		if (sf->sf_cr_flag) {
2033 			/* somebody already allocating for this instance */
2034 			if (func == SLEEP_FUNC) {
2035 				/* user wants to wait */
2036 				cv_wait(&sf->sf_cr_cv, &sf->sf_cr_mutex);
2037 				/* we've been woken so go try again */
2038 				goto try_again;
2039 			}
2040 			/* user does not want to wait */
2041 			mutex_exit(&sf->sf_cr_mutex);
2042 			sf->sf_stats.cralloc_failures++;
2043 			return (DDI_FAILURE);	/* give up */
2044 		}
2045 		/* set flag saying we're allocating */
2046 		sf->sf_cr_flag = 1;
2047 		mutex_exit(&sf->sf_cr_mutex);
2048 		/* add to our pool */
2049 		if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
2050 			/* couldn't add to our pool for some reason */
2051 			mutex_enter(&sf->sf_cr_mutex);
2052 			sf->sf_cr_flag = 0;
2053 			cv_broadcast(&sf->sf_cr_cv);
2054 			mutex_exit(&sf->sf_cr_mutex);
2055 			sf->sf_stats.cralloc_failures++;
2056 			return (DDI_FAILURE);	/* give up */
2057 		}
2058 		/*
2059 		 * clear flag saying we're allocating and tell all other
2060 		 * that care
2061 		 */
2062 		mutex_enter(&sf->sf_cr_mutex);
2063 		sf->sf_cr_flag = 0;
2064 		cv_broadcast(&sf->sf_cr_cv);
2065 		/* now that we have more buffers try again */
2066 		goto try_again;
2067 	}
2068 
2069 	/* we don't have room to allocate any more buffers */
2070 	mutex_exit(&sf->sf_cr_mutex);
2071 	sf->sf_stats.cralloc_failures++;
2072 	return (DDI_FAILURE);			/* give up */
2073 }
2074 
2075 
2076 /*
2077  * free a cmd/response buffer pair in our pool
2078  */
2079 static void
sf_cr_free(struct sf_cr_pool * cp,struct sf_pkt * cmd)2080 sf_cr_free(struct sf_cr_pool *cp, struct sf_pkt *cmd)
2081 {
2082 	struct sf *sf = cp->sf;
2083 	struct sf_cr_free_elem *elem;
2084 
2085 	elem = (struct sf_cr_free_elem *)cmd->cmd_block;
2086 	elem->rsp = (caddr_t)cmd->cmd_rsp_block;
2087 	elem->cmd_dmac = cmd->cmd_dmac;
2088 	elem->rsp_dmac = cmd->cmd_rsp_dmac;
2089 
2090 	mutex_enter(&sf->sf_cr_mutex);
2091 	cp->nfree++;
2092 	ASSERT(cp->nfree <= cp->ntot);
2093 
2094 	elem->next = cp->free;
2095 	cp->free = elem;
2096 	mutex_exit(&sf->sf_cr_mutex);
2097 }
2098 
2099 
2100 /*
2101  * free our pool of cmd/response buffers
2102  */
2103 static void
sf_crpool_free(struct sf * sf)2104 sf_crpool_free(struct sf *sf)
2105 {
2106 	struct sf_cr_pool *cp, *prev;
2107 
2108 	prev = NULL;
2109 	mutex_enter(&sf->sf_cr_mutex);
2110 	cp = sf->sf_cr_pool;
2111 	while (cp != NULL) {
2112 		if (cp->nfree == cp->ntot) {
2113 			if (prev != NULL) {
2114 				prev->next = cp->next;
2115 			} else {
2116 				sf->sf_cr_pool = cp->next;
2117 			}
2118 			sf->sf_cr_pool_cnt--;
2119 			mutex_exit(&sf->sf_cr_mutex);
2120 
2121 			(void) ddi_dma_unbind_handle(cp->cmd_dma_handle);
2122 			ddi_dma_free_handle(&cp->cmd_dma_handle);
2123 			(void) ddi_dma_unbind_handle(cp->rsp_dma_handle);
2124 			ddi_dma_free_handle(&cp->rsp_dma_handle);
2125 			ddi_dma_mem_free(&cp->cmd_acc_handle);
2126 			ddi_dma_mem_free(&cp->rsp_acc_handle);
2127 			kmem_free((caddr_t)cp, sizeof (struct sf_cr_pool));
2128 			return;
2129 		}
2130 		prev = cp;
2131 		cp = cp->next;
2132 	}
2133 	mutex_exit(&sf->sf_cr_mutex);
2134 }
2135 
2136 
2137 /* ARGSUSED */
2138 static int
sf_kmem_cache_constructor(void * buf,void * arg,int size)2139 sf_kmem_cache_constructor(void *buf, void *arg, int size)
2140 {
2141 	struct sf_pkt *cmd = buf;
2142 
2143 	mutex_init(&cmd->cmd_abort_mutex, NULL, MUTEX_DRIVER, NULL);
2144 	cmd->cmd_block = NULL;
2145 	cmd->cmd_dmahandle = NULL;
2146 	return (0);
2147 }
2148 
2149 
2150 /* ARGSUSED */
2151 static void
sf_kmem_cache_destructor(void * buf,void * size)2152 sf_kmem_cache_destructor(void *buf, void *size)
2153 {
2154 	struct sf_pkt *cmd = buf;
2155 
2156 	if (cmd->cmd_dmahandle != NULL) {
2157 		ddi_dma_free_handle(&cmd->cmd_dmahandle);
2158 	}
2159 
2160 	if (cmd->cmd_block != NULL) {
2161 		sf_cr_free(cmd->cmd_cr_pool, cmd);
2162 	}
2163 	mutex_destroy(&cmd->cmd_abort_mutex);
2164 }
2165 
2166 
2167 /*
2168  * called by transport when a state change occurs
2169  */
2170 static void
sf_statec_callback(void * arg,int msg)2171 sf_statec_callback(void *arg, int msg)
2172 {
2173 	struct sf *sf = (struct sf *)arg;
2174 	struct sf_target	*target;
2175 	int i;
2176 	struct sf_pkt *cmd;
2177 	struct scsi_pkt *pkt;
2178 
2179 
2180 
2181 	switch (msg) {
2182 
2183 	case FCAL_STATUS_LOOP_ONLINE: {
2184 		uchar_t		al_pa;		/* to save AL-PA */
2185 		int		ret;		/* ret value from getmap */
2186 		int		lip_cnt;	/* to save current count */
2187 		int		cnt;		/* map length */
2188 
2189 		/*
2190 		 * the loop has gone online
2191 		 */
2192 		SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop online\n",
2193 		    ddi_get_instance(sf->sf_dip)));
2194 		mutex_enter(&sf->sf_mutex);
2195 		sf->sf_lip_cnt++;
2196 		sf->sf_state = SF_STATE_ONLINING;
2197 		mutex_exit(&sf->sf_mutex);
2198 
2199 		/* scan each target hash queue */
2200 		for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
2201 			target = sf->sf_wwn_lists[i];
2202 			while (target != NULL) {
2203 				/*
2204 				 * foreach target, if it's not offline then
2205 				 * mark it as busy
2206 				 */
2207 				mutex_enter(&target->sft_mutex);
2208 				if (!(target->sft_state & SF_TARGET_OFFLINE))
2209 					target->sft_state |= (SF_TARGET_BUSY
2210 					    | SF_TARGET_MARK);
2211 #ifdef DEBUG
2212 				/*
2213 				 * for debugging, print out info on any
2214 				 * pending commands (left hanging)
2215 				 */
2216 				cmd = target->sft_pkt_head;
2217 				while (cmd != (struct sf_pkt *)&target->
2218 				    sft_pkt_head) {
2219 					if (cmd->cmd_state ==
2220 					    SF_STATE_ISSUED) {
2221 						SF_DEBUG(1, (sf, CE_CONT,
2222 						    "cmd 0x%p pending "
2223 						    "after lip\n",
2224 						    (void *)cmd->cmd_fp_pkt));
2225 					}
2226 					cmd = cmd->cmd_forw;
2227 				}
2228 #endif
2229 				mutex_exit(&target->sft_mutex);
2230 				target = target->sft_next;
2231 			}
2232 		}
2233 
2234 		/*
2235 		 * since the loop has just gone online get a new map from
2236 		 * the transport
2237 		 */
2238 		if ((ret = soc_get_lilp_map(sf->sf_sochandle, sf->sf_socp,
2239 		    sf->sf_sochandle->fcal_portno, (uint32_t)sf->
2240 		    sf_lilp_dmacookie.dmac_address, 1)) != FCAL_SUCCESS) {
2241 			if (sf_core && (sf_core & SF_CORE_LILP_FAILED)) {
2242 				(void) soc_take_core(sf->sf_sochandle,
2243 				    sf->sf_socp);
2244 				sf_core = 0;
2245 			}
2246 			sf_log(sf, CE_WARN,
2247 			    "!soc lilp map failed status=0x%x\n", ret);
2248 			mutex_enter(&sf->sf_mutex);
2249 			sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
2250 			sf->sf_lip_cnt++;
2251 			sf->sf_state = SF_STATE_OFFLINE;
2252 			mutex_exit(&sf->sf_mutex);
2253 			return;
2254 		}
2255 
2256 		/* ensure consistent view of DMA memory */
2257 		(void) ddi_dma_sync(sf->sf_lilp_dmahandle, (off_t)0, (size_t)0,
2258 		    DDI_DMA_SYNC_FORKERNEL);
2259 
2260 		/* how many entries in map ? */
2261 		cnt = sf->sf_lilp_map->lilp_length;
2262 		if (cnt >= SF_MAX_LILP_ENTRIES) {
2263 			sf_log(sf, CE_WARN, "invalid lilp map\n");
2264 			return;
2265 		}
2266 
2267 		mutex_enter(&sf->sf_mutex);
2268 		sf->sf_device_count = cnt - 1;
2269 		sf->sf_al_pa = sf->sf_lilp_map->lilp_myalpa;
2270 		lip_cnt = sf->sf_lip_cnt;
2271 		al_pa = sf->sf_al_pa;
2272 
2273 		SF_DEBUG(1, (sf, CE_CONT,
2274 		    "!lilp map has %d entries, al_pa is %x\n", cnt, al_pa));
2275 
2276 		/*
2277 		 * since the last entry of the map may be mine (common) check
2278 		 * for that, and if it is we have one less entry to look at
2279 		 */
2280 		if (sf->sf_lilp_map->lilp_alpalist[cnt-1] == al_pa) {
2281 			cnt--;
2282 		}
2283 		/* If we didn't get a valid loop map enable all targets */
2284 		if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
2285 			for (i = 0; i < sizeof (sf_switch_to_alpa); i++)
2286 				sf->sf_lilp_map->lilp_alpalist[i] =
2287 				    sf_switch_to_alpa[i];
2288 			cnt = i;
2289 			sf->sf_device_count = cnt - 1;
2290 		}
2291 		if (sf->sf_device_count == 0) {
2292 			sf_finish_init(sf, lip_cnt);
2293 			mutex_exit(&sf->sf_mutex);
2294 			break;
2295 		}
2296 		mutex_exit(&sf->sf_mutex);
2297 
2298 		SF_DEBUG(2, (sf, CE_WARN,
2299 		    "!statec_callback: starting with %d targets\n",
2300 		    sf->sf_device_count));
2301 
2302 		/* scan loop map, logging into all ports (except mine) */
2303 		for (i = 0; i < cnt; i++) {
2304 			SF_DEBUG(1, (sf, CE_CONT,
2305 			    "!lilp map entry %d = %x,%x\n", i,
2306 			    sf->sf_lilp_map->lilp_alpalist[i],
2307 			    sf_alpa_to_switch[
2308 			    sf->sf_lilp_map->lilp_alpalist[i]]));
2309 			/* is this entry for somebody else ? */
2310 			if (sf->sf_lilp_map->lilp_alpalist[i] != al_pa) {
2311 				/* do a PLOGI to this port */
2312 				if (!sf_login(sf, LA_ELS_PLOGI,
2313 				    sf->sf_lilp_map->lilp_alpalist[i],
2314 				    sf->sf_lilp_map->lilp_alpalist[cnt-1],
2315 				    lip_cnt)) {
2316 					/* a problem logging in */
2317 					mutex_enter(&sf->sf_mutex);
2318 					if (lip_cnt == sf->sf_lip_cnt) {
2319 						/*
2320 						 * problem not from a new LIP
2321 						 */
2322 						sf->sf_device_count--;
2323 						ASSERT(sf->sf_device_count
2324 						    >= 0);
2325 						if (sf->sf_device_count == 0) {
2326 							sf_finish_init(sf,
2327 							    lip_cnt);
2328 						}
2329 					}
2330 					mutex_exit(&sf->sf_mutex);
2331 				}
2332 			}
2333 		}
2334 		break;
2335 	}
2336 
2337 	case FCAL_STATUS_ERR_OFFLINE:
2338 		/*
2339 		 * loop has gone offline due to an error
2340 		 */
2341 		SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop offline\n",
2342 		    ddi_get_instance(sf->sf_dip)));
2343 		mutex_enter(&sf->sf_mutex);
2344 		sf->sf_lip_cnt++;
2345 		sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
2346 		if (!sf->sf_online_timer) {
2347 			sf->sf_online_timer = sf_watchdog_time +
2348 			    SF_ONLINE_TIMEOUT;
2349 		}
2350 		/*
2351 		 * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
2352 		 * since throttling logic in sf_watch() depends on
2353 		 * preservation of this flag while device is suspended
2354 		 */
2355 		if (sf->sf_state & SF_STATE_SUSPENDED) {
2356 			sf->sf_state |= SF_STATE_OFFLINE;
2357 			SF_DEBUG(1, (sf, CE_CONT,
2358 			    "sf_statec_callback, sf%d: "
2359 			    "got FCAL_STATE_OFFLINE during DDI_SUSPEND\n",
2360 			    ddi_get_instance(sf->sf_dip)));
2361 		} else {
2362 			sf->sf_state = SF_STATE_OFFLINE;
2363 		}
2364 
2365 		/* scan each possible target on the loop */
2366 		for (i = 0; i < sf_max_targets; i++) {
2367 			target = sf->sf_targets[i];
2368 			while (target != NULL) {
2369 				mutex_enter(&target->sft_mutex);
2370 				if (!(target->sft_state & SF_TARGET_OFFLINE))
2371 					target->sft_state |= (SF_TARGET_BUSY
2372 					    | SF_TARGET_MARK);
2373 				mutex_exit(&target->sft_mutex);
2374 				target = target->sft_next_lun;
2375 			}
2376 		}
2377 		mutex_exit(&sf->sf_mutex);
2378 		break;
2379 
2380 	case FCAL_STATE_RESET: {
2381 		struct sf_els_hdr	*privp;	/* ptr to private list */
2382 		struct sf_els_hdr	*tmpp1;	/* tmp prev hdr ptr */
2383 		struct sf_els_hdr	*tmpp2;	/* tmp next hdr ptr */
2384 		struct sf_els_hdr	*head;	/* to save our private list */
2385 		struct fcal_packet	*fpkt;	/* ptr to pkt in hdr */
2386 
2387 		/*
2388 		 * a transport reset
2389 		 */
2390 		SF_DEBUG(1, (sf, CE_CONT, "!sf%d: soc reset\n",
2391 		    ddi_get_instance(sf->sf_dip)));
2392 		tmpp1 = head = NULL;
2393 		mutex_enter(&sf->sf_mutex);
2394 		sf->sf_lip_cnt++;
2395 		sf->sf_timer = sf_watchdog_time + SF_RESET_TIMEOUT;
2396 		/*
2397 		 * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
2398 		 * since throttling logic in sf_watch() depends on
2399 		 * preservation of this flag while device is suspended
2400 		 */
2401 		if (sf->sf_state & SF_STATE_SUSPENDED) {
2402 			sf->sf_state |= SF_STATE_OFFLINE;
2403 			SF_DEBUG(1, (sf, CE_CONT,
2404 			    "sf_statec_callback, sf%d: "
2405 			    "got FCAL_STATE_RESET during DDI_SUSPEND\n",
2406 			    ddi_get_instance(sf->sf_dip)));
2407 		} else {
2408 			sf->sf_state = SF_STATE_OFFLINE;
2409 		}
2410 
2411 		/*
2412 		 * scan each possible target on the loop, looking for targets
2413 		 * that need callbacks ran
2414 		 */
2415 		for (i = 0; i < sf_max_targets; i++) {
2416 			target = sf->sf_targets[i];
2417 			while (target != NULL) {
2418 				if (!(target->sft_state & SF_TARGET_OFFLINE)) {
2419 					target->sft_state |= (SF_TARGET_BUSY
2420 					    | SF_TARGET_MARK);
2421 					mutex_exit(&sf->sf_mutex);
2422 					/*
2423 					 * run remove event callbacks for lun
2424 					 *
2425 					 * We have a nasty race condition here
2426 					 * 'cause we're dropping this mutex to
2427 					 * run the callback and expect the
2428 					 * linked list to be the same.
2429 					 */
2430 					(void) ndi_event_retrieve_cookie(
2431 					    sf->sf_event_hdl, target->sft_dip,
2432 					    FCAL_REMOVE_EVENT, &sf_remove_eid,
2433 					    NDI_EVENT_NOPASS);
2434 					(void) ndi_event_run_callbacks(
2435 					    sf->sf_event_hdl,
2436 					    target->sft_dip,
2437 					    sf_remove_eid, NULL);
2438 					mutex_enter(&sf->sf_mutex);
2439 				}
2440 				target = target->sft_next_lun;
2441 			}
2442 		}
2443 
2444 		/*
2445 		 * scan for ELS commands that are in transport, not complete,
2446 		 * and have a valid timeout, building a private list
2447 		 */
2448 		privp = sf->sf_els_list;
2449 		while (privp != NULL) {
2450 			fpkt = privp->fpkt;
2451 			if ((fpkt->fcal_cmd_state & FCAL_CMD_IN_TRANSPORT) &&
2452 			    (!(fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE)) &&
2453 			    (privp->timeout != SF_INVALID_TIMEOUT)) {
2454 				/*
2455 				 * cmd in transport && not complete &&
2456 				 * timeout valid
2457 				 *
2458 				 * move this entry from ELS input list to our
2459 				 * private list
2460 				 */
2461 
2462 				tmpp2 = privp->next; /* save ptr to next */
2463 
2464 				/* push this on private list head */
2465 				privp->next = head;
2466 				head = privp;
2467 
2468 				/* remove this entry from input list */
2469 				if (tmpp1 != NULL) {
2470 					/*
2471 					 * remove this entry from somewhere in
2472 					 * the middle of the list
2473 					 */
2474 					tmpp1->next = tmpp2;
2475 					if (tmpp2 != NULL) {
2476 						tmpp2->prev = tmpp1;
2477 					}
2478 				} else {
2479 					/*
2480 					 * remove this entry from the head
2481 					 * of the list
2482 					 */
2483 					sf->sf_els_list = tmpp2;
2484 					if (tmpp2 != NULL) {
2485 						tmpp2->prev = NULL;
2486 					}
2487 				}
2488 				privp = tmpp2;	/* skip to next entry */
2489 			} else {
2490 				tmpp1 = privp;	/* save ptr to prev entry */
2491 				privp = privp->next; /* skip to next entry */
2492 			}
2493 		}
2494 
2495 		mutex_exit(&sf->sf_mutex);
2496 
2497 		/*
2498 		 * foreach cmd in our list free the ELS packet associated
2499 		 * with it
2500 		 */
2501 		privp = head;
2502 		while (privp != NULL) {
2503 			fpkt = privp->fpkt;
2504 			privp = privp->next;
2505 			sf_els_free(fpkt);
2506 		}
2507 
2508 		/*
2509 		 * scan for commands from each possible target
2510 		 */
2511 		for (i = 0; i < sf_max_targets; i++) {
2512 			target = sf->sf_targets[i];
2513 			while (target != NULL) {
2514 				/*
2515 				 * scan all active commands for this target,
2516 				 * looking for commands that have been issued,
2517 				 * are in transport, and are not yet complete
2518 				 * (so we can terminate them because of the
2519 				 * reset)
2520 				 */
2521 				mutex_enter(&target->sft_pkt_mutex);
2522 				cmd = target->sft_pkt_head;
2523 				while (cmd != (struct sf_pkt *)&target->
2524 				    sft_pkt_head) {
2525 					fpkt = cmd->cmd_fp_pkt;
2526 					mutex_enter(&cmd->cmd_abort_mutex);
2527 					if ((cmd->cmd_state ==
2528 					    SF_STATE_ISSUED) &&
2529 					    (fpkt->fcal_cmd_state &
2530 					    FCAL_CMD_IN_TRANSPORT) &&
2531 					    (!(fpkt->fcal_cmd_state &
2532 					    FCAL_CMD_COMPLETE))) {
2533 						/* a command to be reset */
2534 						pkt = cmd->cmd_pkt;
2535 						pkt->pkt_reason = CMD_RESET;
2536 						pkt->pkt_statistics |=
2537 						    STAT_BUS_RESET;
2538 						cmd->cmd_state = SF_STATE_IDLE;
2539 						mutex_exit(&cmd->
2540 						    cmd_abort_mutex);
2541 						mutex_exit(&target->
2542 						    sft_pkt_mutex);
2543 						if (pkt->pkt_comp != NULL) {
2544 							(*pkt->pkt_comp)(pkt);
2545 						}
2546 						mutex_enter(&target->
2547 						    sft_pkt_mutex);
2548 						cmd = target->sft_pkt_head;
2549 					} else {
2550 						mutex_exit(&cmd->
2551 						    cmd_abort_mutex);
2552 						/* get next command */
2553 						cmd = cmd->cmd_forw;
2554 					}
2555 				}
2556 				mutex_exit(&target->sft_pkt_mutex);
2557 				target = target->sft_next_lun;
2558 			}
2559 		}
2560 
2561 		/*
2562 		 * get packet queue for this target, resetting all remaining
2563 		 * commands
2564 		 */
2565 		mutex_enter(&sf->sf_mutex);
2566 		cmd = sf->sf_pkt_head;
2567 		sf->sf_pkt_head = NULL;
2568 		mutex_exit(&sf->sf_mutex);
2569 
2570 		while (cmd != NULL) {
2571 			pkt = cmd->cmd_pkt;
2572 			cmd = cmd->cmd_next;
2573 			pkt->pkt_reason = CMD_RESET;
2574 			pkt->pkt_statistics |= STAT_BUS_RESET;
2575 			if (pkt->pkt_comp != NULL) {
2576 				(*pkt->pkt_comp)(pkt);
2577 			}
2578 		}
2579 		break;
2580 	}
2581 
2582 	default:
2583 		break;
2584 	}
2585 }
2586 
2587 
2588 /*
2589  * called to send a PLOGI (N_port login) ELS request to a destination ID,
2590  * returning TRUE upon success, else returning FALSE
2591  */
2592 static int
sf_login(struct sf * sf,uchar_t els_code,uchar_t dest_id,uint_t arg1,int lip_cnt)2593 sf_login(struct sf *sf, uchar_t els_code, uchar_t dest_id, uint_t arg1,
2594     int lip_cnt)
2595 {
2596 	struct la_els_logi	*logi;
2597 	struct	sf_els_hdr	*privp;
2598 
2599 
2600 	if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
2601 	    sizeof (union sf_els_cmd), sizeof (union sf_els_rsp),
2602 	    (caddr_t *)&privp, (caddr_t *)&logi) == NULL) {
2603 		sf_log(sf, CE_WARN, "Cannot allocate PLOGI for target %x "
2604 		    "due to DVMA shortage.\n", sf_alpa_to_switch[dest_id]);
2605 		return (FALSE);
2606 	}
2607 
2608 	privp->lip_cnt = lip_cnt;
2609 	if (els_code == LA_ELS_PLOGI) {
2610 		bcopy((caddr_t)sf->sf_sochandle->fcal_loginparms,
2611 		    (caddr_t)&logi->common_service, sizeof (struct la_els_logi)
2612 		    - 4);
2613 		bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2614 		    (caddr_t)&logi->nport_ww_name, sizeof (la_wwn_t));
2615 		bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
2616 		    (caddr_t)&logi->node_ww_name, sizeof (la_wwn_t));
2617 		bzero((caddr_t)&logi->reserved, 16);
2618 	} else if (els_code == LA_ELS_LOGO) {
2619 		bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2620 		    (caddr_t)&(((struct la_els_logo *)logi)->nport_ww_name), 8);
2621 		((struct la_els_logo	*)logi)->reserved = 0;
2622 		((struct la_els_logo	*)logi)->nport_id[0] = 0;
2623 		((struct la_els_logo	*)logi)->nport_id[1] = 0;
2624 		((struct la_els_logo	*)logi)->nport_id[2] = arg1;
2625 	}
2626 
2627 	privp->els_code = els_code;
2628 	logi->ls_code = els_code;
2629 	logi->mbz[0] = 0;
2630 	logi->mbz[1] = 0;
2631 	logi->mbz[2] = 0;
2632 
2633 	privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2634 	return (sf_els_transport(sf, privp));
2635 }
2636 
2637 
2638 /*
2639  * send an ELS IU via the transport,
2640  * returning TRUE upon success, else returning FALSE
2641  */
2642 static int
sf_els_transport(struct sf * sf,struct sf_els_hdr * privp)2643 sf_els_transport(struct sf *sf, struct sf_els_hdr *privp)
2644 {
2645 	struct fcal_packet *fpkt = privp->fpkt;
2646 
2647 
2648 	(void) ddi_dma_sync(privp->cmd_dma_handle, (off_t)0, (size_t)0,
2649 	    DDI_DMA_SYNC_FORDEV);
2650 	privp->prev = NULL;
2651 	mutex_enter(&sf->sf_mutex);
2652 	privp->next = sf->sf_els_list;
2653 	if (sf->sf_els_list != NULL) {
2654 		sf->sf_els_list->prev = privp;
2655 	}
2656 	sf->sf_els_list = privp;
2657 	mutex_exit(&sf->sf_mutex);
2658 
2659 	/* call the transport to send a packet */
2660 	if (soc_transport(sf->sf_sochandle, fpkt, FCAL_NOSLEEP,
2661 	    CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
2662 		mutex_enter(&sf->sf_mutex);
2663 		if (privp->prev != NULL) {
2664 			privp->prev->next = privp->next;
2665 		}
2666 		if (privp->next != NULL) {
2667 			privp->next->prev = privp->prev;
2668 		}
2669 		if (sf->sf_els_list == privp) {
2670 			sf->sf_els_list = privp->next;
2671 		}
2672 		mutex_exit(&sf->sf_mutex);
2673 		sf_els_free(fpkt);
2674 		return (FALSE);			/* failure */
2675 	}
2676 	return (TRUE);				/* success */
2677 }
2678 
2679 
2680 /*
2681  * called as the pkt_comp routine for ELS FC packets
2682  */
2683 static void
sf_els_callback(struct fcal_packet * fpkt)2684 sf_els_callback(struct fcal_packet *fpkt)
2685 {
2686 	struct sf_els_hdr *privp = fpkt->fcal_pkt_private;
2687 	struct sf *sf = privp->sf;
2688 	struct sf *tsf;
2689 	int tgt_id;
2690 	struct la_els_logi *ptr = (struct la_els_logi *)privp->rsp;
2691 	struct la_els_adisc *adisc = (struct la_els_adisc *)ptr;
2692 	struct	sf_target *target;
2693 	short	ncmds;
2694 	short	free_pkt = TRUE;
2695 
2696 
2697 	/*
2698 	 * we've received an ELS callback, i.e. an ELS packet has arrived
2699 	 */
2700 
2701 	/* take the current packet off of the queue */
2702 	mutex_enter(&sf->sf_mutex);
2703 	if (privp->timeout == SF_INVALID_TIMEOUT) {
2704 		mutex_exit(&sf->sf_mutex);
2705 		return;
2706 	}
2707 	if (privp->prev != NULL) {
2708 		privp->prev->next = privp->next;
2709 	}
2710 	if (privp->next != NULL) {
2711 		privp->next->prev = privp->prev;
2712 	}
2713 	if (sf->sf_els_list == privp) {
2714 		sf->sf_els_list = privp->next;
2715 	}
2716 	privp->prev = privp->next = NULL;
2717 	mutex_exit(&sf->sf_mutex);
2718 
2719 	/* get # pkts in this callback */
2720 	ncmds = fpkt->fcal_ncmds;
2721 	ASSERT(ncmds >= 0);
2722 	mutex_enter(&sf->sf_cmd_mutex);
2723 	sf->sf_ncmds = ncmds;
2724 	mutex_exit(&sf->sf_cmd_mutex);
2725 
2726 	/* sync idea of memory */
2727 	(void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0, (size_t)0,
2728 	    DDI_DMA_SYNC_FORKERNEL);
2729 
2730 	/* was this an OK ACC msg ?? */
2731 	if ((fpkt->fcal_pkt_status == FCAL_STATUS_OK) &&
2732 	    (ptr->ls_code == LA_ELS_ACC)) {
2733 
2734 		/*
2735 		 * this was an OK ACC pkt
2736 		 */
2737 
2738 		switch (privp->els_code) {
2739 		case LA_ELS_PLOGI:
2740 			/*
2741 			 * was able to to an N_port login
2742 			 */
2743 			SF_DEBUG(2, (sf, CE_CONT,
2744 			    "!PLOGI to al_pa %x succeeded, wwn %x%x\n",
2745 			    privp->dest_nport_id,
2746 			    *((int *)&ptr->nport_ww_name.raw_wwn[0]),
2747 			    *((int *)&ptr->nport_ww_name.raw_wwn[4])));
2748 			/* try to do a process login */
2749 			if (!sf_do_prli(sf, privp, ptr)) {
2750 				free_pkt = FALSE;
2751 				goto fail;	/* PRLI failed */
2752 			}
2753 			break;
2754 		case LA_ELS_PRLI:
2755 			/*
2756 			 * was able to do a process login
2757 			 */
2758 			SF_DEBUG(2, (sf, CE_CONT,
2759 			    "!PRLI to al_pa %x succeeded\n",
2760 			    privp->dest_nport_id));
2761 			/* try to do address discovery */
2762 			if (sf_do_adisc(sf, privp) != 1) {
2763 				free_pkt = FALSE;
2764 				goto fail;	/* ADISC failed */
2765 			}
2766 			break;
2767 		case LA_ELS_ADISC:
2768 			/*
2769 			 * found a target via ADISC
2770 			 */
2771 
2772 			SF_DEBUG(2, (sf, CE_CONT,
2773 			    "!ADISC to al_pa %x succeeded\n",
2774 			    privp->dest_nport_id));
2775 
2776 			/* create the target info */
2777 			if ((target = sf_create_target(sf, privp,
2778 			    sf_alpa_to_switch[(uchar_t)adisc->hard_address],
2779 			    (int64_t)0))
2780 			    == NULL) {
2781 				goto fail;	/* can't create target */
2782 			}
2783 
2784 			/*
2785 			 * ensure address discovered matches what we thought
2786 			 * it would be
2787 			 */
2788 			if ((uchar_t)adisc->hard_address !=
2789 			    privp->dest_nport_id) {
2790 				sf_log(sf, CE_WARN,
2791 				    "target 0x%x, AL-PA 0x%x and "
2792 				    "hard address 0x%x don't match\n",
2793 				    sf_alpa_to_switch[
2794 				    (uchar_t)privp->dest_nport_id],
2795 				    privp->dest_nport_id,
2796 				    (uchar_t)adisc->hard_address);
2797 				mutex_enter(&sf->sf_mutex);
2798 				sf_offline_target(sf, target);
2799 				mutex_exit(&sf->sf_mutex);
2800 				goto fail;	/* addr doesn't match */
2801 			}
2802 			/*
2803 			 * get inquiry data from the target
2804 			 */
2805 			if (!sf_do_reportlun(sf, privp, target)) {
2806 				mutex_enter(&sf->sf_mutex);
2807 				sf_offline_target(sf, target);
2808 				mutex_exit(&sf->sf_mutex);
2809 				free_pkt = FALSE;
2810 				goto fail;	/* inquiry failed */
2811 			}
2812 			break;
2813 		default:
2814 			SF_DEBUG(2, (sf, CE_CONT,
2815 			    "!ELS %x to al_pa %x succeeded\n",
2816 			    privp->els_code, privp->dest_nport_id));
2817 			sf_els_free(fpkt);
2818 			break;
2819 		}
2820 
2821 	} else {
2822 
2823 		/*
2824 		 * oh oh -- this was not an OK ACC packet
2825 		 */
2826 
2827 		/* get target ID from dest loop address */
2828 		tgt_id = sf_alpa_to_switch[(uchar_t)privp->dest_nport_id];
2829 
2830 		/* keep track of failures */
2831 		sf->sf_stats.tstats[tgt_id].els_failures++;
2832 		if (++(privp->retries) < sf_els_retries &&
2833 		    fpkt->fcal_pkt_status != FCAL_STATUS_OPEN_FAIL) {
2834 			if (fpkt->fcal_pkt_status ==
2835 			    FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
2836 				tsf = sf->sf_sibling;
2837 				if (tsf != NULL) {
2838 					mutex_enter(&tsf->sf_cmd_mutex);
2839 					tsf->sf_flag = 1;
2840 					tsf->sf_throttle = SF_DECR_DELTA;
2841 					mutex_exit(&tsf->sf_cmd_mutex);
2842 				}
2843 			}
2844 			privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2845 			privp->prev = NULL;
2846 
2847 			mutex_enter(&sf->sf_mutex);
2848 
2849 			if (privp->lip_cnt == sf->sf_lip_cnt) {
2850 				SF_DEBUG(1, (sf, CE_WARN,
2851 				    "!ELS %x to al_pa %x failed, retrying",
2852 				    privp->els_code, privp->dest_nport_id));
2853 				privp->next = sf->sf_els_list;
2854 				if (sf->sf_els_list != NULL) {
2855 					sf->sf_els_list->prev = privp;
2856 				}
2857 
2858 				sf->sf_els_list = privp;
2859 
2860 				mutex_exit(&sf->sf_mutex);
2861 				/* device busy?  wait a bit ... */
2862 				if (fpkt->fcal_pkt_status ==
2863 				    FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
2864 					privp->delayed_retry = 1;
2865 					return;
2866 				}
2867 				/* call the transport to send a pkt */
2868 				if (soc_transport(sf->sf_sochandle, fpkt,
2869 				    FCAL_NOSLEEP, CQ_REQUEST_1) !=
2870 				    FCAL_TRANSPORT_SUCCESS) {
2871 					mutex_enter(&sf->sf_mutex);
2872 					if (privp->prev != NULL) {
2873 						privp->prev->next =
2874 						    privp->next;
2875 					}
2876 					if (privp->next != NULL) {
2877 						privp->next->prev =
2878 						    privp->prev;
2879 					}
2880 					if (sf->sf_els_list == privp) {
2881 						sf->sf_els_list = privp->next;
2882 					}
2883 					mutex_exit(&sf->sf_mutex);
2884 					goto fail;
2885 				} else
2886 					return;
2887 			} else {
2888 				mutex_exit(&sf->sf_mutex);
2889 				goto fail;
2890 			}
2891 		} else {
2892 #ifdef	DEBUG
2893 			if (fpkt->fcal_pkt_status != 0x36 || sfdebug > 4) {
2894 			SF_DEBUG(2, (sf, CE_NOTE, "ELS %x to al_pa %x failed",
2895 			    privp->els_code, privp->dest_nport_id));
2896 			if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
2897 				SF_DEBUG(2, (sf, CE_NOTE,
2898 				    "els reply code = %x", ptr->ls_code));
2899 				if (ptr->ls_code == LA_ELS_RJT)
2900 					SF_DEBUG(1, (sf, CE_CONT,
2901 					    "LS_RJT reason = %x\n",
2902 					    *(((uint_t *)ptr) + 1)));
2903 			} else
2904 				SF_DEBUG(2, (sf, CE_NOTE,
2905 				    "fc packet status = %x",
2906 				    fpkt->fcal_pkt_status));
2907 			}
2908 #endif
2909 			goto fail;
2910 		}
2911 	}
2912 	return;					/* success */
2913 fail:
2914 	mutex_enter(&sf->sf_mutex);
2915 	if (sf->sf_lip_cnt == privp->lip_cnt) {
2916 		sf->sf_device_count--;
2917 		ASSERT(sf->sf_device_count >= 0);
2918 		if (sf->sf_device_count == 0) {
2919 			sf_finish_init(sf, privp->lip_cnt);
2920 		}
2921 	}
2922 	mutex_exit(&sf->sf_mutex);
2923 	if (free_pkt) {
2924 		sf_els_free(fpkt);
2925 	}
2926 }
2927 
2928 
2929 /*
2930  * send a PRLI (process login) ELS IU via the transport,
2931  * returning TRUE upon success, else returning FALSE
2932  */
2933 static int
sf_do_prli(struct sf * sf,struct sf_els_hdr * privp,struct la_els_logi * ptr)2934 sf_do_prli(struct sf *sf, struct sf_els_hdr *privp, struct la_els_logi *ptr)
2935 {
2936 	struct la_els_prli	*prli = (struct la_els_prli *)privp->cmd;
2937 	struct fcp_prli		*fprli;
2938 	struct  fcal_packet	*fpkt = privp->fpkt;
2939 
2940 
2941 	fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
2942 	    sizeof (struct la_els_prli);
2943 	privp->els_code = LA_ELS_PRLI;
2944 	fprli = (struct fcp_prli *)prli->service_params;
2945 	prli->ls_code = LA_ELS_PRLI;
2946 	prli->page_length = 0x10;
2947 	prli->payload_length = sizeof (struct la_els_prli);
2948 	fprli->type = 0x08;			/* no define here? */
2949 	fprli->resvd1 = 0;
2950 	fprli->orig_process_assoc_valid = 0;
2951 	fprli->resp_process_assoc_valid = 0;
2952 	fprli->establish_image_pair = 1;
2953 	fprli->resvd2 = 0;
2954 	fprli->resvd3 = 0;
2955 	fprli->data_overlay_allowed = 0;
2956 	fprli->initiator_fn = 1;
2957 	fprli->target_fn = 0;
2958 	fprli->cmd_data_mixed = 0;
2959 	fprli->data_resp_mixed = 0;
2960 	fprli->read_xfer_rdy_disabled = 1;
2961 	fprli->write_xfer_rdy_disabled = 0;
2962 
2963 	bcopy((caddr_t)&ptr->nport_ww_name, (caddr_t)&privp->port_wwn,
2964 	    sizeof (privp->port_wwn));
2965 	bcopy((caddr_t)&ptr->node_ww_name, (caddr_t)&privp->node_wwn,
2966 	    sizeof (privp->node_wwn));
2967 
2968 	privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2969 	return (sf_els_transport(sf, privp));
2970 }
2971 
2972 
2973 /*
2974  * send an ADISC (address discovery) ELS IU via the transport,
2975  * returning TRUE upon success, else returning FALSE
2976  */
2977 static int
sf_do_adisc(struct sf * sf,struct sf_els_hdr * privp)2978 sf_do_adisc(struct sf *sf, struct sf_els_hdr *privp)
2979 {
2980 	struct la_els_adisc	*adisc = (struct la_els_adisc *)privp->cmd;
2981 	struct	fcal_packet	*fpkt = privp->fpkt;
2982 
2983 	privp->els_code = LA_ELS_ADISC;
2984 	adisc->ls_code = LA_ELS_ADISC;
2985 	adisc->mbz[0] = 0;
2986 	adisc->mbz[1] = 0;
2987 	adisc->mbz[2] = 0;
2988 	adisc->hard_address = 0; /* ??? */
2989 	fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
2990 	    sizeof (struct la_els_adisc);
2991 	bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2992 	    (caddr_t)&adisc->port_wwn, sizeof (adisc->port_wwn));
2993 	bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
2994 	    (caddr_t)&adisc->node_wwn, sizeof (adisc->node_wwn));
2995 	adisc->nport_id = sf->sf_al_pa;
2996 
2997 	privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2998 	return (sf_els_transport(sf, privp));
2999 }
3000 
3001 
3002 static struct fcal_packet *
sf_els_alloc(struct sf * sf,uchar_t dest_id,int priv_size,int cmd_size,int rsp_size,caddr_t * rprivp,caddr_t * cmd_buf)3003 sf_els_alloc(struct sf *sf, uchar_t dest_id, int priv_size, int cmd_size,
3004     int rsp_size, caddr_t *rprivp, caddr_t *cmd_buf)
3005 {
3006 	struct	fcal_packet	*fpkt;
3007 	ddi_dma_cookie_t	pcookie;
3008 	ddi_dma_cookie_t	rcookie;
3009 	struct	sf_els_hdr	*privp;
3010 	ddi_dma_handle_t	cmd_dma_handle = NULL;
3011 	ddi_dma_handle_t	rsp_dma_handle = NULL;
3012 	ddi_acc_handle_t	cmd_acc_handle = NULL;
3013 	ddi_acc_handle_t	rsp_acc_handle = NULL;
3014 	size_t			real_size;
3015 	uint_t			ccount;
3016 	fc_frame_header_t	*hp;
3017 	int			cmd_bound = FALSE, rsp_bound = FALSE;
3018 	caddr_t			cmd = NULL;
3019 	caddr_t			rsp = NULL;
3020 
3021 	if ((fpkt = (struct fcal_packet *)kmem_zalloc(
3022 	    sizeof (struct fcal_packet), KM_NOSLEEP)) == NULL) {
3023 		SF_DEBUG(1, (sf, CE_WARN,
3024 			"Could not allocate fcal_packet for ELS\n"));
3025 		return (NULL);
3026 	}
3027 
3028 	if ((privp = (struct sf_els_hdr *)kmem_zalloc(priv_size,
3029 	    KM_NOSLEEP)) == NULL) {
3030 		SF_DEBUG(1, (sf, CE_WARN,
3031 		    "Could not allocate sf_els_hdr for ELS\n"));
3032 		goto fail;
3033 	}
3034 
3035 	privp->size = priv_size;
3036 	fpkt->fcal_pkt_private = (caddr_t)privp;
3037 
3038 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3039 	    DDI_DMA_DONTWAIT, NULL, &cmd_dma_handle) != DDI_SUCCESS) {
3040 		SF_DEBUG(1, (sf, CE_WARN,
3041 		    "Could not allocate DMA handle for ELS\n"));
3042 		goto fail;
3043 	}
3044 
3045 	if (ddi_dma_mem_alloc(cmd_dma_handle, cmd_size,
3046 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3047 	    DDI_DMA_DONTWAIT, NULL, &cmd,
3048 	    &real_size, &cmd_acc_handle) != DDI_SUCCESS) {
3049 		SF_DEBUG(1, (sf, CE_WARN,
3050 		    "Could not allocate DMA memory for ELS\n"));
3051 		goto fail;
3052 	}
3053 
3054 	if (real_size < cmd_size) {
3055 		SF_DEBUG(1, (sf, CE_WARN,
3056 		    "DMA memory too small for ELS\n"));
3057 		goto fail;
3058 	}
3059 
3060 	if (ddi_dma_addr_bind_handle(cmd_dma_handle, NULL,
3061 	    cmd, real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
3062 	    DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3063 		SF_DEBUG(1, (sf, CE_WARN,
3064 		    "Could not bind DMA memory for ELS\n"));
3065 		goto fail;
3066 	}
3067 	cmd_bound = TRUE;
3068 
3069 	if (ccount != 1) {
3070 		SF_DEBUG(1, (sf, CE_WARN,
3071 		    "Wrong cookie count for ELS\n"));
3072 		goto fail;
3073 	}
3074 
3075 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3076 	    DDI_DMA_DONTWAIT, NULL, &rsp_dma_handle) != DDI_SUCCESS) {
3077 		SF_DEBUG(1, (sf, CE_WARN,
3078 		    "Could not allocate DMA handle for ELS rsp\n"));
3079 		goto fail;
3080 	}
3081 	if (ddi_dma_mem_alloc(rsp_dma_handle, rsp_size,
3082 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3083 	    DDI_DMA_DONTWAIT, NULL, &rsp,
3084 	    &real_size, &rsp_acc_handle) != DDI_SUCCESS) {
3085 		SF_DEBUG(1, (sf, CE_WARN,
3086 		    "Could not allocate DMA memory for ELS rsp\n"));
3087 		goto fail;
3088 	}
3089 
3090 	if (real_size < rsp_size) {
3091 		SF_DEBUG(1, (sf, CE_WARN,
3092 		    "DMA memory too small for ELS rsp\n"));
3093 		goto fail;
3094 	}
3095 
3096 	if (ddi_dma_addr_bind_handle(rsp_dma_handle, NULL,
3097 	    rsp, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3098 	    DDI_DMA_DONTWAIT, NULL, &rcookie, &ccount) != DDI_DMA_MAPPED) {
3099 		SF_DEBUG(1, (sf, CE_WARN,
3100 		    "Could not bind DMA memory for ELS rsp\n"));
3101 		goto fail;
3102 	}
3103 	rsp_bound = TRUE;
3104 
3105 	if (ccount != 1) {
3106 		SF_DEBUG(1, (sf, CE_WARN,
3107 		    "Wrong cookie count for ELS rsp\n"));
3108 		goto fail;
3109 	}
3110 
3111 	privp->cmd = cmd;
3112 	privp->sf = sf;
3113 	privp->cmd_dma_handle = cmd_dma_handle;
3114 	privp->cmd_acc_handle = cmd_acc_handle;
3115 	privp->rsp = rsp;
3116 	privp->rsp_dma_handle = rsp_dma_handle;
3117 	privp->rsp_acc_handle = rsp_acc_handle;
3118 	privp->dest_nport_id = dest_id;
3119 	privp->fpkt = fpkt;
3120 
3121 	fpkt->fcal_pkt_cookie = sf->sf_socp;
3122 	fpkt->fcal_pkt_comp = sf_els_callback;
3123 	fpkt->fcal_magic = FCALP_MAGIC;
3124 	fpkt->fcal_pkt_flags = 0;
3125 	fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
3126 	    (ushort_t)(SOC_FC_HEADER | sf->sf_sochandle->fcal_portno);
3127 	fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
3128 	fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
3129 	fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = cmd_size;
3130 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
3131 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
3132 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
3133 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
3134 	fpkt->fcal_socal_request.sr_dataseg[0].fc_base = (uint32_t)
3135 	    pcookie.dmac_address;
3136 	fpkt->fcal_socal_request.sr_dataseg[0].fc_count = cmd_size;
3137 	fpkt->fcal_socal_request.sr_dataseg[1].fc_base = (uint32_t)
3138 	    rcookie.dmac_address;
3139 	fpkt->fcal_socal_request.sr_dataseg[1].fc_count = rsp_size;
3140 
3141 	/* Fill in the Fabric Channel Header */
3142 	hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3143 	hp->r_ctl = R_CTL_ELS_REQ;
3144 	hp->d_id = dest_id;
3145 	hp->s_id = sf->sf_al_pa;
3146 	hp->type = TYPE_EXTENDED_LS;
3147 	hp->reserved1 = 0;
3148 	hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3149 	hp->seq_id = 0;
3150 	hp->df_ctl  = 0;
3151 	hp->seq_cnt = 0;
3152 	hp->ox_id = 0xffff;
3153 	hp->rx_id = 0xffff;
3154 	hp->ro = 0;
3155 
3156 	*rprivp = (caddr_t)privp;
3157 	*cmd_buf = cmd;
3158 	return (fpkt);
3159 
3160 fail:
3161 	if (cmd_dma_handle != NULL) {
3162 		if (cmd_bound) {
3163 			(void) ddi_dma_unbind_handle(cmd_dma_handle);
3164 		}
3165 		ddi_dma_free_handle(&cmd_dma_handle);
3166 		privp->cmd_dma_handle = NULL;
3167 	}
3168 	if (rsp_dma_handle != NULL) {
3169 		if (rsp_bound) {
3170 			(void) ddi_dma_unbind_handle(rsp_dma_handle);
3171 		}
3172 		ddi_dma_free_handle(&rsp_dma_handle);
3173 		privp->rsp_dma_handle = NULL;
3174 	}
3175 	sf_els_free(fpkt);
3176 	return (NULL);
3177 }
3178 
3179 
3180 static void
sf_els_free(struct fcal_packet * fpkt)3181 sf_els_free(struct fcal_packet *fpkt)
3182 {
3183 	struct	sf_els_hdr	*privp = fpkt->fcal_pkt_private;
3184 
3185 	if (privp != NULL) {
3186 		if (privp->cmd_dma_handle != NULL) {
3187 			(void) ddi_dma_unbind_handle(privp->cmd_dma_handle);
3188 			ddi_dma_free_handle(&privp->cmd_dma_handle);
3189 		}
3190 		if (privp->cmd != NULL) {
3191 			ddi_dma_mem_free(&privp->cmd_acc_handle);
3192 		}
3193 
3194 		if (privp->rsp_dma_handle != NULL) {
3195 			(void) ddi_dma_unbind_handle(privp->rsp_dma_handle);
3196 			ddi_dma_free_handle(&privp->rsp_dma_handle);
3197 		}
3198 
3199 		if (privp->rsp != NULL) {
3200 			ddi_dma_mem_free(&privp->rsp_acc_handle);
3201 		}
3202 		if (privp->data_dma_handle) {
3203 			(void) ddi_dma_unbind_handle(privp->data_dma_handle);
3204 			ddi_dma_free_handle(&privp->data_dma_handle);
3205 		}
3206 		if (privp->data_buf) {
3207 			ddi_dma_mem_free(&privp->data_acc_handle);
3208 		}
3209 		kmem_free(privp, privp->size);
3210 	}
3211 	kmem_free(fpkt, sizeof (struct fcal_packet));
3212 }
3213 
3214 
3215 static struct sf_target *
sf_create_target(struct sf * sf,struct sf_els_hdr * privp,int tnum,int64_t lun)3216 sf_create_target(struct sf *sf, struct sf_els_hdr *privp, int tnum, int64_t lun)
3217 {
3218 	struct sf_target *target, *ntarget, *otarget, *ptarget;
3219 	int hash;
3220 #ifdef RAID_LUNS
3221 	int64_t orig_lun = lun;
3222 
3223 	/* XXXX Work around SCSA limitations. */
3224 	lun = *((short *)&lun);
3225 #endif
3226 	ntarget = kmem_zalloc(sizeof (struct sf_target), KM_NOSLEEP);
3227 	mutex_enter(&sf->sf_mutex);
3228 	if (sf->sf_lip_cnt != privp->lip_cnt) {
3229 		mutex_exit(&sf->sf_mutex);
3230 		if (ntarget != NULL)
3231 			kmem_free(ntarget, sizeof (struct sf_target));
3232 		return (NULL);
3233 	}
3234 
3235 	target = sf_lookup_target(sf, privp->port_wwn, lun);
3236 	if (lun != 0) {
3237 		/*
3238 		 * Since LUNs != 0 are queued up after LUN == 0, find LUN == 0
3239 		 * and enqueue the new LUN.
3240 		 */
3241 		if ((ptarget = sf_lookup_target(sf, privp->port_wwn,
3242 		    (int64_t)0)) ==	NULL) {
3243 			/*
3244 			 * Yeep -- no LUN 0?
3245 			 */
3246 			mutex_exit(&sf->sf_mutex);
3247 			sf_log(sf, CE_WARN, "target 0x%x "
3248 			    "lun %" PRIx64 ": No LUN 0\n", tnum, lun);
3249 			if (ntarget != NULL)
3250 				kmem_free(ntarget, sizeof (struct sf_target));
3251 			return (NULL);
3252 		}
3253 		mutex_enter(&ptarget->sft_mutex);
3254 		if (target != NULL && ptarget->sft_lip_cnt == sf->sf_lip_cnt &&
3255 		    ptarget->sft_state&SF_TARGET_OFFLINE) {
3256 			/* LUN 0 already finished, duplicate its state */
3257 			mutex_exit(&ptarget->sft_mutex);
3258 			sf_offline_target(sf, target);
3259 			mutex_exit(&sf->sf_mutex);
3260 			if (ntarget != NULL)
3261 				kmem_free(ntarget, sizeof (struct sf_target));
3262 			return (target);
3263 		} else if (target != NULL) {
3264 			/*
3265 			 * LUN 0 online or not examined yet.
3266 			 * Try to bring the LUN back online
3267 			 */
3268 			mutex_exit(&ptarget->sft_mutex);
3269 			mutex_enter(&target->sft_mutex);
3270 			target->sft_lip_cnt = privp->lip_cnt;
3271 			target->sft_state |= SF_TARGET_BUSY;
3272 			target->sft_state &= ~(SF_TARGET_OFFLINE|
3273 			    SF_TARGET_MARK);
3274 			target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3275 			target->sft_hard_address = sf_switch_to_alpa[tnum];
3276 			mutex_exit(&target->sft_mutex);
3277 			mutex_exit(&sf->sf_mutex);
3278 			if (ntarget != NULL)
3279 				kmem_free(ntarget, sizeof (struct sf_target));
3280 			return (target);
3281 		}
3282 		mutex_exit(&ptarget->sft_mutex);
3283 		if (ntarget == NULL) {
3284 			mutex_exit(&sf->sf_mutex);
3285 			return (NULL);
3286 		}
3287 		/* Initialize new target structure */
3288 		bcopy((caddr_t)&privp->node_wwn,
3289 		    (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3290 		bcopy((caddr_t)&privp->port_wwn,
3291 		    (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3292 		ntarget->sft_lun.l = lun;
3293 #ifdef RAID_LUNS
3294 		ntarget->sft_lun.l = orig_lun;
3295 		ntarget->sft_raid_lun = (uint_t)lun;
3296 #endif
3297 		mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3298 		mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3299 		/* Don't let anyone use this till we finishup init. */
3300 		mutex_enter(&ntarget->sft_mutex);
3301 		mutex_enter(&ntarget->sft_pkt_mutex);
3302 
3303 		hash = SF_HASH(privp->port_wwn, lun);
3304 		ntarget->sft_next = sf->sf_wwn_lists[hash];
3305 		sf->sf_wwn_lists[hash] = ntarget;
3306 
3307 		ntarget->sft_lip_cnt = privp->lip_cnt;
3308 		ntarget->sft_al_pa = (uchar_t)privp->dest_nport_id;
3309 		ntarget->sft_hard_address = sf_switch_to_alpa[tnum];
3310 		ntarget->sft_device_type = DTYPE_UNKNOWN;
3311 		ntarget->sft_state = SF_TARGET_BUSY;
3312 		ntarget->sft_pkt_head = (struct sf_pkt *)&ntarget->
3313 		    sft_pkt_head;
3314 		ntarget->sft_pkt_tail = (struct sf_pkt *)&ntarget->
3315 		    sft_pkt_head;
3316 
3317 		mutex_enter(&ptarget->sft_mutex);
3318 		/* Traverse the list looking for this target */
3319 		for (target = ptarget; target->sft_next_lun;
3320 		    target = target->sft_next_lun) {
3321 			otarget = target->sft_next_lun;
3322 		}
3323 		ntarget->sft_next_lun = target->sft_next_lun;
3324 		target->sft_next_lun = ntarget;
3325 		mutex_exit(&ptarget->sft_mutex);
3326 		mutex_exit(&ntarget->sft_pkt_mutex);
3327 		mutex_exit(&ntarget->sft_mutex);
3328 		mutex_exit(&sf->sf_mutex);
3329 		return (ntarget);
3330 
3331 	}
3332 	if (target != NULL && target->sft_lip_cnt == sf->sf_lip_cnt) {
3333 		/* It's been touched this LIP -- duplicate WWNs */
3334 		sf_offline_target(sf, target); /* And all the baby targets */
3335 		mutex_exit(&sf->sf_mutex);
3336 		sf_log(sf, CE_WARN, "target 0x%x, duplicate port wwns\n",
3337 		    tnum);
3338 		if (ntarget != NULL) {
3339 			kmem_free(ntarget, sizeof (struct sf_target));
3340 		}
3341 		return (NULL);
3342 	}
3343 
3344 	if ((otarget = sf->sf_targets[tnum]) != NULL) {
3345 		/* Someone else is in our slot */
3346 		mutex_enter(&otarget->sft_mutex);
3347 		if (otarget->sft_lip_cnt == sf->sf_lip_cnt) {
3348 			mutex_exit(&otarget->sft_mutex);
3349 			sf_offline_target(sf, otarget);
3350 			if (target != NULL)
3351 				sf_offline_target(sf, target);
3352 			mutex_exit(&sf->sf_mutex);
3353 			sf_log(sf, CE_WARN,
3354 			    "target 0x%x, duplicate switch settings\n", tnum);
3355 			if (ntarget != NULL)
3356 				kmem_free(ntarget, sizeof (struct sf_target));
3357 			return (NULL);
3358 		}
3359 		mutex_exit(&otarget->sft_mutex);
3360 		if (bcmp((caddr_t)&privp->port_wwn, (caddr_t)&otarget->
3361 		    sft_port_wwn, sizeof (privp->port_wwn))) {
3362 			sf_offline_target(sf, otarget);
3363 			mutex_exit(&sf->sf_mutex);
3364 			sf_log(sf, CE_WARN, "wwn changed on target 0x%x\n",
3365 			    tnum);
3366 			bzero((caddr_t)&sf->sf_stats.tstats[tnum],
3367 			    sizeof (struct sf_target_stats));
3368 			mutex_enter(&sf->sf_mutex);
3369 		}
3370 	}
3371 
3372 	sf->sf_targets[tnum] = target;
3373 	if ((target = sf->sf_targets[tnum]) == NULL) {
3374 		if (ntarget == NULL) {
3375 			mutex_exit(&sf->sf_mutex);
3376 			return (NULL);
3377 		}
3378 		bcopy((caddr_t)&privp->node_wwn,
3379 		    (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3380 		bcopy((caddr_t)&privp->port_wwn,
3381 		    (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3382 		ntarget->sft_lun.l = lun;
3383 #ifdef RAID_LUNS
3384 		ntarget->sft_lun.l = orig_lun;
3385 		ntarget->sft_raid_lun = (uint_t)lun;
3386 #endif
3387 		mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3388 		mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3389 		mutex_enter(&ntarget->sft_mutex);
3390 		mutex_enter(&ntarget->sft_pkt_mutex);
3391 		hash = SF_HASH(privp->port_wwn, lun); /* lun 0 */
3392 		ntarget->sft_next = sf->sf_wwn_lists[hash];
3393 		sf->sf_wwn_lists[hash] = ntarget;
3394 
3395 		target = ntarget;
3396 		target->sft_lip_cnt = privp->lip_cnt;
3397 		target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3398 		target->sft_hard_address = sf_switch_to_alpa[tnum];
3399 		target->sft_device_type = DTYPE_UNKNOWN;
3400 		target->sft_state = SF_TARGET_BUSY;
3401 		target->sft_pkt_head = (struct sf_pkt *)&target->
3402 		    sft_pkt_head;
3403 		target->sft_pkt_tail = (struct sf_pkt *)&target->
3404 		    sft_pkt_head;
3405 		sf->sf_targets[tnum] = target;
3406 		mutex_exit(&ntarget->sft_mutex);
3407 		mutex_exit(&ntarget->sft_pkt_mutex);
3408 		mutex_exit(&sf->sf_mutex);
3409 	} else {
3410 		mutex_enter(&target->sft_mutex);
3411 		target->sft_lip_cnt = privp->lip_cnt;
3412 		target->sft_state |= SF_TARGET_BUSY;
3413 		target->sft_state &= ~(SF_TARGET_OFFLINE|SF_TARGET_MARK);
3414 		target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3415 		target->sft_hard_address = sf_switch_to_alpa[tnum];
3416 		mutex_exit(&target->sft_mutex);
3417 		mutex_exit(&sf->sf_mutex);
3418 		if (ntarget != NULL)
3419 			kmem_free(ntarget, sizeof (struct sf_target));
3420 	}
3421 	return (target);
3422 }
3423 
3424 
3425 /*
3426  * find the target for a given sf instance
3427  */
3428 /* ARGSUSED */
3429 static struct sf_target *
3430 #ifdef RAID_LUNS
sf_lookup_target(struct sf * sf,uchar_t * wwn,int lun)3431 sf_lookup_target(struct sf *sf, uchar_t *wwn, int lun)
3432 #else
3433 sf_lookup_target(struct sf *sf, uchar_t *wwn, int64_t lun)
3434 #endif
3435 {
3436 	int hash;
3437 	struct sf_target *target;
3438 
3439 	ASSERT(mutex_owned(&sf->sf_mutex));
3440 	hash = SF_HASH(wwn, lun);
3441 
3442 	target = sf->sf_wwn_lists[hash];
3443 	while (target != NULL) {
3444 
3445 #ifndef	RAID_LUNS
3446 		if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3447 		    sizeof (target->sft_port_wwn)) == 0 &&
3448 			target->sft_lun.l == lun)
3449 			break;
3450 #else
3451 		if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3452 		    sizeof (target->sft_port_wwn)) == 0 &&
3453 			target->sft_raid_lun == lun)
3454 			break;
3455 #endif
3456 		target = target->sft_next;
3457 	}
3458 
3459 	return (target);
3460 }
3461 
3462 
3463 /*
3464  * Send out a REPORT_LUNS command.
3465  */
3466 static int
sf_do_reportlun(struct sf * sf,struct sf_els_hdr * privp,struct sf_target * target)3467 sf_do_reportlun(struct sf *sf, struct sf_els_hdr *privp,
3468     struct sf_target *target)
3469 {
3470 	struct	fcal_packet	*fpkt = privp->fpkt;
3471 	ddi_dma_cookie_t	pcookie;
3472 	ddi_dma_handle_t	lun_dma_handle = NULL;
3473 	ddi_acc_handle_t	lun_acc_handle;
3474 	uint_t			ccount;
3475 	size_t			real_size;
3476 	caddr_t			lun_buf = NULL;
3477 	int			handle_bound = 0;
3478 	fc_frame_header_t	*hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3479 	struct fcp_cmd		*reportlun = (struct fcp_cmd *)privp->cmd;
3480 	char			*msg = "Transport";
3481 
3482 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3483 	    DDI_DMA_DONTWAIT, NULL, &lun_dma_handle) != DDI_SUCCESS) {
3484 		msg = "ddi_dma_alloc_handle()";
3485 		goto fail;
3486 	}
3487 
3488 	if (ddi_dma_mem_alloc(lun_dma_handle, REPORT_LUNS_SIZE,
3489 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3490 	    DDI_DMA_DONTWAIT, NULL, &lun_buf,
3491 	    &real_size, &lun_acc_handle) != DDI_SUCCESS) {
3492 		msg = "ddi_dma_mem_alloc()";
3493 		goto fail;
3494 	}
3495 
3496 	if (real_size < REPORT_LUNS_SIZE) {
3497 		msg = "DMA mem < REPORT_LUNS_SIZE";
3498 		goto fail;
3499 	}
3500 
3501 	if (ddi_dma_addr_bind_handle(lun_dma_handle, NULL,
3502 	    lun_buf, real_size, DDI_DMA_READ |
3503 	    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
3504 	    NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3505 		msg = "ddi_dma_addr_bind_handle()";
3506 		goto fail;
3507 	}
3508 	handle_bound = 1;
3509 
3510 	if (ccount != 1) {
3511 		msg = "ccount != 1";
3512 		goto fail;
3513 	}
3514 	privp->els_code = 0;
3515 	privp->target = target;
3516 	privp->data_dma_handle = lun_dma_handle;
3517 	privp->data_acc_handle = lun_acc_handle;
3518 	privp->data_buf = lun_buf;
3519 
3520 	fpkt->fcal_pkt_comp = sf_reportlun_callback;
3521 	fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3522 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3523 	fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3524 	    sizeof (struct fcp_cmd);
3525 	fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3526 	    (uint32_t)pcookie.dmac_address;
3527 	fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3528 	fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3529 	hp->r_ctl = R_CTL_COMMAND;
3530 	hp->type = TYPE_SCSI_FCP;
3531 	bzero((caddr_t)reportlun, sizeof (struct fcp_cmd));
3532 	((union scsi_cdb *)reportlun->fcp_cdb)->scc_cmd = SCMD_REPORT_LUNS;
3533 	/* Now set the buffer size.  If DDI gave us extra, that's O.K. */
3534 	((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count0 =
3535 	    (real_size&0x0ff);
3536 	((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count1 =
3537 	    (real_size>>8)&0x0ff;
3538 	((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count2 =
3539 	    (real_size>>16)&0x0ff;
3540 	((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count3 =
3541 	    (real_size>>24)&0x0ff;
3542 	reportlun->fcp_cntl.cntl_read_data = 1;
3543 	reportlun->fcp_cntl.cntl_write_data = 0;
3544 	reportlun->fcp_data_len = pcookie.dmac_size;
3545 	reportlun->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3546 
3547 	(void) ddi_dma_sync(lun_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
3548 	/* We know he's there, so this should be fast */
3549 	privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3550 	if (sf_els_transport(sf, privp) == 1)
3551 		return (1);
3552 
3553 fail:
3554 	sf_log(sf, CE_WARN,
3555 	    "%s failure for REPORTLUN to target 0x%x\n",
3556 	    msg, sf_alpa_to_switch[privp->dest_nport_id]);
3557 	sf_els_free(fpkt);
3558 	if (lun_dma_handle != NULL) {
3559 		if (handle_bound)
3560 			(void) ddi_dma_unbind_handle(lun_dma_handle);
3561 		ddi_dma_free_handle(&lun_dma_handle);
3562 	}
3563 	if (lun_buf != NULL) {
3564 		ddi_dma_mem_free(&lun_acc_handle);
3565 	}
3566 	return (0);
3567 }
3568 
3569 /*
3570  * Handle the results of a REPORT_LUNS command:
3571  *	Create additional targets if necessary
3572  *	Initiate INQUIRYs on all LUNs.
3573  */
3574 static void
sf_reportlun_callback(struct fcal_packet * fpkt)3575 sf_reportlun_callback(struct fcal_packet *fpkt)
3576 {
3577 	struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3578 	    fcal_pkt_private;
3579 	struct scsi_report_luns *ptr =
3580 	    (struct scsi_report_luns *)privp->data_buf;
3581 	struct sf *sf = privp->sf;
3582 	struct sf_target *target = privp->target;
3583 	struct fcp_rsp *rsp = NULL;
3584 	int delayed_retry = 0;
3585 	int tid = sf_alpa_to_switch[target->sft_hard_address];
3586 	int i, free_pkt = 1;
3587 	short	ncmds;
3588 
3589 	mutex_enter(&sf->sf_mutex);
3590 	/* use as temporary state variable */
3591 	if (privp->timeout == SF_INVALID_TIMEOUT) {
3592 		mutex_exit(&sf->sf_mutex);
3593 		return;
3594 	}
3595 	if (privp->prev)
3596 		privp->prev->next = privp->next;
3597 	if (privp->next)
3598 		privp->next->prev = privp->prev;
3599 	if (sf->sf_els_list == privp)
3600 		sf->sf_els_list = privp->next;
3601 	privp->prev = privp->next = NULL;
3602 	mutex_exit(&sf->sf_mutex);
3603 	ncmds = fpkt->fcal_ncmds;
3604 	ASSERT(ncmds >= 0);
3605 	mutex_enter(&sf->sf_cmd_mutex);
3606 	sf->sf_ncmds = ncmds;
3607 	mutex_exit(&sf->sf_cmd_mutex);
3608 
3609 	if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3610 		(void) ddi_dma_sync(privp->rsp_dma_handle, 0,
3611 		    0, DDI_DMA_SYNC_FORKERNEL);
3612 
3613 		rsp = (struct fcp_rsp *)privp->rsp;
3614 	}
3615 	SF_DEBUG(1, (sf, CE_CONT,
3616 	    "!REPORTLUN to al_pa %x pkt status %x scsi status %x\n",
3617 	    privp->dest_nport_id,
3618 	    fpkt->fcal_pkt_status,
3619 	    rsp?rsp->fcp_u.fcp_status.scsi_status:0));
3620 
3621 		/* See if target simply does not support REPORT_LUNS. */
3622 	if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK &&
3623 	    rsp->fcp_u.fcp_status.sense_len_set &&
3624 	    rsp->fcp_sense_len >=
3625 		offsetof(struct scsi_extended_sense, es_qual_code)) {
3626 			struct scsi_extended_sense *sense;
3627 			sense = (struct scsi_extended_sense *)
3628 			((caddr_t)rsp + sizeof (struct fcp_rsp)
3629 				+ rsp->fcp_response_len);
3630 			if (sense->es_key == KEY_ILLEGAL_REQUEST) {
3631 				if (sense->es_add_code == 0x20) {
3632 					/* Fake LUN 0 */
3633 				SF_DEBUG(1, (sf, CE_CONT,
3634 					"!REPORTLUN Faking good "
3635 					"completion for alpa %x\n",
3636 					privp->dest_nport_id));
3637 					ptr->lun_list_len = FCP_LUN_SIZE;
3638 					ptr->lun[0] = 0;
3639 					rsp->fcp_u.fcp_status.scsi_status =
3640 						STATUS_GOOD;
3641 				} else if (sense->es_add_code == 0x25) {
3642 					SF_DEBUG(1, (sf, CE_CONT,
3643 					    "!REPORTLUN device alpa %x "
3644 					    "key %x code %x\n",
3645 					    privp->dest_nport_id,
3646 					    sense->es_key, sense->es_add_code));
3647 					    goto fail;
3648 				}
3649 			} else if (sense->es_key ==
3650 				KEY_UNIT_ATTENTION &&
3651 				sense->es_add_code == 0x29) {
3652 				SF_DEBUG(1, (sf, CE_CONT,
3653 					"!REPORTLUN device alpa %x was reset\n",
3654 					privp->dest_nport_id));
3655 			} else {
3656 				SF_DEBUG(1, (sf, CE_CONT,
3657 					"!REPORTLUN device alpa %x "
3658 					"key %x code %x\n",
3659 					privp->dest_nport_id,
3660 					sense->es_key, sense->es_add_code));
3661 /* XXXXXX The following is here to handle broken targets -- remove it later */
3662 				if (sf_reportlun_forever &&
3663 					sense->es_key == KEY_UNIT_ATTENTION)
3664 					goto retry;
3665 /* XXXXXX */
3666 				if (sense->es_key == KEY_NOT_READY)
3667 					delayed_retry = 1;
3668 				}
3669 		}
3670 
3671 	if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) {
3672 		struct fcp_rsp_info *bep;
3673 
3674 		bep = (struct fcp_rsp_info *)(&rsp->
3675 		    fcp_response_len + 1);
3676 		if (!rsp->fcp_u.fcp_status.rsp_len_set ||
3677 		    bep->rsp_code == FCP_NO_FAILURE) {
3678 			(void) ddi_dma_sync(privp->data_dma_handle,
3679 			    0, 0, DDI_DMA_SYNC_FORKERNEL);
3680 
3681 			/* Convert from #bytes to #ints */
3682 			ptr->lun_list_len = ptr->lun_list_len >> 3;
3683 			SF_DEBUG(2, (sf, CE_CONT,
3684 			    "!REPORTLUN to al_pa %x succeeded: %d LUNs\n",
3685 			    privp->dest_nport_id, ptr->lun_list_len));
3686 			if (!ptr->lun_list_len) {
3687 				/* No LUNs? Ya gotta be kidding... */
3688 				sf_log(sf, CE_WARN,
3689 				    "SCSI violation -- "
3690 				    "target 0x%x reports no LUNs\n",
3691 				    sf_alpa_to_switch[
3692 				    privp->dest_nport_id]);
3693 				ptr->lun_list_len = 1;
3694 				ptr->lun[0] = 0;
3695 			}
3696 
3697 			mutex_enter(&sf->sf_mutex);
3698 			if (sf->sf_lip_cnt == privp->lip_cnt) {
3699 				sf->sf_device_count += ptr->lun_list_len - 1;
3700 			}
3701 
3702 			mutex_exit(&sf->sf_mutex);
3703 			for (i = 0; i < ptr->lun_list_len && privp->lip_cnt ==
3704 			    sf->sf_lip_cnt; i++) {
3705 				struct sf_els_hdr *nprivp;
3706 				struct fcal_packet *nfpkt;
3707 
3708 				/* LUN 0 is already in `target' */
3709 				if (ptr->lun[i] != 0) {
3710 					target = sf_create_target(sf,
3711 					    privp, tid, ptr->lun[i]);
3712 				}
3713 				nprivp = NULL;
3714 				nfpkt = NULL;
3715 				if (target) {
3716 					nfpkt = sf_els_alloc(sf,
3717 					    target->sft_al_pa,
3718 					    sizeof (struct sf_els_hdr),
3719 					    sizeof (union sf_els_cmd),
3720 					    sizeof (union sf_els_rsp),
3721 					    (caddr_t *)&nprivp,
3722 					    (caddr_t *)&rsp);
3723 					if (nprivp)
3724 						nprivp->lip_cnt =
3725 						    privp->lip_cnt;
3726 				}
3727 				if (nfpkt && nprivp &&
3728 				    (sf_do_inquiry(sf, nprivp, target) ==
3729 				    0)) {
3730 					mutex_enter(&sf->sf_mutex);
3731 					if (sf->sf_lip_cnt == privp->
3732 					    lip_cnt) {
3733 						sf->sf_device_count --;
3734 					}
3735 					sf_offline_target(sf, target);
3736 					mutex_exit(&sf->sf_mutex);
3737 				}
3738 			}
3739 			sf_els_free(fpkt);
3740 			return;
3741 		} else {
3742 			SF_DEBUG(1, (sf, CE_CONT,
3743 			    "!REPORTLUN al_pa %x fcp failure, "
3744 			    "fcp_rsp_code %x scsi status %x\n",
3745 			    privp->dest_nport_id, bep->rsp_code,
3746 			    rsp ? rsp->fcp_u.fcp_status.scsi_status:0));
3747 			goto fail;
3748 		}
3749 	}
3750 	if (rsp && ((rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) ||
3751 	    (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL))) {
3752 		delayed_retry = 1;
3753 	}
3754 
3755 	if (++(privp->retries) < sf_els_retries ||
3756 	    (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
3757 /* XXXXXX The following is here to handle broken targets -- remove it later */
3758 retry:
3759 /* XXXXXX */
3760 		if (delayed_retry) {
3761 			privp->retries--;
3762 			privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
3763 			privp->delayed_retry = 1;
3764 		} else {
3765 			privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3766 		}
3767 
3768 		privp->prev = NULL;
3769 		mutex_enter(&sf->sf_mutex);
3770 		if (privp->lip_cnt == sf->sf_lip_cnt) {
3771 			if (!delayed_retry)
3772 				SF_DEBUG(1, (sf, CE_WARN,
3773 				    "!REPORTLUN to al_pa %x failed, retrying\n",
3774 				    privp->dest_nport_id));
3775 			privp->next = sf->sf_els_list;
3776 			if (sf->sf_els_list != NULL)
3777 				sf->sf_els_list->prev = privp;
3778 			sf->sf_els_list = privp;
3779 			mutex_exit(&sf->sf_mutex);
3780 			if (!delayed_retry && soc_transport(sf->sf_sochandle,
3781 			    fpkt, FCAL_NOSLEEP, CQ_REQUEST_1) !=
3782 			    FCAL_TRANSPORT_SUCCESS) {
3783 				mutex_enter(&sf->sf_mutex);
3784 				if (privp->prev)
3785 					privp->prev->next = privp->next;
3786 				if (privp->next)
3787 					privp->next->prev = privp->prev;
3788 				if (sf->sf_els_list == privp)
3789 					sf->sf_els_list = privp->next;
3790 				mutex_exit(&sf->sf_mutex);
3791 				goto fail;
3792 			} else
3793 				return;
3794 		} else {
3795 			mutex_exit(&sf->sf_mutex);
3796 		}
3797 	} else {
3798 fail:
3799 
3800 		/* REPORT_LUN failed -- try inquiry */
3801 		if (sf_do_inquiry(sf, privp, target) != 0) {
3802 			return;
3803 		} else {
3804 			free_pkt = 0;
3805 		}
3806 		mutex_enter(&sf->sf_mutex);
3807 		if (sf->sf_lip_cnt == privp->lip_cnt) {
3808 			sf_log(sf, CE_WARN,
3809 			    "!REPORTLUN to target 0x%x failed\n",
3810 			    sf_alpa_to_switch[privp->dest_nport_id]);
3811 			sf_offline_target(sf, target);
3812 			sf->sf_device_count--;
3813 			ASSERT(sf->sf_device_count >= 0);
3814 			if (sf->sf_device_count == 0)
3815 			sf_finish_init(sf, privp->lip_cnt);
3816 		}
3817 		mutex_exit(&sf->sf_mutex);
3818 	}
3819 	if (free_pkt) {
3820 		sf_els_free(fpkt);
3821 	}
3822 }
3823 
3824 static int
sf_do_inquiry(struct sf * sf,struct sf_els_hdr * privp,struct sf_target * target)3825 sf_do_inquiry(struct sf *sf, struct sf_els_hdr *privp,
3826     struct sf_target *target)
3827 {
3828 	struct	fcal_packet	*fpkt = privp->fpkt;
3829 	ddi_dma_cookie_t	pcookie;
3830 	ddi_dma_handle_t	inq_dma_handle = NULL;
3831 	ddi_acc_handle_t	inq_acc_handle;
3832 	uint_t			ccount;
3833 	size_t			real_size;
3834 	caddr_t			inq_buf = NULL;
3835 	int			handle_bound = FALSE;
3836 	fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3837 	struct fcp_cmd		*inq = (struct fcp_cmd *)privp->cmd;
3838 	char			*msg = "Transport";
3839 
3840 
3841 	if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3842 	    DDI_DMA_DONTWAIT, NULL, &inq_dma_handle) != DDI_SUCCESS) {
3843 		msg = "ddi_dma_alloc_handle()";
3844 		goto fail;
3845 	}
3846 
3847 	if (ddi_dma_mem_alloc(inq_dma_handle, SUN_INQSIZE,
3848 	    sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3849 	    DDI_DMA_DONTWAIT, NULL, &inq_buf,
3850 	    &real_size, &inq_acc_handle) != DDI_SUCCESS) {
3851 		msg = "ddi_dma_mem_alloc()";
3852 		goto fail;
3853 	}
3854 
3855 	if (real_size < SUN_INQSIZE) {
3856 		msg = "DMA mem < inquiry size";
3857 		goto fail;
3858 	}
3859 
3860 	if (ddi_dma_addr_bind_handle(inq_dma_handle, NULL,
3861 	    inq_buf, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3862 	    DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3863 		msg = "ddi_dma_addr_bind_handle()";
3864 		goto fail;
3865 	}
3866 	handle_bound = TRUE;
3867 
3868 	if (ccount != 1) {
3869 		msg = "ccount != 1";
3870 		goto fail;
3871 	}
3872 	privp->els_code = 0;			/* not an ELS command */
3873 	privp->target = target;
3874 	privp->data_dma_handle = inq_dma_handle;
3875 	privp->data_acc_handle = inq_acc_handle;
3876 	privp->data_buf = inq_buf;
3877 	fpkt->fcal_pkt_comp = sf_inq_callback;
3878 	fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3879 	fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3880 	fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3881 	    sizeof (struct fcp_cmd);
3882 	fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3883 	    (uint32_t)pcookie.dmac_address;
3884 	fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3885 	fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3886 	hp->r_ctl = R_CTL_COMMAND;
3887 	hp->type = TYPE_SCSI_FCP;
3888 	bzero((caddr_t)inq, sizeof (struct fcp_cmd));
3889 	((union scsi_cdb *)inq->fcp_cdb)->scc_cmd = SCMD_INQUIRY;
3890 	((union scsi_cdb *)inq->fcp_cdb)->g0_count0 = SUN_INQSIZE;
3891 	bcopy((caddr_t)&target->sft_lun.b, (caddr_t)&inq->fcp_ent_addr,
3892 	    FCP_LUN_SIZE);
3893 	inq->fcp_cntl.cntl_read_data = 1;
3894 	inq->fcp_cntl.cntl_write_data = 0;
3895 	inq->fcp_data_len = pcookie.dmac_size;
3896 	inq->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3897 
3898 	(void) ddi_dma_sync(inq_dma_handle, (off_t)0, (size_t)0,
3899 	    DDI_DMA_SYNC_FORDEV);
3900 	privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3901 	SF_DEBUG(5, (sf, CE_WARN,
3902 	    "!Sending INQUIRY to al_pa %x lun %" PRIx64 "\n",
3903 	    privp->dest_nport_id,
3904 	    SCSA_LUN(target)));
3905 	return (sf_els_transport(sf, privp));
3906 
3907 fail:
3908 	sf_log(sf, CE_WARN,
3909 	    "%s failure for INQUIRY to target 0x%x\n",
3910 	    msg, sf_alpa_to_switch[privp->dest_nport_id]);
3911 	sf_els_free(fpkt);
3912 	if (inq_dma_handle != NULL) {
3913 		if (handle_bound) {
3914 			(void) ddi_dma_unbind_handle(inq_dma_handle);
3915 		}
3916 		ddi_dma_free_handle(&inq_dma_handle);
3917 	}
3918 	if (inq_buf != NULL) {
3919 		ddi_dma_mem_free(&inq_acc_handle);
3920 	}
3921 	return (FALSE);
3922 }
3923 
3924 
3925 /*
3926  * called as the pkt_comp routine for INQ packets
3927  */
3928 static void
sf_inq_callback(struct fcal_packet * fpkt)3929 sf_inq_callback(struct fcal_packet *fpkt)
3930 {
3931 	struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3932 	    fcal_pkt_private;
3933 	struct scsi_inquiry *prt = (struct scsi_inquiry *)privp->data_buf;
3934 	struct sf *sf = privp->sf;
3935 	struct sf *tsf;
3936 	struct sf_target *target = privp->target;
3937 	struct fcp_rsp *rsp;
3938 	int delayed_retry = FALSE;
3939 	short	ncmds;
3940 
3941 
3942 	mutex_enter(&sf->sf_mutex);
3943 	/* use as temporary state variable */
3944 	if (privp->timeout == SF_INVALID_TIMEOUT) {
3945 		mutex_exit(&sf->sf_mutex);
3946 		return;
3947 	}
3948 	if (privp->prev != NULL) {
3949 		privp->prev->next = privp->next;
3950 	}
3951 	if (privp->next != NULL) {
3952 		privp->next->prev = privp->prev;
3953 	}
3954 	if (sf->sf_els_list == privp) {
3955 		sf->sf_els_list = privp->next;
3956 	}
3957 	privp->prev = privp->next = NULL;
3958 	mutex_exit(&sf->sf_mutex);
3959 	ncmds = fpkt->fcal_ncmds;
3960 	ASSERT(ncmds >= 0);
3961 	mutex_enter(&sf->sf_cmd_mutex);
3962 	sf->sf_ncmds = ncmds;
3963 	mutex_exit(&sf->sf_cmd_mutex);
3964 
3965 	if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3966 
3967 		(void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0,
3968 		    (size_t)0, DDI_DMA_SYNC_FORKERNEL);
3969 
3970 		rsp = (struct fcp_rsp *)privp->rsp;
3971 		SF_DEBUG(2, (sf, CE_CONT,
3972 		    "!INQUIRY to al_pa %x scsi status %x",
3973 		    privp->dest_nport_id, rsp->fcp_u.fcp_status.scsi_status));
3974 
3975 		if ((rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) &&
3976 		    !rsp->fcp_u.fcp_status.resid_over &&
3977 		    (!rsp->fcp_u.fcp_status.resid_under ||
3978 		    ((SUN_INQSIZE - rsp->fcp_resid) >= SUN_MIN_INQLEN))) {
3979 			struct fcp_rsp_info *bep;
3980 
3981 			bep = (struct fcp_rsp_info *)(&rsp->
3982 			    fcp_response_len + 1);
3983 
3984 			if (!rsp->fcp_u.fcp_status.rsp_len_set ||
3985 			    (bep->rsp_code == FCP_NO_FAILURE)) {
3986 
3987 				SF_DEBUG(2, (sf, CE_CONT,
3988 				    "!INQUIRY to al_pa %x lun %" PRIx64
3989 				    " succeeded\n",
3990 				    privp->dest_nport_id, SCSA_LUN(target)));
3991 
3992 				(void) ddi_dma_sync(privp->data_dma_handle,
3993 				    (off_t)0, (size_t)0,
3994 				    DDI_DMA_SYNC_FORKERNEL);
3995 
3996 				mutex_enter(&sf->sf_mutex);
3997 
3998 				if (sf->sf_lip_cnt == privp->lip_cnt) {
3999 					mutex_enter(&target->sft_mutex);
4000 					target->sft_device_type =
4001 					    prt->inq_dtype;
4002 					bcopy(prt, &target->sft_inq,
4003 					    sizeof (*prt));
4004 					mutex_exit(&target->sft_mutex);
4005 					sf->sf_device_count--;
4006 					ASSERT(sf->sf_device_count >= 0);
4007 					if (sf->sf_device_count == 0) {
4008 						sf_finish_init(sf,
4009 						    privp->lip_cnt);
4010 					}
4011 				}
4012 				mutex_exit(&sf->sf_mutex);
4013 				sf_els_free(fpkt);
4014 				return;
4015 			}
4016 		} else if ((rsp->fcp_u.fcp_status.scsi_status ==
4017 		    STATUS_BUSY) ||
4018 		    (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL) ||
4019 		    (rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK)) {
4020 			delayed_retry = TRUE;
4021 		}
4022 	} else {
4023 		SF_DEBUG(2, (sf, CE_CONT, "!INQUIRY to al_pa %x fc status %x",
4024 		    privp->dest_nport_id, fpkt->fcal_pkt_status));
4025 	}
4026 
4027 	if (++(privp->retries) < sf_els_retries ||
4028 	    (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
4029 		if (fpkt->fcal_pkt_status == FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
4030 			tsf = sf->sf_sibling;
4031 			if (tsf != NULL) {
4032 				mutex_enter(&tsf->sf_cmd_mutex);
4033 				tsf->sf_flag = 1;
4034 				tsf->sf_throttle = SF_DECR_DELTA;
4035 				mutex_exit(&tsf->sf_cmd_mutex);
4036 			}
4037 			delayed_retry = 1;
4038 		}
4039 		if (delayed_retry) {
4040 			privp->retries--;
4041 			privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
4042 			privp->delayed_retry = TRUE;
4043 		} else {
4044 			privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
4045 		}
4046 
4047 		privp->prev = NULL;
4048 		mutex_enter(&sf->sf_mutex);
4049 		if (privp->lip_cnt == sf->sf_lip_cnt) {
4050 			if (!delayed_retry) {
4051 				SF_DEBUG(1, (sf, CE_WARN,
4052 				    "INQUIRY to al_pa %x failed, retrying",
4053 				    privp->dest_nport_id));
4054 			}
4055 			privp->next = sf->sf_els_list;
4056 			if (sf->sf_els_list != NULL) {
4057 				sf->sf_els_list->prev = privp;
4058 			}
4059 			sf->sf_els_list = privp;
4060 			mutex_exit(&sf->sf_mutex);
4061 			/* if not delayed call transport to send a pkt */
4062 			if (!delayed_retry &&
4063 			    (soc_transport(sf->sf_sochandle, fpkt,
4064 			    FCAL_NOSLEEP, CQ_REQUEST_1) !=
4065 			    FCAL_TRANSPORT_SUCCESS)) {
4066 				mutex_enter(&sf->sf_mutex);
4067 				if (privp->prev != NULL) {
4068 					privp->prev->next = privp->next;
4069 				}
4070 				if (privp->next != NULL) {
4071 					privp->next->prev = privp->prev;
4072 				}
4073 				if (sf->sf_els_list == privp) {
4074 					sf->sf_els_list = privp->next;
4075 				}
4076 				mutex_exit(&sf->sf_mutex);
4077 				goto fail;
4078 			}
4079 			return;
4080 		}
4081 		mutex_exit(&sf->sf_mutex);
4082 	} else {
4083 fail:
4084 		mutex_enter(&sf->sf_mutex);
4085 		if (sf->sf_lip_cnt == privp->lip_cnt) {
4086 			sf_offline_target(sf, target);
4087 			sf_log(sf, CE_NOTE,
4088 			    "INQUIRY to target 0x%x lun %" PRIx64 " failed. "
4089 			    "Retry Count: %d\n",
4090 			    sf_alpa_to_switch[privp->dest_nport_id],
4091 			    SCSA_LUN(target),
4092 			    privp->retries);
4093 			sf->sf_device_count--;
4094 			ASSERT(sf->sf_device_count >= 0);
4095 			if (sf->sf_device_count == 0) {
4096 				sf_finish_init(sf, privp->lip_cnt);
4097 			}
4098 		}
4099 		mutex_exit(&sf->sf_mutex);
4100 	}
4101 	sf_els_free(fpkt);
4102 }
4103 
4104 
4105 static void
sf_finish_init(struct sf * sf,int lip_cnt)4106 sf_finish_init(struct sf *sf, int lip_cnt)
4107 {
4108 	int			i;		/* loop index */
4109 	int			cflag;
4110 	struct sf_target	*target;	/* current target */
4111 	dev_info_t		*dip;
4112 	struct sf_hp_elem	*elem;		/* hotplug element created */
4113 
4114 	SF_DEBUG(1, (sf, CE_WARN, "!sf_finish_init\n"));
4115 	ASSERT(mutex_owned(&sf->sf_mutex));
4116 
4117 	/* scan all hash queues */
4118 	for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
4119 		target = sf->sf_wwn_lists[i];
4120 		while (target != NULL) {
4121 			mutex_enter(&target->sft_mutex);
4122 
4123 			/* see if target is not offline */
4124 			if ((target->sft_state & SF_TARGET_OFFLINE)) {
4125 				/*
4126 				 * target already offline
4127 				 */
4128 				mutex_exit(&target->sft_mutex);
4129 				goto next_entry;
4130 			}
4131 
4132 			/*
4133 			 * target is not already offline -- see if it has
4134 			 * already been marked as ready to go offline
4135 			 */
4136 			if (target->sft_state & SF_TARGET_MARK) {
4137 				/*
4138 				 * target already marked, so take it offline
4139 				 */
4140 				mutex_exit(&target->sft_mutex);
4141 				sf_offline_target(sf, target);
4142 				goto next_entry;
4143 			}
4144 
4145 			/* clear target busy flag */
4146 			target->sft_state &= ~SF_TARGET_BUSY;
4147 
4148 			/* is target init not yet done ?? */
4149 			cflag = !(target->sft_state & SF_TARGET_INIT_DONE);
4150 
4151 			/* get pointer to target dip */
4152 			dip = target->sft_dip;
4153 
4154 			mutex_exit(&target->sft_mutex);
4155 			mutex_exit(&sf->sf_mutex);
4156 
4157 			if (cflag && (dip == NULL)) {
4158 				/*
4159 				 * target init not yet done &&
4160 				 * devinfo not yet created
4161 				 */
4162 				sf_create_devinfo(sf, target, lip_cnt);
4163 				mutex_enter(&sf->sf_mutex);
4164 				goto next_entry;
4165 			}
4166 
4167 			/*
4168 			 * target init already done || devinfo already created
4169 			 */
4170 			ASSERT(dip != NULL);
4171 			if (!sf_create_props(dip, target, lip_cnt)) {
4172 				/* a problem creating properties */
4173 				mutex_enter(&sf->sf_mutex);
4174 				goto next_entry;
4175 			}
4176 
4177 			/* create a new element for the hotplug list */
4178 			if ((elem = kmem_zalloc(sizeof (struct sf_hp_elem),
4179 			    KM_NOSLEEP)) != NULL) {
4180 
4181 				/* fill in the new element */
4182 				elem->dip = dip;
4183 				elem->target = target;
4184 				elem->what = SF_ONLINE;
4185 
4186 				/* add the new element into the hotplug list */
4187 				mutex_enter(&sf->sf_hp_daemon_mutex);
4188 				if (sf->sf_hp_elem_tail != NULL) {
4189 					sf->sf_hp_elem_tail->next = elem;
4190 					sf->sf_hp_elem_tail = elem;
4191 				} else {
4192 					/* this is the first element in list */
4193 					sf->sf_hp_elem_head =
4194 					    sf->sf_hp_elem_tail =
4195 					    elem;
4196 				}
4197 				cv_signal(&sf->sf_hp_daemon_cv);
4198 				mutex_exit(&sf->sf_hp_daemon_mutex);
4199 			} else {
4200 				/* could not allocate memory for element ?? */
4201 				(void) ndi_devi_online_async(dip, 0);
4202 			}
4203 
4204 			mutex_enter(&sf->sf_mutex);
4205 
4206 next_entry:
4207 			/* ensure no new LIPs have occurred */
4208 			if (sf->sf_lip_cnt != lip_cnt) {
4209 				return;
4210 			}
4211 			target = target->sft_next;
4212 		}
4213 
4214 		/* done scanning all targets in this queue */
4215 	}
4216 
4217 	/* done with all hash queues */
4218 
4219 	sf->sf_state = SF_STATE_ONLINE;
4220 	sf->sf_online_timer = 0;
4221 }
4222 
4223 
4224 /*
4225  * create devinfo node
4226  */
4227 static void
sf_create_devinfo(struct sf * sf,struct sf_target * target,int lip_cnt)4228 sf_create_devinfo(struct sf *sf, struct sf_target *target, int lip_cnt)
4229 {
4230 	dev_info_t		*cdip = NULL;
4231 	char			*nname = NULL;
4232 	char			**compatible = NULL;
4233 	int			ncompatible;
4234 	struct scsi_inquiry	*inq = &target->sft_inq;
4235 	char			*scsi_binding_set;
4236 
4237 	/* get the 'scsi-binding-set' property */
4238 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, sf->sf_dip,
4239 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
4240 	    &scsi_binding_set) != DDI_PROP_SUCCESS)
4241 		scsi_binding_set = NULL;
4242 
4243 	/* determine the node name and compatible */
4244 	scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
4245 	    inq->inq_dtype, NULL, &nname, &compatible, &ncompatible);
4246 	if (scsi_binding_set)
4247 		ddi_prop_free(scsi_binding_set);
4248 
4249 	/* if nodename can't be determined then print a message and skip it */
4250 	if (nname == NULL) {
4251 #ifndef	RAID_LUNS
4252 		sf_log(sf, CE_WARN, "%s%d: no driver for device "
4253 		    "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
4254 		    "    compatible: %s",
4255 		    ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
4256 		    target->sft_port_wwn[0], target->sft_port_wwn[1],
4257 		    target->sft_port_wwn[2], target->sft_port_wwn[3],
4258 		    target->sft_port_wwn[4], target->sft_port_wwn[5],
4259 		    target->sft_port_wwn[6], target->sft_port_wwn[7],
4260 		    target->sft_lun.l, *compatible);
4261 #else
4262 		sf_log(sf, CE_WARN, "%s%d: no driver for device "
4263 		    "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
4264 		    "    compatible: %s",
4265 		    ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
4266 		    target->sft_port_wwn[0], target->sft_port_wwn[1],
4267 		    target->sft_port_wwn[2], target->sft_port_wwn[3],
4268 		    target->sft_port_wwn[4], target->sft_port_wwn[5],
4269 		    target->sft_port_wwn[6], target->sft_port_wwn[7],
4270 		    target->sft_raid_lun, *compatible);
4271 #endif
4272 		goto fail;
4273 	}
4274 
4275 	/* allocate the node */
4276 	if (ndi_devi_alloc(sf->sf_dip, nname,
4277 	    DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
4278 		goto fail;
4279 	}
4280 
4281 	/* decorate the node with compatible */
4282 	if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
4283 	    "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
4284 		goto fail;
4285 	}
4286 
4287 	/* add addressing properties to the node */
4288 	if (sf_create_props(cdip, target, lip_cnt) != 1) {
4289 		goto fail;
4290 	}
4291 
4292 	mutex_enter(&target->sft_mutex);
4293 	if (target->sft_dip != NULL) {
4294 		mutex_exit(&target->sft_mutex);
4295 		goto fail;
4296 	}
4297 	target->sft_dip = cdip;
4298 	mutex_exit(&target->sft_mutex);
4299 
4300 	if (ndi_devi_online_async(cdip, 0) != DDI_SUCCESS) {
4301 		goto fail;
4302 	}
4303 
4304 	scsi_hba_nodename_compatible_free(nname, compatible);
4305 	return;
4306 
4307 fail:
4308 	scsi_hba_nodename_compatible_free(nname, compatible);
4309 	if (cdip != NULL) {
4310 		(void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP);
4311 		(void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP);
4312 		(void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LIP_CNT_PROP);
4313 		(void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, TARGET_PROP);
4314 		(void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LUN_PROP);
4315 		if (ndi_devi_free(cdip) != NDI_SUCCESS) {
4316 			sf_log(sf, CE_WARN, "ndi_devi_free failed\n");
4317 		} else {
4318 			mutex_enter(&target->sft_mutex);
4319 			if (cdip == target->sft_dip) {
4320 				target->sft_dip = NULL;
4321 			}
4322 			mutex_exit(&target->sft_mutex);
4323 		}
4324 	}
4325 }
4326 
4327 /*
4328  * create required properties, returning TRUE iff we succeed, else
4329  * returning FALSE
4330  */
4331 static int
sf_create_props(dev_info_t * cdip,struct sf_target * target,int lip_cnt)4332 sf_create_props(dev_info_t *cdip, struct sf_target *target, int lip_cnt)
4333 {
4334 	int tgt_id = sf_alpa_to_switch[target->sft_al_pa];
4335 
4336 
4337 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
4338 	    cdip, NODE_WWN_PROP, target->sft_node_wwn, FC_WWN_SIZE) !=
4339 	    DDI_PROP_SUCCESS) {
4340 		return (FALSE);
4341 	}
4342 
4343 	if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
4344 	    cdip, PORT_WWN_PROP, target->sft_port_wwn, FC_WWN_SIZE) !=
4345 	    DDI_PROP_SUCCESS) {
4346 		return (FALSE);
4347 	}
4348 
4349 	if (ndi_prop_update_int(DDI_DEV_T_NONE,
4350 	    cdip, LIP_CNT_PROP, lip_cnt) != DDI_PROP_SUCCESS) {
4351 		return (FALSE);
4352 	}
4353 
4354 	if (ndi_prop_update_int(DDI_DEV_T_NONE,
4355 	    cdip, TARGET_PROP, tgt_id) != DDI_PROP_SUCCESS) {
4356 		return (FALSE);
4357 	}
4358 
4359 #ifndef	RAID_LUNS
4360 	if (ndi_prop_update_int(DDI_DEV_T_NONE,
4361 	    cdip, LUN_PROP, target->sft_lun.l) != DDI_PROP_SUCCESS) {
4362 		return (0);
4363 	}
4364 #else
4365 	if (ndi_prop_update_int(DDI_DEV_T_NONE,
4366 	    cdip, LUN_PROP, target->sft_raid_lun) != DDI_PROP_SUCCESS) {
4367 		return (0);
4368 	}
4369 #endif
4370 
4371 	return (TRUE);
4372 }
4373 
4374 
4375 /*
4376  * called by the transport to offline a target
4377  */
4378 /* ARGSUSED */
4379 static void
sf_offline_target(struct sf * sf,struct sf_target * target)4380 sf_offline_target(struct sf *sf, struct sf_target *target)
4381 {
4382 	dev_info_t *dip;
4383 	struct sf_target *next_target = NULL;
4384 	struct sf_hp_elem	*elem;
4385 
4386 	ASSERT(mutex_owned(&sf->sf_mutex));
4387 
4388 	if (sf_core && (sf_core & SF_CORE_OFFLINE_TARGET)) {
4389 		(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
4390 		sf_core = 0;
4391 	}
4392 
4393 	while (target != NULL) {
4394 		sf_log(sf, CE_NOTE,
4395 		    "!target 0x%x al_pa 0x%x lun %" PRIx64 " offlined\n",
4396 		    sf_alpa_to_switch[target->sft_al_pa],
4397 		    target->sft_al_pa, SCSA_LUN(target));
4398 		mutex_enter(&target->sft_mutex);
4399 		target->sft_state &= ~(SF_TARGET_BUSY|SF_TARGET_MARK);
4400 		target->sft_state |= SF_TARGET_OFFLINE;
4401 		mutex_exit(&target->sft_mutex);
4402 		mutex_exit(&sf->sf_mutex);
4403 
4404 		/* XXXX if this is LUN 0, offline all other LUNs */
4405 		if (next_target || target->sft_lun.l == 0)
4406 			next_target = target->sft_next_lun;
4407 
4408 		/* abort all cmds for this target */
4409 		sf_abort_all(sf, target, FALSE, sf->sf_lip_cnt, FALSE);
4410 
4411 		mutex_enter(&sf->sf_mutex);
4412 		mutex_enter(&target->sft_mutex);
4413 		if (target->sft_state & SF_TARGET_INIT_DONE) {
4414 			dip = target->sft_dip;
4415 			mutex_exit(&target->sft_mutex);
4416 			mutex_exit(&sf->sf_mutex);
4417 			(void) ndi_prop_remove(DDI_DEV_T_NONE, dip,
4418 			    TARGET_PROP);
4419 			(void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
4420 			    dip, FCAL_REMOVE_EVENT, &sf_remove_eid,
4421 			    NDI_EVENT_NOPASS);
4422 			(void) ndi_event_run_callbacks(sf->sf_event_hdl,
4423 			    target->sft_dip, sf_remove_eid, NULL);
4424 
4425 			elem = kmem_zalloc(sizeof (struct sf_hp_elem),
4426 			    KM_NOSLEEP);
4427 			if (elem != NULL) {
4428 				elem->dip = dip;
4429 				elem->target = target;
4430 				elem->what = SF_OFFLINE;
4431 				mutex_enter(&sf->sf_hp_daemon_mutex);
4432 				if (sf->sf_hp_elem_tail != NULL) {
4433 					sf->sf_hp_elem_tail->next = elem;
4434 					sf->sf_hp_elem_tail = elem;
4435 				} else {
4436 					sf->sf_hp_elem_head =
4437 					    sf->sf_hp_elem_tail =
4438 					    elem;
4439 				}
4440 				cv_signal(&sf->sf_hp_daemon_cv);
4441 				mutex_exit(&sf->sf_hp_daemon_mutex);
4442 			} else {
4443 				/* don't do NDI_DEVI_REMOVE for now */
4444 				if (ndi_devi_offline(dip, 0) != NDI_SUCCESS) {
4445 					SF_DEBUG(1, (sf, CE_WARN,
4446 					    "target %x lun %" PRIx64 ", "
4447 					    "device offline failed",
4448 					    sf_alpa_to_switch[target->
4449 					    sft_al_pa],
4450 					    SCSA_LUN(target)));
4451 				} else {
4452 					SF_DEBUG(1, (sf, CE_NOTE,
4453 					    "target %x, lun %" PRIx64 ", "
4454 					    "device offline succeeded\n",
4455 					    sf_alpa_to_switch[target->
4456 					    sft_al_pa],
4457 					    SCSA_LUN(target)));
4458 				}
4459 			}
4460 			mutex_enter(&sf->sf_mutex);
4461 		} else {
4462 			mutex_exit(&target->sft_mutex);
4463 		}
4464 		target = next_target;
4465 	}
4466 }
4467 
4468 
4469 /*
4470  * routine to get/set a capability
4471  *
4472  * returning:
4473  *	1 (TRUE)	boolean capability is true (on get)
4474  *	0 (FALSE)	invalid capability, can't set capability (on set),
4475  *			or boolean capability is false (on get)
4476  *	-1 (UNDEFINED)	can't find capability (SCSA) or unsupported capability
4477  *	3		when getting SCSI version number
4478  *	AL_PA		when getting port initiator ID
4479  */
4480 static int
sf_commoncap(struct scsi_address * ap,char * cap,int val,int tgtonly,int doset)4481 sf_commoncap(struct scsi_address *ap, char *cap,
4482     int val, int tgtonly, int doset)
4483 {
4484 	struct sf *sf = ADDR2SF(ap);
4485 	int cidx;
4486 	int rval = FALSE;
4487 
4488 
4489 	if (cap == NULL) {
4490 		SF_DEBUG(3, (sf, CE_WARN, "sf_commoncap: invalid arg"));
4491 		return (rval);
4492 	}
4493 
4494 	/* get index of capability string */
4495 	if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
4496 		/* can't find capability */
4497 		return (UNDEFINED);
4498 	}
4499 
4500 	if (doset) {
4501 		/*
4502 		 * Process setcap request.
4503 		 */
4504 
4505 		/*
4506 		 * At present, we can only set binary (0/1) values
4507 		 */
4508 		switch (cidx) {
4509 		case SCSI_CAP_ARQ:	/* can't set this capability */
4510 			break;
4511 		default:
4512 			SF_DEBUG(3, (sf, CE_WARN,
4513 			    "sf_setcap: unsupported %d", cidx));
4514 			rval = UNDEFINED;
4515 			break;
4516 		}
4517 
4518 		SF_DEBUG(4, (sf, CE_NOTE,
4519 		    "set cap: cap=%s,val=0x%x,tgtonly=0x%x"
4520 		    ",doset=0x%x,rval=%d\n",
4521 		    cap, val, tgtonly, doset, rval));
4522 
4523 	} else {
4524 		/*
4525 		 * Process getcap request.
4526 		 */
4527 		switch (cidx) {
4528 		case SCSI_CAP_DMA_MAX:
4529 			break;		/* don't' have this capability */
4530 		case SCSI_CAP_INITIATOR_ID:
4531 			rval = sf->sf_al_pa;
4532 			break;
4533 		case SCSI_CAP_ARQ:
4534 			rval = TRUE;	/* do have this capability */
4535 			break;
4536 		case SCSI_CAP_RESET_NOTIFICATION:
4537 		case SCSI_CAP_TAGGED_QING:
4538 			rval = TRUE;	/* do have this capability */
4539 			break;
4540 		case SCSI_CAP_SCSI_VERSION:
4541 			rval = 3;
4542 			break;
4543 		case SCSI_CAP_INTERCONNECT_TYPE:
4544 			rval = INTERCONNECT_FIBRE;
4545 			break;
4546 		default:
4547 			SF_DEBUG(4, (sf, CE_WARN,
4548 			    "sf_scsi_getcap: unsupported"));
4549 			rval = UNDEFINED;
4550 			break;
4551 		}
4552 		SF_DEBUG(4, (sf, CE_NOTE,
4553 		    "get cap: cap=%s,val=0x%x,tgtonly=0x%x,"
4554 		    "doset=0x%x,rval=%d\n",
4555 		    cap, val, tgtonly, doset, rval));
4556 	}
4557 
4558 	return (rval);
4559 }
4560 
4561 
4562 /*
4563  * called by the transport to get a capability
4564  */
4565 static int
sf_getcap(struct scsi_address * ap,char * cap,int whom)4566 sf_getcap(struct scsi_address *ap, char *cap, int whom)
4567 {
4568 	return (sf_commoncap(ap, cap, 0, whom, FALSE));
4569 }
4570 
4571 
4572 /*
4573  * called by the transport to set a capability
4574  */
4575 static int
sf_setcap(struct scsi_address * ap,char * cap,int value,int whom)4576 sf_setcap(struct scsi_address *ap, char *cap, int value, int whom)
4577 {
4578 	return (sf_commoncap(ap, cap, value, whom, TRUE));
4579 }
4580 
4581 
4582 /*
4583  * called by the transport to abort a target
4584  */
4585 static int
sf_abort(struct scsi_address * ap,struct scsi_pkt * pkt)4586 sf_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
4587 {
4588 	struct sf *sf = ADDR2SF(ap);
4589 	struct sf_target *target = ADDR2TARGET(ap);
4590 	struct sf_pkt *cmd, *ncmd, *pcmd;
4591 	struct fcal_packet *fpkt;
4592 	int	rval = 0, t, my_rval = FALSE;
4593 	int	old_target_state;
4594 	int	lip_cnt;
4595 	int	tgt_id;
4596 	fc_frame_header_t	*hp;
4597 	int	deferred_destroy;
4598 
4599 	deferred_destroy = 0;
4600 
4601 	if (pkt != NULL) {
4602 		cmd = PKT2CMD(pkt);
4603 		fpkt = cmd->cmd_fp_pkt;
4604 		SF_DEBUG(2, (sf, CE_NOTE, "sf_abort packet %p\n",
4605 		    (void *)fpkt));
4606 		pcmd = NULL;
4607 		mutex_enter(&sf->sf_cmd_mutex);
4608 		ncmd = sf->sf_pkt_head;
4609 		while (ncmd != NULL) {
4610 			if (ncmd == cmd) {
4611 				if (pcmd != NULL) {
4612 					pcmd->cmd_next = cmd->cmd_next;
4613 				} else {
4614 					sf->sf_pkt_head = cmd->cmd_next;
4615 				}
4616 				cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
4617 				cmd->cmd_state = SF_STATE_IDLE;
4618 				pkt->pkt_reason = CMD_ABORTED;
4619 				pkt->pkt_statistics |= STAT_ABORTED;
4620 				my_rval = TRUE;
4621 				break;
4622 			} else {
4623 				pcmd = ncmd;
4624 				ncmd = ncmd->cmd_next;
4625 			}
4626 		}
4627 		mutex_exit(&sf->sf_cmd_mutex);
4628 		if (ncmd == NULL) {
4629 			mutex_enter(&cmd->cmd_abort_mutex);
4630 			if (cmd->cmd_state == SF_STATE_ISSUED) {
4631 				cmd->cmd_state = SF_STATE_ABORTING;
4632 				cmd->cmd_timeout = sf_watchdog_time + 20;
4633 				mutex_exit(&cmd->cmd_abort_mutex);
4634 				/* call transport to abort command */
4635 				if (((rval = soc_abort(sf->sf_sochandle,
4636 				    sf->sf_socp, sf->sf_sochandle->fcal_portno,
4637 				    fpkt, 1)) == FCAL_ABORTED) ||
4638 				    (rval == FCAL_ABORT_FAILED)) {
4639 					my_rval = TRUE;
4640 					pkt->pkt_reason = CMD_ABORTED;
4641 					pkt->pkt_statistics |= STAT_ABORTED;
4642 					cmd->cmd_state = SF_STATE_IDLE;
4643 				} else if (rval == FCAL_BAD_ABORT) {
4644 					cmd->cmd_timeout = sf_watchdog_time
4645 					    + 20;
4646 					my_rval = FALSE;
4647 				} else {
4648 					SF_DEBUG(1, (sf, CE_NOTE,
4649 					    "Command Abort failed\n"));
4650 				}
4651 			} else {
4652 				mutex_exit(&cmd->cmd_abort_mutex);
4653 			}
4654 		}
4655 	} else {
4656 		SF_DEBUG(2, (sf, CE_NOTE, "sf_abort target\n"));
4657 		mutex_enter(&sf->sf_mutex);
4658 		lip_cnt = sf->sf_lip_cnt;
4659 		mutex_enter(&target->sft_mutex);
4660 		if (target->sft_state & (SF_TARGET_BUSY |
4661 		    SF_TARGET_OFFLINE)) {
4662 			mutex_exit(&target->sft_mutex);
4663 			return (rval);
4664 		}
4665 		old_target_state = target->sft_state;
4666 		target->sft_state |= SF_TARGET_BUSY;
4667 		mutex_exit(&target->sft_mutex);
4668 		mutex_exit(&sf->sf_mutex);
4669 
4670 		if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
4671 		    0, 0, 0, NULL, 0)) != NULL) {
4672 
4673 			cmd = PKT2CMD(pkt);
4674 			cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 1;
4675 			cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
4676 			cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
4677 
4678 			/* prepare the packet for transport */
4679 			if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
4680 
4681 				cmd->cmd_state = SF_STATE_ISSUED;
4682 				/*
4683 				 * call transport to send a pkt polled
4684 				 *
4685 				 * if that fails call the transport to abort it
4686 				 */
4687 				if (soc_transport_poll(sf->sf_sochandle,
4688 				    cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
4689 				    CQ_REQUEST_1) == FCAL_TRANSPORT_SUCCESS) {
4690 					(void) ddi_dma_sync(
4691 					    cmd->cmd_cr_pool->rsp_dma_handle,
4692 					    (off_t)
4693 					    ((caddr_t)cmd->cmd_rsp_block -
4694 					    cmd->cmd_cr_pool->rsp_base),
4695 					    FCP_MAX_RSP_IU_SIZE,
4696 					    DDI_DMA_SYNC_FORKERNEL);
4697 					if (((struct fcp_rsp_info *)
4698 					    (&cmd->cmd_rsp_block->
4699 					    fcp_response_len + 1))->
4700 					    rsp_code == FCP_NO_FAILURE) {
4701 						/* abort cmds for this targ */
4702 						sf_abort_all(sf, target, TRUE,
4703 						    lip_cnt, TRUE);
4704 					} else {
4705 						hp = &cmd->cmd_fp_pkt->
4706 						    fcal_socal_request.
4707 						    sr_fc_frame_hdr;
4708 						tgt_id = sf_alpa_to_switch[
4709 						    (uchar_t)hp->d_id];
4710 						sf->sf_stats.tstats[tgt_id].
4711 						    task_mgmt_failures++;
4712 						SF_DEBUG(1, (sf, CE_NOTE,
4713 						    "Target %d Abort Task "
4714 						    "Set failed\n", hp->d_id));
4715 					}
4716 				} else {
4717 					mutex_enter(&cmd->cmd_abort_mutex);
4718 					if (cmd->cmd_state == SF_STATE_ISSUED) {
4719 					cmd->cmd_state = SF_STATE_ABORTING;
4720 					cmd->cmd_timeout = sf_watchdog_time
4721 					    + 20;
4722 					mutex_exit(&cmd->cmd_abort_mutex);
4723 					if ((t = soc_abort(sf->sf_sochandle,
4724 					    sf->sf_socp, sf->sf_sochandle->
4725 					    fcal_portno, cmd->cmd_fp_pkt, 1)) !=
4726 					    FCAL_ABORTED &&
4727 					    (t != FCAL_ABORT_FAILED)) {
4728 						sf_log(sf, CE_NOTE,
4729 						    "sf_abort failed, "
4730 						    "initiating LIP\n");
4731 						sf_force_lip(sf);
4732 						deferred_destroy = 1;
4733 					}
4734 					} else {
4735 					mutex_exit(&cmd->cmd_abort_mutex);
4736 					}
4737 				}
4738 			}
4739 			if (!deferred_destroy) {
4740 				cmd->cmd_fp_pkt->fcal_pkt_comp =
4741 				    sf_cmd_callback;
4742 				cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 0;
4743 				sf_scsi_destroy_pkt(ap, pkt);
4744 				my_rval = TRUE;
4745 			}
4746 		}
4747 		mutex_enter(&sf->sf_mutex);
4748 		if (lip_cnt == sf->sf_lip_cnt) {
4749 			mutex_enter(&target->sft_mutex);
4750 			target->sft_state = old_target_state;
4751 			mutex_exit(&target->sft_mutex);
4752 		}
4753 		mutex_exit(&sf->sf_mutex);
4754 	}
4755 	return (my_rval);
4756 }
4757 
4758 
4759 /*
4760  * called by the transport and internally to reset a target
4761  */
4762 static int
sf_reset(struct scsi_address * ap,int level)4763 sf_reset(struct scsi_address *ap, int level)
4764 {
4765 	struct scsi_pkt *pkt;
4766 	struct fcal_packet *fpkt;
4767 	struct sf *sf = ADDR2SF(ap);
4768 	struct sf_target *target = ADDR2TARGET(ap), *ntarget;
4769 	struct sf_pkt *cmd;
4770 	int	rval = FALSE, t;
4771 	int	lip_cnt;
4772 	int	tgt_id, ret;
4773 	fc_frame_header_t	*hp;
4774 	int	deferred_destroy;
4775 
4776 	/* We don't support RESET_LUN yet. */
4777 	if (level == RESET_TARGET) {
4778 		struct sf_reset_list *p;
4779 
4780 		if ((p = kmem_alloc(sizeof (struct sf_reset_list), KM_NOSLEEP))
4781 		    == NULL)
4782 			return (rval);
4783 
4784 		SF_DEBUG(2, (sf, CE_NOTE, "sf_reset target\n"));
4785 		mutex_enter(&sf->sf_mutex);
4786 		/* All target resets go to LUN 0 */
4787 		if (target->sft_lun.l) {
4788 			target = sf_lookup_target(sf, target->sft_port_wwn, 0);
4789 		}
4790 		mutex_enter(&target->sft_mutex);
4791 		if (target->sft_state & (SF_TARGET_BUSY |
4792 		    SF_TARGET_OFFLINE)) {
4793 			mutex_exit(&target->sft_mutex);
4794 			mutex_exit(&sf->sf_mutex);
4795 			kmem_free(p, sizeof (struct sf_reset_list));
4796 			return (rval);
4797 		}
4798 		lip_cnt = sf->sf_lip_cnt;
4799 		target->sft_state |= SF_TARGET_BUSY;
4800 		for (ntarget = target->sft_next_lun;
4801 		    ntarget;
4802 		    ntarget = ntarget->sft_next_lun) {
4803 			mutex_enter(&ntarget->sft_mutex);
4804 			/*
4805 			 * XXXX If we supported RESET_LUN we should check here
4806 			 * to see if any LUN were being reset and somehow fail
4807 			 * that operation.
4808 			 */
4809 			ntarget->sft_state |= SF_TARGET_BUSY;
4810 			mutex_exit(&ntarget->sft_mutex);
4811 		}
4812 		mutex_exit(&target->sft_mutex);
4813 		mutex_exit(&sf->sf_mutex);
4814 
4815 		deferred_destroy = 0;
4816 		if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
4817 		    0, 0, 0, NULL, 0)) != NULL) {
4818 			cmd = PKT2CMD(pkt);
4819 			cmd->cmd_block->fcp_cntl.cntl_reset = 1;
4820 			cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
4821 			cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
4822 
4823 			/* prepare the packet for transport */
4824 			if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
4825 				/* call transport to send a pkt polled */
4826 				cmd->cmd_state = SF_STATE_ISSUED;
4827 				if ((ret = soc_transport_poll(sf->sf_sochandle,
4828 				    cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
4829 				    CQ_REQUEST_1)) == FCAL_TRANSPORT_SUCCESS) {
4830 					(void) ddi_dma_sync(cmd->cmd_cr_pool->
4831 					    rsp_dma_handle, (caddr_t)cmd->
4832 					    cmd_rsp_block - cmd->cmd_cr_pool->
4833 					    rsp_base, FCP_MAX_RSP_IU_SIZE,
4834 					    DDI_DMA_SYNC_FORKERNEL);
4835 					fpkt = cmd->cmd_fp_pkt;
4836 					if ((fpkt->fcal_pkt_status ==
4837 					    FCAL_STATUS_OK) &&
4838 					    (((struct fcp_rsp_info *)
4839 					    (&cmd->cmd_rsp_block->
4840 					    fcp_response_len + 1))->
4841 					    rsp_code == FCP_NO_FAILURE)) {
4842 						sf_log(sf, CE_NOTE,
4843 						    "!sf%d: Target 0x%x Reset "
4844 						    "successful\n",
4845 						    ddi_get_instance(\
4846 						    sf->sf_dip),
4847 						    sf_alpa_to_switch[
4848 						    target->sft_al_pa]);
4849 						rval = TRUE;
4850 					} else {
4851 						hp = &cmd->cmd_fp_pkt->
4852 						    fcal_socal_request.
4853 						    sr_fc_frame_hdr;
4854 						tgt_id = sf_alpa_to_switch[
4855 						    (uchar_t)hp->d_id];
4856 						sf->sf_stats.tstats[tgt_id].
4857 						    task_mgmt_failures++;
4858 						sf_log(sf, CE_NOTE,
4859 						    "!sf%d: Target 0x%x "
4860 						    "Reset failed."
4861 						    "Status code 0x%x "
4862 						    "Resp code 0x%x\n",
4863 						    ddi_get_instance(\
4864 						    sf->sf_dip),
4865 						    tgt_id,
4866 						    fpkt->fcal_pkt_status,
4867 						    ((struct fcp_rsp_info *)
4868 						    (&cmd->cmd_rsp_block->
4869 						    fcp_response_len + 1))->
4870 						    rsp_code);
4871 					}
4872 				} else {
4873 					sf_log(sf, CE_NOTE, "!sf%d: Target "
4874 					    "0x%x Reset Failed. Ret=%x\n",
4875 					    ddi_get_instance(sf->sf_dip),
4876 					    sf_alpa_to_switch[
4877 					    target->sft_al_pa], ret);
4878 					mutex_enter(&cmd->cmd_abort_mutex);
4879 					if (cmd->cmd_state == SF_STATE_ISSUED) {
4880 					/* call the transport to abort a cmd */
4881 					cmd->cmd_timeout = sf_watchdog_time
4882 					    + 20;
4883 					cmd->cmd_state = SF_STATE_ABORTING;
4884 					mutex_exit(&cmd->cmd_abort_mutex);
4885 					if (((t = soc_abort(sf->sf_sochandle,
4886 					    sf->sf_socp,
4887 					    sf->sf_sochandle->fcal_portno,
4888 					    cmd->cmd_fp_pkt, 1)) !=
4889 					    FCAL_ABORTED) &&
4890 					    (t != FCAL_ABORT_FAILED)) {
4891 						sf_log(sf, CE_NOTE,
4892 						    "!sf%d: Target 0x%x Reset "
4893 						    "failed. Abort Failed, "
4894 						    "forcing LIP\n",
4895 						    ddi_get_instance(
4896 						    sf->sf_dip),
4897 						    sf_alpa_to_switch[
4898 						    target->sft_al_pa]);
4899 						sf_force_lip(sf);
4900 						rval = TRUE;
4901 						deferred_destroy = 1;
4902 					}
4903 					} else {
4904 						mutex_exit
4905 						    (&cmd->cmd_abort_mutex);
4906 					}
4907 				}
4908 			}
4909 			/*
4910 			 * Defer releasing the packet if we abort returned with
4911 			 * a BAD_ABORT or timed out, because there is a
4912 			 * possibility that the ucode might return it.
4913 			 * We wait for at least 20s and let it be released
4914 			 * by the sf_watch thread
4915 			 */
4916 			if (!deferred_destroy) {
4917 				cmd->cmd_block->fcp_cntl.cntl_reset = 0;
4918 				cmd->cmd_fp_pkt->fcal_pkt_comp =
4919 				    sf_cmd_callback;
4920 				cmd->cmd_state = SF_STATE_IDLE;
4921 				/* for cache */
4922 				sf_scsi_destroy_pkt(ap, pkt);
4923 			}
4924 		} else {
4925 			cmn_err(CE_WARN, "!sf%d: Target 0x%x Reset Failed. "
4926 			    "Resource allocation error.\n",
4927 			    ddi_get_instance(sf->sf_dip),
4928 			    sf_alpa_to_switch[target->sft_al_pa]);
4929 		}
4930 		mutex_enter(&sf->sf_mutex);
4931 		if ((rval == TRUE) && (lip_cnt == sf->sf_lip_cnt)) {
4932 			p->target = target;
4933 			p->lip_cnt = lip_cnt;
4934 			p->timeout = ddi_get_lbolt() +
4935 			    drv_usectohz(SF_TARGET_RESET_DELAY);
4936 			p->next = sf->sf_reset_list;
4937 			sf->sf_reset_list = p;
4938 			mutex_exit(&sf->sf_mutex);
4939 			mutex_enter(&sf_global_mutex);
4940 			if (sf_reset_timeout_id == 0) {
4941 				sf_reset_timeout_id = timeout(
4942 				    sf_check_reset_delay, NULL,
4943 				    drv_usectohz(SF_TARGET_RESET_DELAY));
4944 			}
4945 			mutex_exit(&sf_global_mutex);
4946 		} else {
4947 			if (lip_cnt == sf->sf_lip_cnt) {
4948 				mutex_enter(&target->sft_mutex);
4949 				target->sft_state &= ~SF_TARGET_BUSY;
4950 				for (ntarget = target->sft_next_lun;
4951 				    ntarget;
4952 				    ntarget = ntarget->sft_next_lun) {
4953 					mutex_enter(&ntarget->sft_mutex);
4954 					ntarget->sft_state &= ~SF_TARGET_BUSY;
4955 					mutex_exit(&ntarget->sft_mutex);
4956 				}
4957 				mutex_exit(&target->sft_mutex);
4958 			}
4959 			mutex_exit(&sf->sf_mutex);
4960 			kmem_free(p, sizeof (struct sf_reset_list));
4961 		}
4962 	} else {
4963 		mutex_enter(&sf->sf_mutex);
4964 		if ((sf->sf_state == SF_STATE_OFFLINE) &&
4965 		    (sf_watchdog_time < sf->sf_timer)) {
4966 			/*
4967 			 * We are currently in a lip, so let this one
4968 			 * finish before forcing another one.
4969 			 */
4970 			mutex_exit(&sf->sf_mutex);
4971 			return (TRUE);
4972 		}
4973 		mutex_exit(&sf->sf_mutex);
4974 		sf_log(sf, CE_NOTE, "!sf:Target driver initiated lip\n");
4975 		sf_force_lip(sf);
4976 		rval = TRUE;
4977 	}
4978 	return (rval);
4979 }
4980 
4981 
4982 /*
4983  * abort all commands for a target
4984  *
4985  * if try_abort is set then send an abort
4986  * if abort is set then this is abort, else this is a reset
4987  */
4988 static void
sf_abort_all(struct sf * sf,struct sf_target * target,int abort,int lip_cnt,int try_abort)4989 sf_abort_all(struct sf *sf, struct sf_target *target, int abort, int
4990     lip_cnt, int try_abort)
4991 {
4992 	struct sf_target *ntarget;
4993 	struct sf_pkt *cmd, *head = NULL, *tail = NULL, *pcmd = NULL, *tcmd;
4994 	struct fcal_packet *fpkt;
4995 	struct scsi_pkt *pkt;
4996 	int rval = FCAL_ABORTED;
4997 
4998 	/*
4999 	 * First pull all commands for all LUNs on this target out of the
5000 	 * overflow list.  We can tell it's the same target by comparing
5001 	 * the node WWN.
5002 	 */
5003 	mutex_enter(&sf->sf_mutex);
5004 	if (lip_cnt == sf->sf_lip_cnt) {
5005 		mutex_enter(&sf->sf_cmd_mutex);
5006 		cmd = sf->sf_pkt_head;
5007 		while (cmd != NULL) {
5008 			ntarget = ADDR2TARGET(&cmd->cmd_pkt->
5009 			    pkt_address);
5010 			if (ntarget == target) {
5011 				if (pcmd != NULL)
5012 					pcmd->cmd_next = cmd->cmd_next;
5013 				else
5014 					sf->sf_pkt_head = cmd->cmd_next;
5015 				if (sf->sf_pkt_tail == cmd) {
5016 					sf->sf_pkt_tail = pcmd;
5017 					if (pcmd != NULL)
5018 						pcmd->cmd_next = NULL;
5019 				}
5020 				tcmd = cmd->cmd_next;
5021 				if (head == NULL) {
5022 					head = cmd;
5023 					tail = cmd;
5024 				} else {
5025 					tail->cmd_next = cmd;
5026 					tail = cmd;
5027 				}
5028 				cmd->cmd_next = NULL;
5029 				cmd = tcmd;
5030 			} else {
5031 				pcmd = cmd;
5032 				cmd = cmd->cmd_next;
5033 			}
5034 		}
5035 		mutex_exit(&sf->sf_cmd_mutex);
5036 	}
5037 	mutex_exit(&sf->sf_mutex);
5038 
5039 	/*
5040 	 * Now complete all the commands on our list.  In the process,
5041 	 * the completion routine may take the commands off the target
5042 	 * lists.
5043 	 */
5044 	cmd = head;
5045 	while (cmd != NULL) {
5046 		pkt = cmd->cmd_pkt;
5047 		if (abort) {
5048 			pkt->pkt_reason = CMD_ABORTED;
5049 			pkt->pkt_statistics |= STAT_ABORTED;
5050 		} else {
5051 			pkt->pkt_reason = CMD_RESET;
5052 			pkt->pkt_statistics |= STAT_DEV_RESET;
5053 		}
5054 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
5055 		cmd->cmd_state = SF_STATE_IDLE;
5056 		cmd = cmd->cmd_next;
5057 		/*
5058 		 * call the packet completion routine only for
5059 		 * non-polled commands. Ignore the polled commands as
5060 		 * they timeout and will be handled differently
5061 		 */
5062 		if ((pkt->pkt_comp) && !(pkt->pkt_flags & FLAG_NOINTR))
5063 			(*pkt->pkt_comp)(pkt);
5064 
5065 	}
5066 
5067 	/*
5068 	 * Finally get all outstanding commands for each LUN, and abort them if
5069 	 * they've been issued, and call the completion routine.
5070 	 * For the case where sf_offline_target is called from sf_watch
5071 	 * due to a Offline Timeout, it is quite possible that the soc+
5072 	 * ucode is hosed and therefore  cannot return the commands.
5073 	 * Clear up all the issued commands as well.
5074 	 * Try_abort will be false only if sf_abort_all is coming from
5075 	 * sf_target_offline.
5076 	 */
5077 
5078 	if (try_abort || sf->sf_state == SF_STATE_OFFLINE) {
5079 		mutex_enter(&target->sft_pkt_mutex);
5080 		cmd = tcmd = target->sft_pkt_head;
5081 		while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
5082 			fpkt = cmd->cmd_fp_pkt;
5083 			pkt = cmd->cmd_pkt;
5084 			mutex_enter(&cmd->cmd_abort_mutex);
5085 			if ((cmd->cmd_state == SF_STATE_ISSUED) &&
5086 			    (fpkt->fcal_cmd_state &
5087 			    FCAL_CMD_IN_TRANSPORT) &&
5088 			    ((fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE) ==
5089 			    0) && !(pkt->pkt_flags & FLAG_NOINTR)) {
5090 				cmd->cmd_state = SF_STATE_ABORTING;
5091 				cmd->cmd_timeout = sf_watchdog_time +
5092 				    cmd->cmd_pkt->pkt_time + 20;
5093 				mutex_exit(&cmd->cmd_abort_mutex);
5094 				mutex_exit(&target->sft_pkt_mutex);
5095 				if (try_abort) {
5096 					/* call the transport to abort a pkt */
5097 					rval = soc_abort(sf->sf_sochandle,
5098 					    sf->sf_socp,
5099 					    sf->sf_sochandle->fcal_portno,
5100 					    fpkt, 1);
5101 				}
5102 				if ((rval == FCAL_ABORTED) ||
5103 				    (rval == FCAL_ABORT_FAILED)) {
5104 					if (abort) {
5105 						pkt->pkt_reason = CMD_ABORTED;
5106 						pkt->pkt_statistics |=
5107 						    STAT_ABORTED;
5108 					} else {
5109 						pkt->pkt_reason = CMD_RESET;
5110 						pkt->pkt_statistics |=
5111 						    STAT_DEV_RESET;
5112 					}
5113 					cmd->cmd_state = SF_STATE_IDLE;
5114 					if (pkt->pkt_comp)
5115 						(*pkt->pkt_comp)(pkt);
5116 				}
5117 				mutex_enter(&sf->sf_mutex);
5118 				if (lip_cnt != sf->sf_lip_cnt) {
5119 					mutex_exit(&sf->sf_mutex);
5120 					return;
5121 				}
5122 				mutex_exit(&sf->sf_mutex);
5123 				mutex_enter(&target->sft_pkt_mutex);
5124 				cmd = target->sft_pkt_head;
5125 			} else {
5126 				mutex_exit(&cmd->cmd_abort_mutex);
5127 				cmd = cmd->cmd_forw;
5128 			}
5129 		}
5130 		mutex_exit(&target->sft_pkt_mutex);
5131 	}
5132 }
5133 
5134 
5135 /*
5136  * called by the transport to start a packet
5137  */
5138 static int
sf_start(struct scsi_address * ap,struct scsi_pkt * pkt)5139 sf_start(struct scsi_address *ap, struct scsi_pkt *pkt)
5140 {
5141 	struct sf *sf = ADDR2SF(ap);
5142 	struct sf_target *target = ADDR2TARGET(ap);
5143 	struct sf_pkt *cmd = PKT2CMD(pkt);
5144 	int rval;
5145 
5146 
5147 	SF_DEBUG(6, (sf, CE_NOTE, "sf_start\n"));
5148 
5149 	if (cmd->cmd_state == SF_STATE_ISSUED) {
5150 		cmn_err(CE_PANIC, "sf: issuing packet twice 0x%p\n",
5151 		    (void *)cmd);
5152 	}
5153 
5154 	/* prepare the packet for transport */
5155 	if ((rval = sf_prepare_pkt(sf, cmd, target)) != TRAN_ACCEPT) {
5156 		return (rval);
5157 	}
5158 
5159 	if (target->sft_state & (SF_TARGET_BUSY|SF_TARGET_OFFLINE)) {
5160 		if (target->sft_state & SF_TARGET_OFFLINE) {
5161 			return (TRAN_FATAL_ERROR);
5162 		}
5163 		if (pkt->pkt_flags & FLAG_NOINTR) {
5164 			return (TRAN_BUSY);
5165 		}
5166 		mutex_enter(&sf->sf_cmd_mutex);
5167 		sf->sf_use_lock = TRUE;
5168 		goto enque;
5169 	}
5170 
5171 
5172 	/* if no interrupts then do polled I/O */
5173 	if (pkt->pkt_flags & FLAG_NOINTR) {
5174 		return (sf_dopoll(sf, cmd));
5175 	}
5176 
5177 	/* regular interrupt-driven I/O */
5178 
5179 	if (!sf->sf_use_lock) {
5180 
5181 		/* locking no needed */
5182 
5183 		cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
5184 		    sf_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
5185 		cmd->cmd_state = SF_STATE_ISSUED;
5186 
5187 		/* call the transport to send a pkt */
5188 		if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt,
5189 		    FCAL_NOSLEEP, CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
5190 			cmd->cmd_state = SF_STATE_IDLE;
5191 			return (TRAN_BADPKT);
5192 		}
5193 		return (TRAN_ACCEPT);
5194 	}
5195 
5196 	/* regular I/O using locking */
5197 
5198 	mutex_enter(&sf->sf_cmd_mutex);
5199 	if ((sf->sf_ncmds >= sf->sf_throttle) ||
5200 	    (sf->sf_pkt_head != NULL)) {
5201 enque:
5202 		/*
5203 		 * either we're throttling back or there are already commands
5204 		 * on the queue, so enqueue this one for later
5205 		 */
5206 		cmd->cmd_flags |= CFLAG_IN_QUEUE;
5207 		if (sf->sf_pkt_head != NULL) {
5208 			/* add to the queue */
5209 			sf->sf_pkt_tail->cmd_next = cmd;
5210 			cmd->cmd_next = NULL;
5211 			sf->sf_pkt_tail = cmd;
5212 		} else {
5213 			/* this is the first entry in the queue */
5214 			sf->sf_pkt_head = sf->sf_pkt_tail = cmd;
5215 			cmd->cmd_next = NULL;
5216 		}
5217 		mutex_exit(&sf->sf_cmd_mutex);
5218 		return (TRAN_ACCEPT);
5219 	}
5220 
5221 	/*
5222 	 * start this packet now
5223 	 */
5224 
5225 	/* still have cmd mutex */
5226 	return (sf_start_internal(sf, cmd));
5227 }
5228 
5229 
5230 /*
5231  * internal routine to start a packet from the queue now
5232  *
5233  * enter with cmd mutex held and leave with it released
5234  */
5235 static int
sf_start_internal(struct sf * sf,struct sf_pkt * cmd)5236 sf_start_internal(struct sf *sf, struct sf_pkt *cmd)
5237 {
5238 	/* we have the cmd mutex */
5239 	sf->sf_ncmds++;
5240 	mutex_exit(&sf->sf_cmd_mutex);
5241 
5242 	ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5243 	SF_DEBUG(6, (sf, CE_NOTE, "sf_start_internal\n"));
5244 
5245 	cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? sf_watchdog_time +
5246 	    cmd->cmd_pkt->pkt_time : 0;
5247 	cmd->cmd_state = SF_STATE_ISSUED;
5248 
5249 	/* call transport to send the pkt */
5250 	if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt, FCAL_NOSLEEP,
5251 	    CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
5252 		cmd->cmd_state = SF_STATE_IDLE;
5253 		mutex_enter(&sf->sf_cmd_mutex);
5254 		sf->sf_ncmds--;
5255 		mutex_exit(&sf->sf_cmd_mutex);
5256 		return (TRAN_BADPKT);
5257 	}
5258 	return (TRAN_ACCEPT);
5259 }
5260 
5261 
5262 /*
5263  * prepare a packet for transport
5264  */
5265 static int
sf_prepare_pkt(struct sf * sf,struct sf_pkt * cmd,struct sf_target * target)5266 sf_prepare_pkt(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
5267 {
5268 	struct fcp_cmd *fcmd = cmd->cmd_block;
5269 
5270 /* XXXX Need to set the LUN ? */
5271 	bcopy((caddr_t)&target->sft_lun.b,
5272 	    (caddr_t)&fcmd->fcp_ent_addr,
5273 	    FCP_LUN_SIZE);
5274 	cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
5275 	cmd->cmd_pkt->pkt_state = 0;
5276 	cmd->cmd_pkt->pkt_statistics = 0;
5277 
5278 
5279 	if ((cmd->cmd_pkt->pkt_comp == NULL) &&
5280 	    ((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0)) {
5281 		return (TRAN_BADPKT);
5282 	}
5283 
5284 	/* invalidate imp field(s) of rsp block */
5285 	cmd->cmd_rsp_block->fcp_u.i_fcp_status = SF_BAD_DMA_MAGIC;
5286 
5287 	/* set up amt of I/O to do */
5288 	if (cmd->cmd_flags & CFLAG_DMAVALID) {
5289 		cmd->cmd_pkt->pkt_resid = cmd->cmd_dmacount;
5290 		if (cmd->cmd_flags & CFLAG_CMDIOPB) {
5291 			(void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
5292 			    DDI_DMA_SYNC_FORDEV);
5293 		}
5294 	} else {
5295 		cmd->cmd_pkt->pkt_resid = 0;
5296 	}
5297 
5298 	/* set up the Tagged Queuing type */
5299 	if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
5300 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
5301 	} else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
5302 		fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
5303 	}
5304 
5305 	/*
5306 	 * Sync the cmd segment
5307 	 */
5308 	(void) ddi_dma_sync(cmd->cmd_cr_pool->cmd_dma_handle,
5309 	    (caddr_t)fcmd - cmd->cmd_cr_pool->cmd_base,
5310 	    sizeof (struct fcp_cmd), DDI_DMA_SYNC_FORDEV);
5311 
5312 	sf_fill_ids(sf, cmd, target);
5313 	return (TRAN_ACCEPT);
5314 }
5315 
5316 
5317 /*
5318  * fill in packet hdr source and destination IDs and hdr byte count
5319  */
5320 static void
sf_fill_ids(struct sf * sf,struct sf_pkt * cmd,struct sf_target * target)5321 sf_fill_ids(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
5322 {
5323 	struct fcal_packet *fpkt = cmd->cmd_fp_pkt;
5324 	fc_frame_header_t	*hp;
5325 
5326 
5327 	hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
5328 	hp->d_id = target->sft_al_pa;
5329 	hp->s_id = sf->sf_al_pa;
5330 	fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
5331 	    cmd->cmd_dmacookie.dmac_size;
5332 }
5333 
5334 
5335 /*
5336  * do polled I/O using transport
5337  */
5338 static int
sf_dopoll(struct sf * sf,struct sf_pkt * cmd)5339 sf_dopoll(struct sf *sf, struct sf_pkt *cmd)
5340 {
5341 	int timeout;
5342 	int rval;
5343 
5344 
5345 	mutex_enter(&sf->sf_cmd_mutex);
5346 	sf->sf_ncmds++;
5347 	mutex_exit(&sf->sf_cmd_mutex);
5348 
5349 	timeout = cmd->cmd_pkt->pkt_time ? cmd->cmd_pkt->pkt_time
5350 	    : SF_POLL_TIMEOUT;
5351 	cmd->cmd_timeout = 0;
5352 	cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
5353 	cmd->cmd_state = SF_STATE_ISSUED;
5354 
5355 	/* call transport to send a pkt polled */
5356 	rval = soc_transport_poll(sf->sf_sochandle, cmd->cmd_fp_pkt,
5357 	    timeout*1000000, CQ_REQUEST_1);
5358 	mutex_enter(&cmd->cmd_abort_mutex);
5359 	cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5360 	if (rval != FCAL_TRANSPORT_SUCCESS) {
5361 		if (rval == FCAL_TRANSPORT_TIMEOUT) {
5362 			cmd->cmd_state = SF_STATE_ABORTING;
5363 			mutex_exit(&cmd->cmd_abort_mutex);
5364 			(void) sf_target_timeout(sf, cmd);
5365 		} else {
5366 			mutex_exit(&cmd->cmd_abort_mutex);
5367 		}
5368 		cmd->cmd_state = SF_STATE_IDLE;
5369 		cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5370 		mutex_enter(&sf->sf_cmd_mutex);
5371 		sf->sf_ncmds--;
5372 		mutex_exit(&sf->sf_cmd_mutex);
5373 		return (TRAN_BADPKT);
5374 	}
5375 	mutex_exit(&cmd->cmd_abort_mutex);
5376 	cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5377 	sf_cmd_callback(cmd->cmd_fp_pkt);
5378 	return (TRAN_ACCEPT);
5379 }
5380 
5381 
5382 /* a shortcut for defining debug messages below */
5383 #ifdef	DEBUG
5384 #define	SF_DMSG1(s)		msg1 = s
5385 #else
5386 #define	SF_DMSG1(s)		/* do nothing */
5387 #endif
5388 
5389 
5390 /*
5391  * the pkt_comp callback for command packets
5392  */
5393 static void
sf_cmd_callback(struct fcal_packet * fpkt)5394 sf_cmd_callback(struct fcal_packet *fpkt)
5395 {
5396 	struct sf_pkt *cmd = (struct sf_pkt *)fpkt->fcal_pkt_private;
5397 	struct scsi_pkt *pkt = cmd->cmd_pkt;
5398 	struct sf *sf = ADDR2SF(&pkt->pkt_address);
5399 	struct sf_target *target = ADDR2TARGET(&pkt->pkt_address);
5400 	struct fcp_rsp *rsp;
5401 	char *msg1 = NULL;
5402 	char *msg2 = NULL;
5403 	short ncmds;
5404 	int tgt_id;
5405 	int good_scsi_status = TRUE;
5406 
5407 
5408 
5409 	if (cmd->cmd_state == SF_STATE_IDLE) {
5410 		cmn_err(CE_PANIC, "sf: completing idle packet 0x%p\n",
5411 		    (void *)cmd);
5412 	}
5413 
5414 	mutex_enter(&cmd->cmd_abort_mutex);
5415 	if (cmd->cmd_state == SF_STATE_ABORTING) {
5416 		/* cmd already being aborted -- nothing to do */
5417 		mutex_exit(&cmd->cmd_abort_mutex);
5418 		return;
5419 	}
5420 
5421 	cmd->cmd_state = SF_STATE_IDLE;
5422 	mutex_exit(&cmd->cmd_abort_mutex);
5423 
5424 	if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
5425 
5426 		(void) ddi_dma_sync(cmd->cmd_cr_pool->rsp_dma_handle,
5427 		    (caddr_t)cmd->cmd_rsp_block - cmd->cmd_cr_pool->rsp_base,
5428 		    FCP_MAX_RSP_IU_SIZE, DDI_DMA_SYNC_FORKERNEL);
5429 
5430 		rsp = (struct fcp_rsp *)cmd->cmd_rsp_block;
5431 
5432 		if (rsp->fcp_u.i_fcp_status == SF_BAD_DMA_MAGIC) {
5433 
5434 			if (sf_core && (sf_core & SF_CORE_BAD_DMA)) {
5435 				sf_token = (int *)(uintptr_t)
5436 				    fpkt->fcal_socal_request.\
5437 				    sr_soc_hdr.sh_request_token;
5438 				(void) soc_take_core(sf->sf_sochandle,
5439 				    sf->sf_socp);
5440 			}
5441 
5442 			pkt->pkt_reason = CMD_INCOMPLETE;
5443 			pkt->pkt_state = STATE_GOT_BUS;
5444 			pkt->pkt_statistics |= STAT_ABORTED;
5445 
5446 		} else {
5447 
5448 			pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
5449 			    STATE_SENT_CMD | STATE_GOT_STATUS;
5450 			pkt->pkt_resid = 0;
5451 			if (cmd->cmd_flags & CFLAG_DMAVALID) {
5452 				pkt->pkt_state |= STATE_XFERRED_DATA;
5453 			}
5454 
5455 			if ((pkt->pkt_scbp != NULL) &&
5456 			    ((*(pkt->pkt_scbp) =
5457 			    rsp->fcp_u.fcp_status.scsi_status)
5458 			    != STATUS_GOOD)) {
5459 				good_scsi_status = FALSE;
5460 			/*
5461 			 * The next two checks make sure that if there
5462 			 * is no sense data or a valid response and
5463 			 * the command came back with check condition,
5464 			 * the command should be retried
5465 			 */
5466 				if (!rsp->fcp_u.fcp_status.rsp_len_set &&
5467 				    !rsp->fcp_u.fcp_status.sense_len_set) {
5468 					pkt->pkt_state &= ~STATE_XFERRED_DATA;
5469 					pkt->pkt_resid = cmd->cmd_dmacount;
5470 				}
5471 			}
5472 
5473 			if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
5474 			    (pkt->pkt_state & STATE_XFERRED_DATA)) {
5475 				(void) ddi_dma_sync(cmd->cmd_dmahandle, 0,
5476 				    (uint_t)0, DDI_DMA_SYNC_FORCPU);
5477 			}
5478 			/*
5479 			 * Update the transfer resid, if appropriate
5480 			 */
5481 			if (rsp->fcp_u.fcp_status.resid_over ||
5482 			    rsp->fcp_u.fcp_status.resid_under)
5483 				pkt->pkt_resid = rsp->fcp_resid;
5484 
5485 			/*
5486 			 * Check to see if the SCSI command failed.
5487 			 *
5488 			 */
5489 
5490 			/*
5491 			 * First see if we got a FCP protocol error.
5492 			 */
5493 			if (rsp->fcp_u.fcp_status.rsp_len_set) {
5494 				struct fcp_rsp_info *bep;
5495 
5496 				bep = (struct fcp_rsp_info *)
5497 				    (&rsp->fcp_response_len + 1);
5498 				if (bep->rsp_code != FCP_NO_FAILURE) {
5499 						pkt->pkt_reason = CMD_TRAN_ERR;
5500 					tgt_id = pkt->pkt_address.a_target;
5501 					switch (bep->rsp_code) {
5502 					case FCP_CMND_INVALID:
5503 						SF_DMSG1("FCP_RSP FCP_CMND "
5504 						    "fields invalid");
5505 						break;
5506 					case FCP_TASK_MGMT_NOT_SUPPTD:
5507 						SF_DMSG1("FCP_RSP Task"
5508 						    "Management Function"
5509 						    "Not Supported");
5510 						break;
5511 					case FCP_TASK_MGMT_FAILED:
5512 						SF_DMSG1("FCP_RSP Task "
5513 						    "Management Function"
5514 						    "Failed");
5515 						sf->sf_stats.tstats[tgt_id].
5516 						    task_mgmt_failures++;
5517 						break;
5518 					case FCP_DATA_RO_MISMATCH:
5519 						SF_DMSG1("FCP_RSP FCP_DATA RO "
5520 						    "mismatch with "
5521 						    "FCP_XFER_RDY DATA_RO");
5522 						sf->sf_stats.tstats[tgt_id].
5523 						    data_ro_mismatches++;
5524 						break;
5525 					case FCP_DL_LEN_MISMATCH:
5526 						SF_DMSG1("FCP_RSP FCP_DATA "
5527 						    "length "
5528 						    "different than BURST_LEN");
5529 						sf->sf_stats.tstats[tgt_id].
5530 						    dl_len_mismatches++;
5531 						break;
5532 					default:
5533 						SF_DMSG1("FCP_RSP invalid "
5534 						    "RSP_CODE");
5535 						break;
5536 					}
5537 				}
5538 			}
5539 
5540 			/*
5541 			 * See if we got a SCSI error with sense data
5542 			 */
5543 			if (rsp->fcp_u.fcp_status.sense_len_set) {
5544 				uchar_t rqlen = min(rsp->fcp_sense_len,
5545 				    sizeof (struct scsi_extended_sense));
5546 				caddr_t sense = (caddr_t)rsp +
5547 				    sizeof (struct fcp_rsp) +
5548 				    rsp->fcp_response_len;
5549 				struct scsi_arq_status *arq;
5550 				struct scsi_extended_sense *sensep =
5551 				    (struct scsi_extended_sense *)sense;
5552 
5553 				if (rsp->fcp_u.fcp_status.scsi_status !=
5554 				    STATUS_GOOD) {
5555 				if (rsp->fcp_u.fcp_status.scsi_status
5556 				    == STATUS_CHECK) {
5557 					if (sensep->es_key ==
5558 					    KEY_RECOVERABLE_ERROR)
5559 						good_scsi_status = 1;
5560 					if (sensep->es_key ==
5561 					    KEY_UNIT_ATTENTION &&
5562 					    sensep->es_add_code == 0x3f &&
5563 					    sensep->es_qual_code == 0x0e) {
5564 						/* REPORT_LUNS_HAS_CHANGED */
5565 						sf_log(sf, CE_NOTE,
5566 						"!REPORT_LUNS_HAS_CHANGED\n");
5567 						sf_force_lip(sf);
5568 					}
5569 				}
5570 				}
5571 
5572 				if ((pkt->pkt_scbp != NULL) &&
5573 				    (cmd->cmd_scblen >=
5574 					sizeof (struct scsi_arq_status))) {
5575 
5576 				pkt->pkt_state |= STATE_ARQ_DONE;
5577 
5578 				arq = (struct scsi_arq_status *)pkt->pkt_scbp;
5579 				/*
5580 				 * copy out sense information
5581 				 */
5582 				bcopy(sense, (caddr_t)&arq->sts_sensedata,
5583 				    rqlen);
5584 				arq->sts_rqpkt_resid =
5585 				    sizeof (struct scsi_extended_sense) -
5586 					rqlen;
5587 				*((uchar_t *)&arq->sts_rqpkt_status) =
5588 				    STATUS_GOOD;
5589 				arq->sts_rqpkt_reason = 0;
5590 				arq->sts_rqpkt_statistics = 0;
5591 				arq->sts_rqpkt_state = STATE_GOT_BUS |
5592 				    STATE_GOT_TARGET | STATE_SENT_CMD |
5593 				    STATE_GOT_STATUS | STATE_ARQ_DONE |
5594 				    STATE_XFERRED_DATA;
5595 			    }
5596 				target->sft_alive = TRUE;
5597 			}
5598 
5599 			/*
5600 			 * The firmware returns the number of bytes actually
5601 			 * xfered into/out of host. Compare this with what
5602 			 * we asked and if it is different, we lost frames ?
5603 			 */
5604 			if ((pkt->pkt_reason == 0) && (pkt->pkt_resid == 0) &&
5605 			    (good_scsi_status) &&
5606 			    (pkt->pkt_state & STATE_XFERRED_DATA) &&
5607 			    (!(cmd->cmd_flags & CFLAG_CMDIOPB)) &&
5608 			    (target->sft_device_type != DTYPE_ESI)) {
5609 				int byte_cnt =
5610 				    fpkt->fcal_socal_request.
5611 				    sr_soc_hdr.sh_byte_cnt;
5612 				if (cmd->cmd_flags & CFLAG_DMASEND) {
5613 					if (byte_cnt != 0) {
5614 					sf_log(sf, CE_NOTE,
5615 					    "!sf_cmd_callback: Lost Frame: "
5616 					    "(write) received 0x%x expected"
5617 					    " 0x%x target 0x%x\n",
5618 					    byte_cnt, cmd->cmd_dmacount,
5619 					    sf_alpa_to_switch[
5620 					    target->sft_al_pa]);
5621 					pkt->pkt_reason = CMD_INCOMPLETE;
5622 					pkt->pkt_statistics |= STAT_ABORTED;
5623 					}
5624 				} else if (byte_cnt < cmd->cmd_dmacount) {
5625 					sf_log(sf, CE_NOTE,
5626 					    "!sf_cmd_callback: "
5627 					    "Lost Frame: (read) "
5628 					    "received 0x%x expected 0x%x "
5629 					    "target 0x%x\n", byte_cnt,
5630 					    cmd->cmd_dmacount,
5631 					    sf_alpa_to_switch[
5632 					    target->sft_al_pa]);
5633 					pkt->pkt_reason = CMD_INCOMPLETE;
5634 					pkt->pkt_statistics |= STAT_ABORTED;
5635 				}
5636 			}
5637 		}
5638 
5639 	} else {
5640 
5641 		/* pkt status was not ok */
5642 
5643 		switch (fpkt->fcal_pkt_status) {
5644 
5645 		case FCAL_STATUS_ERR_OFFLINE:
5646 			SF_DMSG1("Fibre Channel Offline");
5647 			mutex_enter(&target->sft_mutex);
5648 			if (!(target->sft_state & SF_TARGET_OFFLINE)) {
5649 				target->sft_state |= (SF_TARGET_BUSY
5650 				    | SF_TARGET_MARK);
5651 			}
5652 			mutex_exit(&target->sft_mutex);
5653 			(void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
5654 			    target->sft_dip, FCAL_REMOVE_EVENT,
5655 			    &sf_remove_eid, NDI_EVENT_NOPASS);
5656 			(void) ndi_event_run_callbacks(sf->sf_event_hdl,
5657 			    target->sft_dip, sf_remove_eid, NULL);
5658 			pkt->pkt_reason = CMD_TRAN_ERR;
5659 			pkt->pkt_statistics |= STAT_BUS_RESET;
5660 			break;
5661 
5662 		case FCAL_STATUS_MAX_XCHG_EXCEEDED:
5663 			sf_throttle(sf);
5664 			sf->sf_use_lock = TRUE;
5665 			pkt->pkt_reason = CMD_TRAN_ERR;
5666 			pkt->pkt_state = STATE_GOT_BUS;
5667 			pkt->pkt_statistics |= STAT_ABORTED;
5668 			break;
5669 
5670 		case FCAL_STATUS_TIMEOUT:
5671 			SF_DMSG1("Fibre Channel Timeout");
5672 			pkt->pkt_reason = CMD_TIMEOUT;
5673 			break;
5674 
5675 		case FCAL_STATUS_ERR_OVERRUN:
5676 			SF_DMSG1("CMD_DATA_OVR");
5677 			pkt->pkt_reason = CMD_DATA_OVR;
5678 			break;
5679 
5680 		case FCAL_STATUS_UNKNOWN_CQ_TYPE:
5681 			SF_DMSG1("Unknown CQ type");
5682 			pkt->pkt_reason = CMD_TRAN_ERR;
5683 			break;
5684 
5685 		case FCAL_STATUS_BAD_SEG_CNT:
5686 			SF_DMSG1("Bad SEG CNT");
5687 			pkt->pkt_reason = CMD_TRAN_ERR;
5688 			break;
5689 
5690 		case FCAL_STATUS_BAD_XID:
5691 			SF_DMSG1("Fibre Channel Invalid X_ID");
5692 			pkt->pkt_reason = CMD_TRAN_ERR;
5693 			break;
5694 
5695 		case FCAL_STATUS_XCHG_BUSY:
5696 			SF_DMSG1("Fibre Channel Exchange Busy");
5697 			pkt->pkt_reason = CMD_TRAN_ERR;
5698 			break;
5699 
5700 		case FCAL_STATUS_INSUFFICIENT_CQES:
5701 			SF_DMSG1("Insufficient CQEs");
5702 			pkt->pkt_reason = CMD_TRAN_ERR;
5703 			break;
5704 
5705 		case FCAL_STATUS_ALLOC_FAIL:
5706 			SF_DMSG1("ALLOC FAIL");
5707 			pkt->pkt_reason = CMD_TRAN_ERR;
5708 			break;
5709 
5710 		case FCAL_STATUS_BAD_SID:
5711 			SF_DMSG1("Fibre Channel Invalid S_ID");
5712 			pkt->pkt_reason = CMD_TRAN_ERR;
5713 			break;
5714 
5715 		case FCAL_STATUS_INCOMPLETE_DMA_ERR:
5716 			if (sf_core && (sf_core & SF_CORE_INCOMPLETE_DMA)) {
5717 				sf_token = (int *)(uintptr_t)
5718 				    fpkt->fcal_socal_request.\
5719 				    sr_soc_hdr.sh_request_token;
5720 				(void) soc_take_core(sf->sf_sochandle,
5721 				    sf->sf_socp);
5722 				sf_core = 0;
5723 			}
5724 			msg2 =
5725 			"INCOMPLETE DMA XFER due to bad SOC+ card, replace HBA";
5726 			pkt->pkt_reason = CMD_INCOMPLETE;
5727 			pkt->pkt_state = STATE_GOT_BUS;
5728 			pkt->pkt_statistics |= STAT_ABORTED;
5729 			break;
5730 
5731 		case FCAL_STATUS_CRC_ERR:
5732 			msg2 = "Fibre Channel CRC Error on frames";
5733 			pkt->pkt_reason = CMD_INCOMPLETE;
5734 			pkt->pkt_state = STATE_GOT_BUS;
5735 			pkt->pkt_statistics |= STAT_ABORTED;
5736 			break;
5737 
5738 		case FCAL_STATUS_NO_SEQ_INIT:
5739 			SF_DMSG1("Fibre Channel Seq Init Error");
5740 			pkt->pkt_reason = CMD_TRAN_ERR;
5741 			break;
5742 
5743 		case  FCAL_STATUS_OPEN_FAIL:
5744 			pkt->pkt_reason = CMD_TRAN_ERR;
5745 			SF_DMSG1("Fibre Channel Open Failure");
5746 			if ((target->sft_state & (SF_TARGET_BUSY |
5747 			    SF_TARGET_MARK | SF_TARGET_OFFLINE)) == 0) {
5748 				sf_log(sf, CE_NOTE,
5749 				    "!Open failure to target 0x%x "
5750 				    "forcing LIP\n",
5751 				    sf_alpa_to_switch[target->sft_al_pa]);
5752 				sf_force_lip(sf);
5753 			}
5754 			break;
5755 
5756 
5757 		case FCAL_STATUS_ONLINE_TIMEOUT:
5758 			SF_DMSG1("Fibre Channel Online Timeout");
5759 			pkt->pkt_reason = CMD_TRAN_ERR;
5760 			break;
5761 
5762 		default:
5763 			SF_DMSG1("Unknown FC Status");
5764 			pkt->pkt_reason = CMD_TRAN_ERR;
5765 			break;
5766 		}
5767 	}
5768 
5769 #ifdef	DEBUG
5770 	/*
5771 	 * msg1 will be non-NULL if we've detected some sort of error
5772 	 */
5773 	if (msg1 != NULL && sfdebug >= 4) {
5774 		sf_log(sf, CE_WARN,
5775 		    "!Transport error on cmd=0x%p target=0x%x:  %s\n",
5776 		    (void *)fpkt, pkt->pkt_address.a_target, msg1);
5777 	}
5778 #endif
5779 
5780 	if (msg2 != NULL) {
5781 		sf_log(sf, CE_WARN, "!Transport error on target=0x%x:  %s\n",
5782 		    pkt->pkt_address.a_target, msg2);
5783 	}
5784 
5785 	ncmds = fpkt->fcal_ncmds;
5786 	ASSERT(ncmds >= 0);
5787 	if (ncmds >= (sf->sf_throttle - SF_HI_CMD_DELTA)) {
5788 #ifdef DEBUG
5789 		if (!sf->sf_use_lock) {
5790 			SF_DEBUG(4, (sf, CE_NOTE, "use lock flag on\n"));
5791 		}
5792 #endif
5793 		sf->sf_use_lock = TRUE;
5794 	}
5795 
5796 	mutex_enter(&sf->sf_cmd_mutex);
5797 	sf->sf_ncmds = ncmds;
5798 	sf_throttle_start(sf);
5799 	mutex_exit(&sf->sf_cmd_mutex);
5800 
5801 	if (!msg1 && !msg2)
5802 		SF_DEBUG(6, (sf, CE_NOTE, "Completing pkt 0x%p\n",
5803 		    (void *)pkt));
5804 	if (pkt->pkt_comp != NULL) {
5805 		(*pkt->pkt_comp)(pkt);
5806 	}
5807 }
5808 
5809 #undef	SF_DMSG1
5810 
5811 
5812 
5813 /*
5814  * start throttling for this instance
5815  */
5816 static void
sf_throttle_start(struct sf * sf)5817 sf_throttle_start(struct sf *sf)
5818 {
5819 	struct sf_pkt *cmd, *prev_cmd = NULL;
5820 	struct scsi_pkt *pkt;
5821 	struct sf_target *target;
5822 
5823 
5824 	ASSERT(mutex_owned(&sf->sf_cmd_mutex));
5825 
5826 	cmd = sf->sf_pkt_head;
5827 	while ((cmd != NULL) &&
5828 	    (sf->sf_state == SF_STATE_ONLINE) &&
5829 	    (sf->sf_ncmds < sf->sf_throttle)) {
5830 
5831 		pkt = CMD2PKT(cmd);
5832 
5833 		target = ADDR2TARGET(&pkt->pkt_address);
5834 		if (target->sft_state & SF_TARGET_BUSY) {
5835 			/* this command is busy -- go to next */
5836 			ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5837 			prev_cmd = cmd;
5838 			cmd = cmd->cmd_next;
5839 			continue;
5840 		}
5841 
5842 		ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5843 
5844 		/* this cmd not busy and not issued */
5845 
5846 		/* remove this packet from the queue */
5847 		if (sf->sf_pkt_head == cmd) {
5848 			/* this was the first packet */
5849 			sf->sf_pkt_head = cmd->cmd_next;
5850 		} else if (sf->sf_pkt_tail == cmd) {
5851 			/* this was the last packet */
5852 			sf->sf_pkt_tail = prev_cmd;
5853 			if (prev_cmd != NULL) {
5854 				prev_cmd->cmd_next = NULL;
5855 			}
5856 		} else {
5857 			/* some packet in the middle of the queue */
5858 			ASSERT(prev_cmd != NULL);
5859 			prev_cmd->cmd_next = cmd->cmd_next;
5860 		}
5861 		cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
5862 
5863 		if (target->sft_state & SF_TARGET_OFFLINE) {
5864 			mutex_exit(&sf->sf_cmd_mutex);
5865 			pkt->pkt_reason = CMD_TRAN_ERR;
5866 			if (pkt->pkt_comp != NULL) {
5867 				(*pkt->pkt_comp)(cmd->cmd_pkt);
5868 			}
5869 		} else {
5870 			sf_fill_ids(sf, cmd, target);
5871 			if (sf_start_internal(sf, cmd) != TRAN_ACCEPT) {
5872 				pkt->pkt_reason = CMD_TRAN_ERR;
5873 				if (pkt->pkt_comp != NULL) {
5874 					(*pkt->pkt_comp)(cmd->cmd_pkt);
5875 				}
5876 			}
5877 		}
5878 		mutex_enter(&sf->sf_cmd_mutex);
5879 		cmd = sf->sf_pkt_head;
5880 		prev_cmd = NULL;
5881 	}
5882 }
5883 
5884 
5885 /*
5886  * called when the max exchange value is exceeded to throttle back commands
5887  */
5888 static void
sf_throttle(struct sf * sf)5889 sf_throttle(struct sf *sf)
5890 {
5891 	int cmdmax = sf->sf_sochandle->fcal_cmdmax;
5892 
5893 
5894 	mutex_enter(&sf->sf_cmd_mutex);
5895 
5896 	sf->sf_flag = TRUE;
5897 
5898 	if (sf->sf_ncmds > (cmdmax / 2)) {
5899 		sf->sf_throttle = cmdmax / 2;
5900 	} else {
5901 		if (sf->sf_ncmds > SF_DECR_DELTA) {
5902 			sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
5903 		} else {
5904 			/*
5905 			 * This case is just a safeguard, should not really
5906 			 * happen(ncmds < SF_DECR_DELTA and MAX_EXCHG exceed
5907 			 */
5908 			sf->sf_throttle = SF_DECR_DELTA;
5909 		}
5910 	}
5911 	mutex_exit(&sf->sf_cmd_mutex);
5912 
5913 	sf = sf->sf_sibling;
5914 	if (sf != NULL) {
5915 		mutex_enter(&sf->sf_cmd_mutex);
5916 		sf->sf_flag = TRUE;
5917 		if (sf->sf_ncmds >= (cmdmax / 2)) {
5918 			sf->sf_throttle = cmdmax / 2;
5919 		} else {
5920 			if (sf->sf_ncmds > SF_DECR_DELTA) {
5921 				sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
5922 			} else {
5923 				sf->sf_throttle = SF_DECR_DELTA;
5924 			}
5925 		}
5926 
5927 		mutex_exit(&sf->sf_cmd_mutex);
5928 	}
5929 }
5930 
5931 
5932 /*
5933  * sf watchdog routine, called for a timeout
5934  */
5935 /*ARGSUSED*/
5936 static void
sf_watch(void * arg)5937 sf_watch(void *arg)
5938 {
5939 	struct sf *sf;
5940 	struct sf_els_hdr	*privp;
5941 	static int count = 0, pscan_count = 0;
5942 	int cmdmax, i, mescount = 0;
5943 	struct sf_target *target;
5944 
5945 
5946 	sf_watchdog_time += sf_watchdog_timeout;
5947 	count++;
5948 	pscan_count++;
5949 
5950 	mutex_enter(&sf_global_mutex);
5951 	sf_watch_running = 1;
5952 	for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
5953 
5954 		mutex_exit(&sf_global_mutex);
5955 
5956 		/* disable throttling while we're suspended */
5957 		mutex_enter(&sf->sf_mutex);
5958 		if (sf->sf_state & SF_STATE_SUSPENDED) {
5959 			mutex_exit(&sf->sf_mutex);
5960 			SF_DEBUG(1, (sf, CE_CONT,
5961 			    "sf_watch, sf%d:throttle disabled "
5962 			    "due to DDI_SUSPEND\n",
5963 			    ddi_get_instance(sf->sf_dip)));
5964 			mutex_enter(&sf_global_mutex);
5965 			continue;
5966 		}
5967 		mutex_exit(&sf->sf_mutex);
5968 
5969 		cmdmax = sf->sf_sochandle->fcal_cmdmax;
5970 
5971 		if (sf->sf_take_core) {
5972 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
5973 		}
5974 
5975 		mutex_enter(&sf->sf_cmd_mutex);
5976 
5977 		if (!sf->sf_flag) {
5978 			if (sf->sf_throttle < (cmdmax / 2)) {
5979 				sf->sf_throttle = cmdmax / 2;
5980 			} else if ((sf->sf_throttle += SF_INCR_DELTA) >
5981 			    cmdmax) {
5982 				sf->sf_throttle = cmdmax;
5983 			}
5984 		} else {
5985 			sf->sf_flag = FALSE;
5986 		}
5987 
5988 		sf->sf_ncmds_exp_avg = (sf->sf_ncmds + sf->sf_ncmds_exp_avg)
5989 		    >> 2;
5990 		if ((sf->sf_ncmds <= (sf->sf_throttle - SF_LO_CMD_DELTA)) &&
5991 		    (sf->sf_pkt_head == NULL)) {
5992 #ifdef DEBUG
5993 			if (sf->sf_use_lock) {
5994 				SF_DEBUG(4, (sf, CE_NOTE,
5995 				    "use lock flag off\n"));
5996 			}
5997 #endif
5998 			sf->sf_use_lock = FALSE;
5999 		}
6000 
6001 		if (sf->sf_state == SF_STATE_ONLINE && sf->sf_pkt_head &&
6002 		    sf->sf_ncmds < sf->sf_throttle) {
6003 			sf_throttle_start(sf);
6004 		}
6005 
6006 		mutex_exit(&sf->sf_cmd_mutex);
6007 
6008 		if (pscan_count >= sf_pool_scan_cnt) {
6009 			if (sf->sf_ncmds_exp_avg < (sf->sf_cr_pool_cnt <<
6010 			    SF_LOG2_ELEMS_IN_POOL) - SF_FREE_CR_EPSILON) {
6011 				sf_crpool_free(sf);
6012 			}
6013 		}
6014 		mutex_enter(&sf->sf_mutex);
6015 
6016 		privp = sf->sf_els_list;
6017 		while (privp != NULL) {
6018 			if (privp->timeout < sf_watchdog_time) {
6019 				/* timeout this command */
6020 				privp = sf_els_timeout(sf, privp);
6021 			} else if ((privp->timeout == SF_INVALID_TIMEOUT) &&
6022 			    (privp->lip_cnt != sf->sf_lip_cnt)) {
6023 				if (privp->prev != NULL) {
6024 					privp->prev->next = privp->next;
6025 				}
6026 				if (sf->sf_els_list == privp) {
6027 					sf->sf_els_list = privp->next;
6028 				}
6029 				if (privp->next != NULL) {
6030 					privp->next->prev = privp->prev;
6031 				}
6032 				mutex_exit(&sf->sf_mutex);
6033 				sf_els_free(privp->fpkt);
6034 				mutex_enter(&sf->sf_mutex);
6035 				privp = sf->sf_els_list;
6036 			} else {
6037 				privp = privp->next;
6038 			}
6039 		}
6040 
6041 		if (sf->sf_online_timer && sf->sf_online_timer <
6042 		    sf_watchdog_time) {
6043 			for (i = 0; i < sf_max_targets; i++) {
6044 				target = sf->sf_targets[i];
6045 				if (target != NULL) {
6046 					if (!mescount && target->sft_state &
6047 					    SF_TARGET_BUSY) {
6048 						sf_log(sf, CE_WARN, "!Loop "
6049 						    "Unstable: Failed to bring "
6050 						    "Loop Online\n");
6051 						mescount = 1;
6052 					}
6053 					target->sft_state |= SF_TARGET_MARK;
6054 				}
6055 			}
6056 			sf_finish_init(sf, sf->sf_lip_cnt);
6057 			sf->sf_state = SF_STATE_INIT;
6058 			sf->sf_online_timer = 0;
6059 		}
6060 
6061 		if (sf->sf_state == SF_STATE_ONLINE) {
6062 			mutex_exit(&sf->sf_mutex);
6063 			if (count >= sf_pkt_scan_cnt) {
6064 				sf_check_targets(sf);
6065 			}
6066 		} else if ((sf->sf_state == SF_STATE_OFFLINE) &&
6067 		    (sf->sf_timer < sf_watchdog_time)) {
6068 			for (i = 0; i < sf_max_targets; i++) {
6069 				target = sf->sf_targets[i];
6070 				if ((target != NULL) &&
6071 				    (target->sft_state &
6072 				    SF_TARGET_BUSY)) {
6073 					sf_log(sf, CE_WARN,
6074 					    "!Offline Timeout\n");
6075 					if (sf_core && (sf_core &
6076 					    SF_CORE_OFFLINE_TIMEOUT)) {
6077 						(void) soc_take_core(
6078 						    sf->sf_sochandle,
6079 						    sf->sf_socp);
6080 						sf_core = 0;
6081 					}
6082 					break;
6083 				}
6084 			}
6085 			sf_finish_init(sf, sf->sf_lip_cnt);
6086 			sf->sf_state = SF_STATE_INIT;
6087 			mutex_exit(&sf->sf_mutex);
6088 		} else {
6089 			mutex_exit(&sf->sf_mutex);
6090 		}
6091 		mutex_enter(&sf_global_mutex);
6092 	}
6093 	mutex_exit(&sf_global_mutex);
6094 	if (count >= sf_pkt_scan_cnt) {
6095 		count = 0;
6096 	}
6097 	if (pscan_count >= sf_pool_scan_cnt) {
6098 		pscan_count = 0;
6099 	}
6100 
6101 	/* reset timeout */
6102 	sf_watchdog_id = timeout(sf_watch, (caddr_t)0, sf_watchdog_tick);
6103 
6104 	/* signal waiting thread */
6105 	mutex_enter(&sf_global_mutex);
6106 	sf_watch_running = 0;
6107 	cv_broadcast(&sf_watch_cv);
6108 	mutex_exit(&sf_global_mutex);
6109 }
6110 
6111 
6112 /*
6113  * called during a timeout to check targets
6114  */
6115 static void
sf_check_targets(struct sf * sf)6116 sf_check_targets(struct sf *sf)
6117 {
6118 	struct sf_target *target;
6119 	int i;
6120 	struct sf_pkt *cmd;
6121 	struct scsi_pkt *pkt;
6122 	int lip_cnt;
6123 
6124 	mutex_enter(&sf->sf_mutex);
6125 	lip_cnt = sf->sf_lip_cnt;
6126 	mutex_exit(&sf->sf_mutex);
6127 
6128 	/* check scan all possible targets */
6129 	for (i = 0; i < sf_max_targets; i++) {
6130 		target = sf->sf_targets[i];
6131 		while (target != NULL) {
6132 			mutex_enter(&target->sft_pkt_mutex);
6133 			if (target->sft_alive && target->sft_scan_count !=
6134 			    sf_target_scan_cnt) {
6135 				target->sft_alive = 0;
6136 				target->sft_scan_count++;
6137 				mutex_exit(&target->sft_pkt_mutex);
6138 				return;
6139 			}
6140 			target->sft_alive = 0;
6141 			target->sft_scan_count = 0;
6142 			cmd = target->sft_pkt_head;
6143 			while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
6144 				mutex_enter(&cmd->cmd_abort_mutex);
6145 				if (cmd->cmd_state == SF_STATE_ISSUED &&
6146 				    ((cmd->cmd_timeout && sf_watchdog_time >
6147 #ifdef	DEBUG
6148 				    cmd->cmd_timeout) || sf_abort_flag)) {
6149 					sf_abort_flag = 0;
6150 #else
6151 					cmd->cmd_timeout))) {
6152 #endif
6153 					cmd->cmd_timeout = 0;
6154 	/* prevent reset from getting at this packet */
6155 					cmd->cmd_state = SF_STATE_ABORTING;
6156 					mutex_exit(&cmd->cmd_abort_mutex);
6157 					mutex_exit(&target->sft_pkt_mutex);
6158 					sf->sf_stats.tstats[i].timeouts++;
6159 					if (sf_target_timeout(sf, cmd))
6160 						return;
6161 					else {
6162 						if (lip_cnt != sf->sf_lip_cnt) {
6163 							return;
6164 						} else {
6165 							mutex_enter(&target->
6166 							    sft_pkt_mutex);
6167 							cmd = target->
6168 							    sft_pkt_head;
6169 						}
6170 					}
6171 	/*
6172 	 * if the abort and lip fail, a reset will be carried out.
6173 	 * But the reset will ignore this packet. We have waited at least
6174 	 * 20 seconds after the initial timeout. Now, complete it here.
6175 	 * This also takes care of spurious bad aborts.
6176 	 */
6177 				} else if ((cmd->cmd_state ==
6178 				    SF_STATE_ABORTING) && (cmd->cmd_timeout
6179 				    <= sf_watchdog_time)) {
6180 					cmd->cmd_state = SF_STATE_IDLE;
6181 					mutex_exit(&cmd->cmd_abort_mutex);
6182 					mutex_exit(&target->sft_pkt_mutex);
6183 					SF_DEBUG(1, (sf, CE_NOTE,
6184 					    "Command 0x%p to sft 0x%p"
6185 					    " delayed release\n",
6186 					    (void *)cmd, (void *)target));
6187 					pkt = cmd->cmd_pkt;
6188 					pkt->pkt_statistics |=
6189 					    (STAT_TIMEOUT|STAT_ABORTED);
6190 					pkt->pkt_reason = CMD_TIMEOUT;
6191 					if (pkt->pkt_comp) {
6192 						scsi_hba_pkt_comp(pkt);
6193 					/* handle deferred_destroy case */
6194 					} else {
6195 						if ((cmd->cmd_block->fcp_cntl.
6196 						    cntl_reset == 1) ||
6197 						    (cmd->cmd_block->
6198 						    fcp_cntl.cntl_abort_tsk ==
6199 						    1)) {
6200 							cmd->cmd_block->
6201 							    fcp_cntl.
6202 							    cntl_reset = 0;
6203 							cmd->cmd_block->
6204 							    fcp_cntl.
6205 							    cntl_abort_tsk = 0;
6206 							cmd->cmd_fp_pkt->
6207 							    fcal_pkt_comp =
6208 							    sf_cmd_callback;
6209 							/* for cache */
6210 							sf_scsi_destroy_pkt
6211 							    (&pkt->pkt_address,
6212 							    pkt);
6213 						}
6214 					}
6215 					mutex_enter(&target->sft_pkt_mutex);
6216 					cmd = target->sft_pkt_head;
6217 				} else {
6218 					mutex_exit(&cmd->cmd_abort_mutex);
6219 					cmd = cmd->cmd_forw;
6220 				}
6221 			}
6222 			mutex_exit(&target->sft_pkt_mutex);
6223 			target = target->sft_next_lun;
6224 		}
6225 	}
6226 }
6227 
6228 
6229 /*
6230  * a command to a target has timed out
6231  * return TRUE iff cmd abort failed or timed out, else return FALSE
6232  */
6233 static int
6234 sf_target_timeout(struct sf *sf, struct sf_pkt *cmd)
6235 {
6236 	int rval;
6237 	struct scsi_pkt *pkt;
6238 	struct fcal_packet *fpkt;
6239 	int tgt_id;
6240 	int retval = FALSE;
6241 
6242 
6243 	SF_DEBUG(1, (sf, CE_NOTE, "Command 0x%p to target %x timed out\n",
6244 	    (void *)cmd->cmd_fp_pkt, cmd->cmd_pkt->pkt_address.a_target));
6245 
6246 	fpkt = cmd->cmd_fp_pkt;
6247 
6248 	if (sf_core && (sf_core & SF_CORE_CMD_TIMEOUT)) {
6249 		sf_token = (int *)(uintptr_t)
6250 		    fpkt->fcal_socal_request.sr_soc_hdr.\
6251 		    sh_request_token;
6252 		(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6253 		sf_core = 0;
6254 	}
6255 
6256 	/* call the transport to abort a command */
6257 	rval = soc_abort(sf->sf_sochandle, sf->sf_socp,
6258 	    sf->sf_sochandle->fcal_portno, fpkt, 1);
6259 
6260 	switch (rval) {
6261 	case FCAL_ABORTED:
6262 		SF_DEBUG(1, (sf, CE_NOTE, "Command Abort succeeded\n"));
6263 		pkt = cmd->cmd_pkt;
6264 		cmd->cmd_state = SF_STATE_IDLE;
6265 		pkt->pkt_statistics |= (STAT_TIMEOUT|STAT_ABORTED);
6266 		pkt->pkt_reason = CMD_TIMEOUT;
6267 		if (pkt->pkt_comp != NULL) {
6268 			(*pkt->pkt_comp)(pkt);
6269 		}
6270 		break;				/* success */
6271 
6272 	case FCAL_ABORT_FAILED:
6273 		SF_DEBUG(1, (sf, CE_NOTE, "Command Abort failed at target\n"));
6274 		pkt = cmd->cmd_pkt;
6275 		cmd->cmd_state = SF_STATE_IDLE;
6276 		pkt->pkt_reason = CMD_TIMEOUT;
6277 		pkt->pkt_statistics |= STAT_TIMEOUT;
6278 		tgt_id = pkt->pkt_address.a_target;
6279 		sf->sf_stats.tstats[tgt_id].abts_failures++;
6280 		if (pkt->pkt_comp != NULL) {
6281 			(*pkt->pkt_comp)(pkt);
6282 		}
6283 		break;
6284 
6285 	case FCAL_BAD_ABORT:
6286 		if (sf_core && (sf_core & SF_CORE_BAD_ABORT)) {
6287 			sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6288 			    sr_soc_hdr.sh_request_token;
6289 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6290 			sf_core = 0;
6291 		}
6292 		SF_DEBUG(1, (sf, CE_NOTE, "Command Abort bad abort\n"));
6293 		cmd->cmd_timeout = sf_watchdog_time + cmd->cmd_pkt->pkt_time
6294 		    + 20;
6295 		break;
6296 
6297 	case FCAL_TIMEOUT:
6298 		retval = TRUE;
6299 		break;
6300 
6301 	default:
6302 		pkt = cmd->cmd_pkt;
6303 		tgt_id = pkt->pkt_address.a_target;
6304 		sf_log(sf, CE_WARN,
6305 		"Command Abort failed target 0x%x, forcing a LIP\n", tgt_id);
6306 		if (sf_core && (sf_core & SF_CORE_ABORT_TIMEOUT)) {
6307 			sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6308 			    sr_soc_hdr.sh_request_token;
6309 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6310 			sf_core = 0;
6311 		}
6312 		sf_force_lip(sf);
6313 		retval = TRUE;
6314 		break;
6315 	}
6316 
6317 	return (retval);
6318 }
6319 
6320 
6321 /*
6322  * an ELS command has timed out
6323  * return ???
6324  */
6325 static struct sf_els_hdr *
6326 sf_els_timeout(struct sf *sf, struct sf_els_hdr *privp)
6327 {
6328 	struct fcal_packet *fpkt;
6329 	int rval, dflag, timeout = SF_ELS_TIMEOUT;
6330 	uint_t lip_cnt = privp->lip_cnt;
6331 	uchar_t els_code = privp->els_code;
6332 	struct sf_target *target = privp->target;
6333 	char what[64];
6334 
6335 	fpkt = privp->fpkt;
6336 	dflag = privp->delayed_retry;
6337 	/* use as temporary state variable */
6338 	privp->timeout = SF_INVALID_TIMEOUT;
6339 	mutex_exit(&sf->sf_mutex);
6340 
6341 	if (privp->fpkt->fcal_pkt_comp == sf_els_callback) {
6342 		/*
6343 		 * take socal core if required. Timeouts for IB and hosts
6344 		 * are not very interesting, so we take socal core only
6345 		 * if the timeout is *not* for a IB or host.
6346 		 */
6347 		if (sf_core && (sf_core & SF_CORE_ELS_TIMEOUT) &&
6348 		    ((sf_alpa_to_switch[privp->dest_nport_id] &
6349 		    0x0d) != 0x0d) && ((privp->dest_nport_id != 1) ||
6350 		    (privp->dest_nport_id != 2) ||
6351 		    (privp->dest_nport_id != 4) ||
6352 		    (privp->dest_nport_id != 8) ||
6353 		    (privp->dest_nport_id != 0xf))) {
6354 			sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6355 			    sr_soc_hdr.sh_request_token;
6356 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6357 			sf_core = 0;
6358 		}
6359 		(void) sprintf(what, "ELS 0x%x", privp->els_code);
6360 	} else if (privp->fpkt->fcal_pkt_comp == sf_reportlun_callback) {
6361 		if (sf_core && (sf_core & SF_CORE_REPORTLUN_TIMEOUT)) {
6362 			sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6363 			    sr_soc_hdr.sh_request_token;
6364 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6365 			sf_core = 0;
6366 		}
6367 		timeout = SF_FCP_TIMEOUT;
6368 		(void) sprintf(what, "REPORT_LUNS");
6369 	} else if (privp->fpkt->fcal_pkt_comp == sf_inq_callback) {
6370 		if (sf_core && (sf_core & SF_CORE_INQUIRY_TIMEOUT)) {
6371 			sf_token = (int *)(uintptr_t)
6372 			    fpkt->fcal_socal_request.\
6373 			    sr_soc_hdr.sh_request_token;
6374 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6375 			sf_core = 0;
6376 		}
6377 		timeout = SF_FCP_TIMEOUT;
6378 		(void) sprintf(what, "INQUIRY to LUN 0x%lx",
6379 		    (long)SCSA_LUN(target));
6380 	} else {
6381 		(void) sprintf(what, "UNKNOWN OPERATION");
6382 	}
6383 
6384 	if (dflag) {
6385 		/* delayed retry */
6386 		SF_DEBUG(2, (sf, CE_CONT,
6387 		    "!sf%d: %s to target %x delayed retry\n",
6388 		    ddi_get_instance(sf->sf_dip), what,
6389 		    sf_alpa_to_switch[privp->dest_nport_id]));
6390 		privp->delayed_retry = FALSE;
6391 		goto try_again;
6392 	}
6393 
6394 	sf_log(sf, CE_NOTE, "!%s to target 0x%x alpa 0x%x timed out\n",
6395 	    what, sf_alpa_to_switch[privp->dest_nport_id],
6396 	    privp->dest_nport_id);
6397 
6398 	rval = soc_abort(sf->sf_sochandle, sf->sf_socp, sf->sf_sochandle
6399 	    ->fcal_portno, fpkt, 1);
6400 	if (rval == FCAL_ABORTED || rval == FCAL_ABORT_FAILED) {
6401 	SF_DEBUG(1, (sf, CE_NOTE, "!%s abort to al_pa %x succeeded\n",
6402 	    what, privp->dest_nport_id));
6403 try_again:
6404 
6405 		mutex_enter(&sf->sf_mutex);
6406 		if (privp->prev != NULL) {
6407 			privp->prev->next = privp->next;
6408 		}
6409 		if (sf->sf_els_list == privp) {
6410 			sf->sf_els_list = privp->next;
6411 		}
6412 		if (privp->next != NULL) {
6413 			privp->next->prev = privp->prev;
6414 		}
6415 		privp->prev = privp->next = NULL;
6416 		if (lip_cnt == sf->sf_lip_cnt) {
6417 			privp->timeout = sf_watchdog_time + timeout;
6418 			if ((++(privp->retries) < sf_els_retries) ||
6419 			    (dflag && (privp->retries < SF_BSY_RETRIES))) {
6420 				mutex_exit(&sf->sf_mutex);
6421 				sf_log(sf, CE_NOTE,
6422 				    "!%s to target 0x%x retrying\n",
6423 				    what,
6424 				    sf_alpa_to_switch[privp->dest_nport_id]);
6425 				if (sf_els_transport(sf, privp) == 1) {
6426 					mutex_enter(&sf->sf_mutex);
6427 					return (sf->sf_els_list); /* success */
6428 				}
6429 				mutex_enter(&sf->sf_mutex);
6430 				fpkt = NULL;
6431 			}
6432 			if ((lip_cnt == sf->sf_lip_cnt) &&
6433 			    (els_code != LA_ELS_LOGO)) {
6434 				if (target != NULL) {
6435 					sf_offline_target(sf, target);
6436 				}
6437 				if (sf->sf_lip_cnt == lip_cnt) {
6438 					sf->sf_device_count--;
6439 					ASSERT(sf->sf_device_count >= 0);
6440 					if (sf->sf_device_count == 0) {
6441 						sf_finish_init(sf,
6442 						    sf->sf_lip_cnt);
6443 					}
6444 				}
6445 			}
6446 			privp = sf->sf_els_list;
6447 			mutex_exit(&sf->sf_mutex);
6448 			if (fpkt != NULL) {
6449 				sf_els_free(fpkt);
6450 			}
6451 		} else {
6452 			mutex_exit(&sf->sf_mutex);
6453 			sf_els_free(privp->fpkt);
6454 			privp = NULL;
6455 		}
6456 	} else {
6457 		if (sf_core && (sf_core & SF_CORE_ELS_FAILED)) {
6458 			sf_token = (int *)(uintptr_t)
6459 			    fpkt->fcal_socal_request.\
6460 			    sr_soc_hdr.sh_request_token;
6461 			(void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6462 			sf_core = 0;
6463 		}
6464 		sf_log(sf, CE_NOTE, "%s abort to target 0x%x failed. "
6465 		    "status=0x%x, forcing LIP\n", what,
6466 		    sf_alpa_to_switch[privp->dest_nport_id], rval);
6467 		privp = NULL;
6468 		if (sf->sf_lip_cnt == lip_cnt) {
6469 			sf_force_lip(sf);
6470 		}
6471 	}
6472 
6473 	mutex_enter(&sf->sf_mutex);
6474 	return (privp);
6475 }
6476 
6477 
6478 /*
6479  * called by timeout when a reset times out
6480  */
6481 /*ARGSUSED*/
6482 static void
6483 sf_check_reset_delay(void *arg)
6484 {
6485 	struct sf *sf;
6486 	struct sf_target *target;
6487 	struct sf_reset_list *rp, *tp;
6488 	uint_t lip_cnt, reset_timeout_flag = FALSE;
6489 	clock_t lb;
6490 
6491 	lb = ddi_get_lbolt();
6492 
6493 	mutex_enter(&sf_global_mutex);
6494 
6495 	sf_reset_timeout_id = 0;
6496 
6497 	for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
6498 
6499 		mutex_exit(&sf_global_mutex);
6500 		mutex_enter(&sf->sf_mutex);
6501 
6502 		/* is this type cast needed? */
6503 		tp = (struct sf_reset_list *)&sf->sf_reset_list;
6504 
6505 		rp = sf->sf_reset_list;
6506 		while (rp != NULL) {
6507 			if (((rp->timeout - lb) < 0) &&
6508 			    (rp->lip_cnt == sf->sf_lip_cnt)) {
6509 				tp->next = rp->next;
6510 				mutex_exit(&sf->sf_mutex);
6511 				target = rp->target;
6512 				lip_cnt = rp->lip_cnt;
6513 				kmem_free(rp, sizeof (struct sf_reset_list));
6514 				/* abort all cmds for this target */
6515 				while (target) {
6516 					sf_abort_all(sf, target, FALSE,
6517 					    lip_cnt, TRUE);
6518 					mutex_enter(&target->sft_mutex);
6519 					if (lip_cnt == sf->sf_lip_cnt) {
6520 						target->sft_state &=
6521 						    ~SF_TARGET_BUSY;
6522 					}
6523 					mutex_exit(&target->sft_mutex);
6524 					target = target->sft_next_lun;
6525 				}
6526 				mutex_enter(&sf->sf_mutex);
6527 				tp = (struct sf_reset_list *)
6528 				    &sf->sf_reset_list;
6529 				rp = sf->sf_reset_list;
6530 				lb = ddi_get_lbolt();
6531 			} else if (rp->lip_cnt != sf->sf_lip_cnt) {
6532 				tp->next = rp->next;
6533 				kmem_free(rp, sizeof (struct sf_reset_list));
6534 				rp = tp->next;
6535 			} else {
6536 				reset_timeout_flag = TRUE;
6537 				tp = rp;
6538 				rp = rp->next;
6539 			}
6540 		}
6541 		mutex_exit(&sf->sf_mutex);
6542 		mutex_enter(&sf_global_mutex);
6543 	}
6544 
6545 	if (reset_timeout_flag && (sf_reset_timeout_id == 0)) {
6546 		sf_reset_timeout_id = timeout(sf_check_reset_delay,
6547 		    NULL, drv_usectohz(SF_TARGET_RESET_DELAY));
6548 	}
6549 
6550 	mutex_exit(&sf_global_mutex);
6551 }
6552 
6553 
6554 /*
6555  * called to "reset the bus", i.e. force loop initialization (and address
6556  * re-negotiation)
6557  */
6558 static void
6559 sf_force_lip(struct sf *sf)
6560 {
6561 	int i;
6562 	struct sf_target *target;
6563 
6564 
6565 	/* disable restart of lip if we're suspended */
6566 	mutex_enter(&sf->sf_mutex);
6567 	if (sf->sf_state & SF_STATE_SUSPENDED) {
6568 		mutex_exit(&sf->sf_mutex);
6569 		SF_DEBUG(1, (sf, CE_CONT,
6570 		    "sf_force_lip, sf%d: lip restart disabled "
6571 		    "due to DDI_SUSPEND\n",
6572 		    ddi_get_instance(sf->sf_dip)));
6573 		return;
6574 	}
6575 
6576 	sf_log(sf, CE_NOTE, "Forcing lip\n");
6577 
6578 	for (i = 0; i < sf_max_targets; i++) {
6579 		target = sf->sf_targets[i];
6580 		while (target != NULL) {
6581 			mutex_enter(&target->sft_mutex);
6582 			if (!(target->sft_state & SF_TARGET_OFFLINE))
6583 				target->sft_state |= SF_TARGET_BUSY;
6584 			mutex_exit(&target->sft_mutex);
6585 			target = target->sft_next_lun;
6586 		}
6587 	}
6588 
6589 	sf->sf_lip_cnt++;
6590 	sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
6591 	sf->sf_state = SF_STATE_OFFLINE;
6592 	mutex_exit(&sf->sf_mutex);
6593 	sf->sf_stats.lip_count++;		/* no mutex for this? */
6594 
6595 #ifdef DEBUG
6596 	/* are we allowing LIPs ?? */
6597 	if (sf_lip_flag != 0) {
6598 #endif
6599 		/* call the transport to force loop initialization */
6600 		if (((i = soc_force_lip(sf->sf_sochandle, sf->sf_socp,
6601 		    sf->sf_sochandle->fcal_portno, 1,
6602 		    FCAL_FORCE_LIP)) != FCAL_SUCCESS) &&
6603 		    (i != FCAL_TIMEOUT)) {
6604 			/* force LIP failed */
6605 			if (sf_core && (sf_core & SF_CORE_LIP_FAILED)) {
6606 				(void) soc_take_core(sf->sf_sochandle,
6607 				    sf->sf_socp);
6608 				sf_core = 0;
6609 			}
6610 #ifdef DEBUG
6611 			/* are we allowing reset after LIP failed ?? */
6612 			if (sf_reset_flag != 0) {
6613 #endif
6614 				/* restart socal after resetting it */
6615 				sf_log(sf, CE_NOTE,
6616 				    "!Force lip failed Status code 0x%x."
6617 				    " Reseting\n", i);
6618 				/* call transport to force a reset */
6619 				soc_force_reset(sf->sf_sochandle, sf->sf_socp,
6620 				    sf->sf_sochandle->fcal_portno, 1);
6621 #ifdef	DEBUG
6622 			}
6623 #endif
6624 		}
6625 #ifdef	DEBUG
6626 	}
6627 #endif
6628 }
6629 
6630 
6631 /*
6632  * called by the transport when an unsolicited ELS is received
6633  */
6634 static void
6635 sf_unsol_els_callback(void *arg, soc_response_t *srp, caddr_t payload)
6636 {
6637 	struct sf *sf = (struct sf *)arg;
6638 	els_payload_t	*els = (els_payload_t *)payload;
6639 	struct la_els_rjt *rsp;
6640 	int	i, tgt_id;
6641 	uchar_t dest_id;
6642 	struct fcal_packet *fpkt;
6643 	fc_frame_header_t *hp;
6644 	struct sf_els_hdr *privp;
6645 
6646 
6647 	if ((els == NULL) || ((i = srp->sr_soc_hdr.sh_byte_cnt) == 0)) {
6648 		return;
6649 	}
6650 
6651 	if (i > SOC_CQE_PAYLOAD) {
6652 		i = SOC_CQE_PAYLOAD;
6653 	}
6654 
6655 	dest_id = (uchar_t)srp->sr_fc_frame_hdr.s_id;
6656 	tgt_id = sf_alpa_to_switch[dest_id];
6657 
6658 	switch (els->els_cmd.c.ls_command) {
6659 
6660 	case LA_ELS_LOGO:
6661 		/*
6662 		 * logout received -- log the fact
6663 		 */
6664 		sf->sf_stats.tstats[tgt_id].logouts_recvd++;
6665 		sf_log(sf, CE_NOTE, "!LOGO recvd from target %x, %s\n",
6666 		    tgt_id,
6667 		    sf_lip_on_plogo ? "Forcing LIP...." : "");
6668 		if (sf_lip_on_plogo) {
6669 			sf_force_lip(sf);
6670 		}
6671 		break;
6672 
6673 	default:  /* includes LA_ELS_PLOGI */
6674 		/*
6675 		 * something besides a logout received -- we don't handle
6676 		 * this so send back a reject saying its unsupported
6677 		 */
6678 
6679 		sf_log(sf, CE_NOTE, "!ELS 0x%x recvd from target 0x%x\n",
6680 		    els->els_cmd.c.ls_command, tgt_id);
6681 
6682 
6683 		/* allocate room for a response */
6684 		if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
6685 		    sizeof (struct la_els_rjt), sizeof (union sf_els_rsp),
6686 		    (caddr_t *)&privp, (caddr_t *)&rsp) == NULL) {
6687 			break;
6688 		}
6689 
6690 		fpkt = privp->fpkt;
6691 
6692 		/* fill in pkt header */
6693 		hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
6694 		hp->r_ctl = R_CTL_ELS_RSP;
6695 		hp->f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
6696 		hp->ox_id = srp->sr_fc_frame_hdr.ox_id;
6697 		hp->rx_id = srp->sr_fc_frame_hdr.rx_id;
6698 		fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
6699 		    CQ_TYPE_OUTBOUND;
6700 
6701 		fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 1;
6702 
6703 		/* fill in response */
6704 		rsp->ls_code = LA_ELS_RJT;	/* reject this ELS */
6705 		rsp->mbz[0] = 0;
6706 		rsp->mbz[1] = 0;
6707 		rsp->mbz[2] = 0;
6708 		((struct la_els_logi *)privp->rsp)->ls_code = LA_ELS_ACC;
6709 		*((int *)&rsp->reserved) = 0;
6710 		rsp->reason_code = RJT_UNSUPPORTED;
6711 		privp->retries = sf_els_retries;
6712 		privp->els_code = LA_ELS_RJT;
6713 		privp->timeout = (unsigned)0xffffffff;
6714 		(void) sf_els_transport(sf, privp);
6715 		break;
6716 	}
6717 }
6718 
6719 
6720 /*
6721  * Error logging, printing, and debug print routines
6722  */
6723 
6724 /*PRINTFLIKE3*/
6725 static void
6726 sf_log(struct sf *sf, int level, const char *fmt, ...)
6727 {
6728 	char buf[256];
6729 	dev_info_t *dip;
6730 	va_list ap;
6731 
6732 	if (sf != NULL) {
6733 		dip = sf->sf_dip;
6734 	} else {
6735 		dip = NULL;
6736 	}
6737 
6738 	va_start(ap, fmt);
6739 	(void) vsprintf(buf, fmt, ap);
6740 	va_end(ap);
6741 	scsi_log(dip, "sf", level, buf);
6742 }
6743 
6744 
6745 /*
6746  * called to get some sf kstats -- return 0 on success else return errno
6747  */
6748 static int
6749 sf_kstat_update(kstat_t *ksp, int rw)
6750 {
6751 	struct sf *sf;
6752 
6753 	if (rw == KSTAT_WRITE) {
6754 		/* can't write */
6755 		return (EACCES);
6756 	}
6757 
6758 	sf = ksp->ks_private;
6759 	sf->sf_stats.ncmds = sf->sf_ncmds;
6760 	sf->sf_stats.throttle_limit = sf->sf_throttle;
6761 	sf->sf_stats.cr_pool_size = sf->sf_cr_pool_cnt;
6762 
6763 	return (0);				/* success */
6764 }
6765 
6766 
6767 /*
6768  * Unix Entry Points
6769  */
6770 
6771 /*
6772  * driver entry point for opens on control device
6773  */
6774 /* ARGSUSED */
6775 static int
6776 sf_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
6777 {
6778 	dev_t dev = *dev_p;
6779 	struct sf *sf;
6780 
6781 
6782 	/* just ensure soft state exists for this device */
6783 	sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6784 	if (sf == NULL) {
6785 		return (ENXIO);
6786 	}
6787 
6788 	++(sf->sf_check_n_close);
6789 
6790 	return (0);
6791 }
6792 
6793 
6794 /*
6795  * driver entry point for last close on control device
6796  */
6797 /* ARGSUSED */
6798 static int
6799 sf_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
6800 {
6801 	struct sf *sf;
6802 
6803 	sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6804 	if (sf == NULL) {
6805 		return (ENXIO);
6806 	}
6807 
6808 	if (!sf->sf_check_n_close) { /* if this flag is zero */
6809 		cmn_err(CE_WARN, "sf%d: trying to close unopened instance",
6810 		    SF_MINOR2INST(getminor(dev)));
6811 		return (ENODEV);
6812 	} else {
6813 		--(sf->sf_check_n_close);
6814 	}
6815 	return (0);
6816 }
6817 
6818 
6819 /*
6820  * driver entry point for sf ioctl commands
6821  */
6822 /* ARGSUSED */
6823 static int
6824 sf_ioctl(dev_t dev,
6825     int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p)
6826 {
6827 	struct sf *sf;
6828 	struct sf_target *target;
6829 	uchar_t al_pa;
6830 	struct sf_al_map map;
6831 	int cnt, i;
6832 	int	retval;				/* return value */
6833 	struct devctl_iocdata *dcp;
6834 	dev_info_t *cdip;
6835 	struct scsi_address ap;
6836 	scsi_hba_tran_t *tran;
6837 
6838 
6839 	sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6840 	if (sf == NULL) {
6841 		return (ENXIO);
6842 	}
6843 
6844 	/* handle all ioctls */
6845 	switch (cmd) {
6846 
6847 	/*
6848 	 * We can use the generic implementation for these ioctls
6849 	 */
6850 	case DEVCTL_DEVICE_GETSTATE:
6851 	case DEVCTL_DEVICE_ONLINE:
6852 	case DEVCTL_DEVICE_OFFLINE:
6853 	case DEVCTL_BUS_GETSTATE:
6854 		return (ndi_devctl_ioctl(sf->sf_dip, cmd, arg, mode, 0));
6855 
6856 	/*
6857 	 * return FC map
6858 	 */
6859 	case SFIOCGMAP:
6860 		if ((sf->sf_lilp_map->lilp_magic != FCAL_LILP_MAGIC &&
6861 		    sf->sf_lilp_map->lilp_magic != FCAL_BADLILP_MAGIC) ||
6862 		    sf->sf_state != SF_STATE_ONLINE) {
6863 			retval = ENOENT;
6864 			goto dun;
6865 		}
6866 		mutex_enter(&sf->sf_mutex);
6867 		if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
6868 			int i, j = 0;
6869 
6870 			/* Need to generate a fake lilp map */
6871 			for (i = 0; i < sf_max_targets; i++) {
6872 				if (sf->sf_targets[i])
6873 					sf->sf_lilp_map->lilp_alpalist[j++] =
6874 					    sf->sf_targets[i]->
6875 					    sft_hard_address;
6876 			}
6877 			sf->sf_lilp_map->lilp_length = (uchar_t)j;
6878 		}
6879 		cnt = sf->sf_lilp_map->lilp_length;
6880 		map.sf_count = (short)cnt;
6881 		bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
6882 		    (caddr_t)&map.sf_hba_addr.sf_node_wwn,
6883 		    sizeof (la_wwn_t));
6884 		bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
6885 		    (caddr_t)&map.sf_hba_addr.sf_port_wwn,
6886 		    sizeof (la_wwn_t));
6887 		map.sf_hba_addr.sf_al_pa = sf->sf_al_pa;
6888 		map.sf_hba_addr.sf_hard_address = 0;
6889 		map.sf_hba_addr.sf_inq_dtype = DTYPE_UNKNOWN;
6890 		for (i = 0; i < cnt; i++) {
6891 			al_pa = sf->sf_lilp_map->lilp_alpalist[i];
6892 			map.sf_addr_pair[i].sf_al_pa = al_pa;
6893 			if (al_pa == sf->sf_al_pa) {
6894 				(void) bcopy((caddr_t)&sf->sf_sochandle
6895 				    ->fcal_n_wwn, (caddr_t)&map.
6896 				    sf_addr_pair[i].sf_node_wwn,
6897 				    sizeof (la_wwn_t));
6898 				(void) bcopy((caddr_t)&sf->sf_sochandle
6899 				    ->fcal_p_wwn, (caddr_t)&map.
6900 				    sf_addr_pair[i].sf_port_wwn,
6901 				    sizeof (la_wwn_t));
6902 				map.sf_addr_pair[i].sf_hard_address =
6903 				    al_pa;
6904 				map.sf_addr_pair[i].sf_inq_dtype =
6905 				    DTYPE_PROCESSOR;
6906 				continue;
6907 			}
6908 			target = sf->sf_targets[sf_alpa_to_switch[
6909 			    al_pa]];
6910 			if (target != NULL) {
6911 				mutex_enter(&target->sft_mutex);
6912 				if (!(target->sft_state &
6913 				    (SF_TARGET_OFFLINE |
6914 				    SF_TARGET_BUSY))) {
6915 					bcopy((caddr_t)&target->
6916 					    sft_node_wwn,
6917 					    (caddr_t)&map.sf_addr_pair
6918 					    [i].sf_node_wwn,
6919 					    sizeof (la_wwn_t));
6920 					bcopy((caddr_t)&target->
6921 					    sft_port_wwn,
6922 					    (caddr_t)&map.sf_addr_pair
6923 					    [i].sf_port_wwn,
6924 					    sizeof (la_wwn_t));
6925 					map.sf_addr_pair[i].
6926 					    sf_hard_address
6927 					    = target->sft_hard_address;
6928 					map.sf_addr_pair[i].
6929 					    sf_inq_dtype
6930 					    = target->sft_device_type;
6931 					mutex_exit(&target->sft_mutex);
6932 					continue;
6933 				}
6934 				mutex_exit(&target->sft_mutex);
6935 			}
6936 			bzero((caddr_t)&map.sf_addr_pair[i].
6937 			    sf_node_wwn, sizeof (la_wwn_t));
6938 			bzero((caddr_t)&map.sf_addr_pair[i].
6939 			    sf_port_wwn, sizeof (la_wwn_t));
6940 			map.sf_addr_pair[i].sf_inq_dtype =
6941 			    DTYPE_UNKNOWN;
6942 		}
6943 		mutex_exit(&sf->sf_mutex);
6944 		if (ddi_copyout((caddr_t)&map, (caddr_t)arg,
6945 		    sizeof (struct sf_al_map), mode) != 0) {
6946 			retval = EFAULT;
6947 			goto dun;
6948 		}
6949 		break;
6950 
6951 	/*
6952 	 * handle device control ioctls
6953 	 */
6954 	case DEVCTL_DEVICE_RESET:
6955 		if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) {
6956 			retval = EFAULT;
6957 			goto dun;
6958 		}
6959 		if ((ndi_dc_getname(dcp) == NULL) ||
6960 		    (ndi_dc_getaddr(dcp) == NULL)) {
6961 			ndi_dc_freehdl(dcp);
6962 			retval = EINVAL;
6963 			goto dun;
6964 		}
6965 		cdip = ndi_devi_find(sf->sf_dip,
6966 		    ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
6967 		ndi_dc_freehdl(dcp);
6968 
6969 		if (cdip == NULL) {
6970 			retval = ENXIO;
6971 			goto dun;
6972 		}
6973 
6974 		if ((target = sf_get_target_from_dip(sf, cdip)) == NULL) {
6975 			retval = ENXIO;
6976 			goto dun;
6977 		}
6978 		mutex_enter(&target->sft_mutex);
6979 		if (!(target->sft_state & SF_TARGET_INIT_DONE)) {
6980 			mutex_exit(&target->sft_mutex);
6981 			retval = ENXIO;
6982 			goto dun;
6983 		}
6984 
6985 		/* This is ugly */
6986 		tran = kmem_zalloc(scsi_hba_tran_size(), KM_SLEEP);
6987 		bcopy(target->sft_tran, tran, scsi_hba_tran_size());
6988 		mutex_exit(&target->sft_mutex);
6989 		ap.a_hba_tran = tran;
6990 		ap.a_target = sf_alpa_to_switch[target->sft_al_pa];
6991 		if (sf_reset(&ap, RESET_TARGET) == FALSE) {
6992 			retval = EIO;
6993 		} else {
6994 			retval = 0;
6995 		}
6996 		kmem_free(tran, scsi_hba_tran_size());
6997 		goto dun;
6998 
6999 	case DEVCTL_BUS_QUIESCE:
7000 	case DEVCTL_BUS_UNQUIESCE:
7001 		retval = ENOTSUP;
7002 		goto dun;
7003 
7004 	case DEVCTL_BUS_RESET:
7005 	case DEVCTL_BUS_RESETALL:
7006 		sf_force_lip(sf);
7007 		break;
7008 
7009 	default:
7010 		retval = ENOTTY;
7011 		goto dun;
7012 	}
7013 
7014 	retval = 0;				/* success */
7015 
7016 dun:
7017 	return (retval);
7018 }
7019 
7020 
7021 /*
7022  * get the target given a DIP
7023  */
7024 static struct sf_target *
7025 sf_get_target_from_dip(struct sf *sf, dev_info_t *dip)
7026 {
7027 	int i;
7028 	struct sf_target *target;
7029 
7030 
7031 	/* scan each hash queue for the DIP in question */
7032 	for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
7033 		target = sf->sf_wwn_lists[i];
7034 		while (target != NULL) {
7035 			if (target->sft_dip == dip) {
7036 				return (target); /* success: target found */
7037 			}
7038 			target = target->sft_next;
7039 		}
7040 	}
7041 	return (NULL);				/* failure: target not found */
7042 }
7043 
7044 
7045 /*
7046  * called by the transport to get an event cookie
7047  */
7048 static int
7049 sf_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
7050     ddi_eventcookie_t *event_cookiep)
7051 {
7052 	struct sf *sf;
7053 
7054 	sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7055 	if (sf == NULL) {
7056 		/* can't find instance for this device */
7057 		return (DDI_FAILURE);
7058 	}
7059 
7060 	return (ndi_event_retrieve_cookie(sf->sf_event_hdl, rdip, name,
7061 	    event_cookiep, NDI_EVENT_NOPASS));
7062 
7063 }
7064 
7065 
7066 /*
7067  * called by the transport to add an event callback
7068  */
7069 static int
7070 sf_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
7071     ddi_eventcookie_t eventid, void (*callback)(dev_info_t *dip,
7072     ddi_eventcookie_t event, void *arg, void *impl_data), void *arg,
7073     ddi_callback_id_t *cb_id)
7074 {
7075 	struct sf *sf;
7076 
7077 	sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7078 	if (sf == NULL) {
7079 		/* can't find instance for this device */
7080 		return (DDI_FAILURE);
7081 	}
7082 
7083 	return (ndi_event_add_callback(sf->sf_event_hdl, rdip,
7084 	    eventid, callback, arg, NDI_SLEEP, cb_id));
7085 
7086 }
7087 
7088 
7089 /*
7090  * called by the transport to remove an event callback
7091  */
7092 static int
7093 sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id)
7094 {
7095 	struct sf *sf;
7096 
7097 	sf = ddi_get_soft_state(sf_state, ddi_get_instance(devi));
7098 	if (sf == NULL) {
7099 		/* can't find instance for this device */
7100 		return (DDI_FAILURE);
7101 	}
7102 
7103 	return (ndi_event_remove_callback(sf->sf_event_hdl, cb_id));
7104 }
7105 
7106 
7107 /*
7108  * called by the transport to post an event
7109  */
7110 static int
7111 sf_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
7112     ddi_eventcookie_t eventid, void *impldata)
7113 {
7114 	ddi_eventcookie_t remove_cookie, cookie;
7115 
7116 	/* is this a remove event ?? */
7117 	struct sf *sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7118 	remove_cookie = ndi_event_tag_to_cookie(sf->sf_event_hdl,
7119 	    SF_EVENT_TAG_REMOVE);
7120 
7121 	if (remove_cookie == eventid) {
7122 		struct sf_target *target;
7123 
7124 		/* handle remove event */
7125 
7126 		if (sf == NULL) {
7127 			/* no sf instance for this device */
7128 			return (NDI_FAILURE);
7129 		}
7130 
7131 		/* get the target for this event */
7132 		if ((target = sf_get_target_from_dip(sf, rdip)) != NULL) {
7133 			/*
7134 			 * clear device info for this target and mark as
7135 			 * not done
7136 			 */
7137 			mutex_enter(&target->sft_mutex);
7138 			target->sft_dip = NULL;
7139 			target->sft_state &= ~SF_TARGET_INIT_DONE;
7140 			mutex_exit(&target->sft_mutex);
7141 			return (NDI_SUCCESS); /* event handled */
7142 		}
7143 
7144 		/* no target for this event */
7145 		return (NDI_FAILURE);
7146 	}
7147 
7148 	/* an insertion event */
7149 	if (ndi_busop_get_eventcookie(dip, rdip, FCAL_INSERT_EVENT, &cookie)
7150 	    != NDI_SUCCESS) {
7151 		return (NDI_FAILURE);
7152 	}
7153 
7154 	return (ndi_post_event(dip, rdip, cookie, impldata));
7155 }
7156 
7157 
7158 /*
7159  * the sf hotplug daemon, one thread per sf instance
7160  */
7161 static void
7162 sf_hp_daemon(void *arg)
7163 {
7164 	struct sf *sf = (struct sf *)arg;
7165 	struct sf_hp_elem *elem;
7166 	struct sf_target *target;
7167 	int tgt_id;
7168 	callb_cpr_t cprinfo;
7169 
7170 	CALLB_CPR_INIT(&cprinfo, &sf->sf_hp_daemon_mutex,
7171 	    callb_generic_cpr, "sf_hp_daemon");
7172 
7173 	mutex_enter(&sf->sf_hp_daemon_mutex);
7174 
7175 	do {
7176 		while (sf->sf_hp_elem_head != NULL) {
7177 
7178 			/* save ptr to head of list */
7179 			elem = sf->sf_hp_elem_head;
7180 
7181 			/* take element off of list */
7182 			if (sf->sf_hp_elem_head == sf->sf_hp_elem_tail) {
7183 				/* element only one in list -- list now empty */
7184 				sf->sf_hp_elem_head = NULL;
7185 				sf->sf_hp_elem_tail = NULL;
7186 			} else {
7187 				/* remove element from head of list */
7188 				sf->sf_hp_elem_head = sf->sf_hp_elem_head->next;
7189 			}
7190 
7191 			mutex_exit(&sf->sf_hp_daemon_mutex);
7192 
7193 			switch (elem->what) {
7194 			case SF_ONLINE:
7195 				/* online this target */
7196 				target = elem->target;
7197 				(void) ndi_devi_online(elem->dip, 0);
7198 				(void) ndi_event_retrieve_cookie(
7199 				    sf->sf_event_hdl,
7200 				    target->sft_dip, FCAL_INSERT_EVENT,
7201 				    &sf_insert_eid, NDI_EVENT_NOPASS);
7202 				(void) ndi_event_run_callbacks(sf->sf_event_hdl,
7203 				    target->sft_dip, sf_insert_eid, NULL);
7204 				break;
7205 			case SF_OFFLINE:
7206 				/* offline this target */
7207 				target = elem->target;
7208 				tgt_id = sf_alpa_to_switch[target->sft_al_pa];
7209 				/* don't do NDI_DEVI_REMOVE for now */
7210 				if (ndi_devi_offline(elem->dip, 0) !=
7211 				    NDI_SUCCESS) {
7212 					SF_DEBUG(1, (sf, CE_WARN, "target %x, "
7213 					    "device offline failed", tgt_id));
7214 				} else {
7215 					SF_DEBUG(1, (sf, CE_NOTE, "target %x, "
7216 					    "device offline succeeded\n",
7217 					    tgt_id));
7218 				}
7219 				break;
7220 			}
7221 			kmem_free(elem, sizeof (struct sf_hp_elem));
7222 			mutex_enter(&sf->sf_hp_daemon_mutex);
7223 		}
7224 
7225 		/* if exit is not already signaled */
7226 		if (sf->sf_hp_exit == 0) {
7227 			/* wait to be signaled by work or exit */
7228 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
7229 			cv_wait(&sf->sf_hp_daemon_cv, &sf->sf_hp_daemon_mutex);
7230 			CALLB_CPR_SAFE_END(&cprinfo, &sf->sf_hp_daemon_mutex);
7231 		}
7232 	} while (sf->sf_hp_exit == 0);
7233 
7234 	/* sf_hp_daemon_mutex is dropped by CALLB_CPR_EXIT */
7235 	CALLB_CPR_EXIT(&cprinfo);
7236 	thread_exit();			/* no more hotplug thread */
7237 	/* NOTREACHED */
7238 }
7239