xref: /onnv-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c (revision 11692:8795ed2df6db)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #include <sys/scsi/adapters/pmcs/pmcs.h>
26 
27 #define	PMCS_DRIVER_VERSION	"pmcs HBA device driver"
28 
29 static	char	*pmcs_driver_rev = PMCS_DRIVER_VERSION;
30 
31 /*
32  * Non-DDI Compliant stuff
33  */
34 extern char hw_serial[];
35 
36 /*
37  * Global driver data
38  */
39 void *pmcs_softc_state = NULL;
40 void *pmcs_iport_softstate = NULL;
41 
42 /*
43  * Tracing and Logging info
44  */
45 pmcs_tbuf_t *pmcs_tbuf = NULL;
46 uint32_t pmcs_tbuf_num_elems = 0;
47 pmcs_tbuf_t *pmcs_tbuf_ptr;
48 uint32_t pmcs_tbuf_idx = 0;
49 boolean_t pmcs_tbuf_wrap = B_FALSE;
50 static kmutex_t pmcs_trace_lock;
51 
52 /*
53  * If pmcs_force_syslog value is non-zero, all messages put in the trace log
54  * will also be sent to system log.
55  */
56 int pmcs_force_syslog = 0;
57 int pmcs_console = 0;
58 
59 /*
60  * External References
61  */
62 extern int ncpus_online;
63 
64 /*
65  * Local static data
66  */
67 static int fwlog_level = 3;
68 static int physpeed = PHY_LINK_ALL;
69 static int phymode = PHY_LM_AUTO;
70 static int block_mask = 0;
71 static int phymap_usec = 3 * MICROSEC;
72 static int iportmap_usec = 2 * MICROSEC;
73 
74 #ifdef DEBUG
75 static int debug_mask = 1;
76 #else
77 static int debug_mask = 0;
78 #endif
79 
80 #ifdef DISABLE_MSIX
81 static int disable_msix = 1;
82 #else
83 static int disable_msix = 0;
84 #endif
85 
86 #ifdef DISABLE_MSI
87 static int disable_msi = 1;
88 #else
89 static int disable_msi = 0;
90 #endif
91 
92 static uint16_t maxqdepth = 0xfffe;
93 
94 /*
95  * Local prototypes
96  */
97 static int pmcs_attach(dev_info_t *, ddi_attach_cmd_t);
98 static int pmcs_detach(dev_info_t *, ddi_detach_cmd_t);
99 static int pmcs_unattach(pmcs_hw_t *);
100 static int pmcs_iport_unattach(pmcs_iport_t *);
101 static int pmcs_add_more_chunks(pmcs_hw_t *, unsigned long);
102 static void pmcs_watchdog(void *);
103 static int pmcs_setup_intr(pmcs_hw_t *);
104 static int pmcs_teardown_intr(pmcs_hw_t *);
105 
106 static uint_t pmcs_nonio_ix(caddr_t, caddr_t);
107 static uint_t pmcs_general_ix(caddr_t, caddr_t);
108 static uint_t pmcs_event_ix(caddr_t, caddr_t);
109 static uint_t pmcs_iodone_ix(caddr_t, caddr_t);
110 static uint_t pmcs_fatal_ix(caddr_t, caddr_t);
111 static uint_t pmcs_all_intr(caddr_t, caddr_t);
112 static int pmcs_quiesce(dev_info_t *dip);
113 static boolean_t pmcs_fabricate_wwid(pmcs_hw_t *);
114 
115 static void pmcs_create_phy_stats(pmcs_iport_t *);
116 int pmcs_update_phy_stats(kstat_t *, int);
117 static void pmcs_destroy_phy_stats(pmcs_iport_t *);
118 
119 static void pmcs_fm_fini(pmcs_hw_t *pwp);
120 static void pmcs_fm_init(pmcs_hw_t *pwp);
121 static int pmcs_fm_error_cb(dev_info_t *dip,
122     ddi_fm_error_t *err, const void *impl_data);
123 
124 /*
125  * Local configuration data
126  */
127 static struct dev_ops pmcs_ops = {
128 	DEVO_REV,		/* devo_rev, */
129 	0,			/* refcnt */
130 	ddi_no_info,		/* info */
131 	nulldev,		/* identify */
132 	nulldev,		/* probe */
133 	pmcs_attach,		/* attach */
134 	pmcs_detach,		/* detach */
135 	nodev,			/* reset */
136 	NULL,			/* driver operations */
137 	NULL,			/* bus operations */
138 	ddi_power,		/* power management */
139 	pmcs_quiesce		/* quiesce */
140 };
141 
142 static struct modldrv modldrv = {
143 	&mod_driverops,
144 	PMCS_DRIVER_VERSION,
145 	&pmcs_ops,	/* driver ops */
146 };
147 static struct modlinkage modlinkage = {
148 	MODREV_1, &modldrv, NULL
149 };
150 
151 const ddi_dma_attr_t pmcs_dattr = {
152 	DMA_ATTR_V0,			/* dma_attr version	*/
153 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
154 	0xFFFFFFFFFFFFFFFFull,		/* dma_attr_addr_hi	*/
155 	0x00000000FFFFFFFFull,		/* dma_attr_count_max	*/
156 	0x0000000000000001ull,		/* dma_attr_align	*/
157 	0x00000078,			/* dma_attr_burstsizes	*/
158 	0x00000001,			/* dma_attr_minxfer	*/
159 	0x00000000FFFFFFFFull,		/* dma_attr_maxxfer	*/
160 	0x00000000FFFFFFFFull,		/* dma_attr_seg		*/
161 	1,				/* dma_attr_sgllen 	*/
162 	512,				/* dma_attr_granular 	*/
163 	0				/* dma_attr_flags 	*/
164 };
165 
166 static ddi_device_acc_attr_t rattr = {
167 	DDI_DEVICE_ATTR_V1,
168 	DDI_STRUCTURE_LE_ACC,
169 	DDI_STRICTORDER_ACC,
170 	DDI_DEFAULT_ACC
171 };
172 
173 
174 /*
175  * Attach/Detach functions
176  */
177 
178 int
179 _init(void)
180 {
181 	int ret;
182 
183 	ret = ddi_soft_state_init(&pmcs_softc_state, sizeof (pmcs_hw_t), 1);
184 	if (ret != 0) {
185 		cmn_err(CE_WARN, "?soft state init failed for pmcs");
186 		return (ret);
187 	}
188 
189 	if ((ret = scsi_hba_init(&modlinkage)) != 0) {
190 		cmn_err(CE_WARN, "?scsi_hba_init failed for pmcs");
191 		ddi_soft_state_fini(&pmcs_softc_state);
192 		return (ret);
193 	}
194 
195 	/*
196 	 * Allocate soft state for iports
197 	 */
198 	ret = ddi_soft_state_init(&pmcs_iport_softstate,
199 	    sizeof (pmcs_iport_t), 2);
200 	if (ret != 0) {
201 		cmn_err(CE_WARN, "?iport soft state init failed for pmcs");
202 		ddi_soft_state_fini(&pmcs_softc_state);
203 		return (ret);
204 	}
205 
206 	ret = mod_install(&modlinkage);
207 	if (ret != 0) {
208 		cmn_err(CE_WARN, "?mod_install failed for pmcs (%d)", ret);
209 		scsi_hba_fini(&modlinkage);
210 		ddi_soft_state_fini(&pmcs_iport_softstate);
211 		ddi_soft_state_fini(&pmcs_softc_state);
212 		return (ret);
213 	}
214 
215 	/* Initialize the global trace lock */
216 	mutex_init(&pmcs_trace_lock, NULL, MUTEX_DRIVER, NULL);
217 
218 	return (0);
219 }
220 
221 int
222 _fini(void)
223 {
224 	int ret;
225 	if ((ret = mod_remove(&modlinkage)) != 0) {
226 		return (ret);
227 	}
228 	scsi_hba_fini(&modlinkage);
229 
230 	/* Free pmcs log buffer and destroy the global lock */
231 	if (pmcs_tbuf) {
232 		kmem_free(pmcs_tbuf,
233 		    pmcs_tbuf_num_elems * sizeof (pmcs_tbuf_t));
234 		pmcs_tbuf = NULL;
235 	}
236 	mutex_destroy(&pmcs_trace_lock);
237 
238 	ddi_soft_state_fini(&pmcs_iport_softstate);
239 	ddi_soft_state_fini(&pmcs_softc_state);
240 	return (0);
241 }
242 
243 int
244 _info(struct modinfo *modinfop)
245 {
246 	return (mod_info(&modlinkage, modinfop));
247 }
248 
249 static int
250 pmcs_iport_attach(dev_info_t *dip)
251 {
252 	pmcs_iport_t		*iport;
253 	pmcs_hw_t		*pwp;
254 	scsi_hba_tran_t		*tran;
255 	void			*ua_priv = NULL;
256 	char			*iport_ua;
257 	char			*init_port;
258 	int			hba_inst;
259 	int			inst;
260 
261 	hba_inst = ddi_get_instance(ddi_get_parent(dip));
262 	inst = ddi_get_instance(dip);
263 
264 	pwp = ddi_get_soft_state(pmcs_softc_state, hba_inst);
265 	if (pwp == NULL) {
266 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
267 		    "%s: iport%d attach invoked with NULL parent (HBA) node)",
268 		    __func__, inst);
269 		return (DDI_FAILURE);
270 	}
271 
272 	if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
273 		return (DDI_FAILURE);
274 	}
275 
276 	if ((iport_ua = scsi_hba_iport_unit_address(dip)) == NULL) {
277 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
278 		    "%s: invoked with NULL unit address, inst (%d)",
279 		    __func__, inst);
280 		return (DDI_FAILURE);
281 	}
282 
283 	if (ddi_soft_state_zalloc(pmcs_iport_softstate, inst) != DDI_SUCCESS) {
284 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
285 		    "Failed to alloc soft state for iport %d", inst);
286 		return (DDI_FAILURE);
287 	}
288 
289 	iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
290 	if (iport == NULL) {
291 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
292 		    "cannot get iport soft state");
293 		goto iport_attach_fail1;
294 	}
295 
296 	mutex_init(&iport->lock, NULL, MUTEX_DRIVER,
297 	    DDI_INTR_PRI(pwp->intr_pri));
298 	cv_init(&iport->refcnt_cv, NULL, CV_DEFAULT, NULL);
299 	cv_init(&iport->smp_cv, NULL, CV_DEFAULT, NULL);
300 	mutex_init(&iport->refcnt_lock, NULL, MUTEX_DRIVER,
301 	    DDI_INTR_PRI(pwp->intr_pri));
302 	mutex_init(&iport->smp_lock, NULL, MUTEX_DRIVER,
303 	    DDI_INTR_PRI(pwp->intr_pri));
304 
305 	/* Set some data on the iport handle */
306 	iport->dip = dip;
307 	iport->pwp = pwp;
308 
309 	/* Dup the UA into the iport handle */
310 	iport->ua = strdup(iport_ua);
311 
312 	tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
313 	tran->tran_hba_private = iport;
314 
315 	list_create(&iport->phys, sizeof (pmcs_phy_t),
316 	    offsetof(pmcs_phy_t, list_node));
317 
318 	/*
319 	 * If our unit address is active in the phymap, configure our
320 	 * iport's phylist.
321 	 */
322 	mutex_enter(&iport->lock);
323 	ua_priv = sas_phymap_lookup_uapriv(pwp->hss_phymap, iport->ua);
324 	if (ua_priv) {
325 		/* Non-NULL private data indicates the unit address is active */
326 		iport->ua_state = UA_ACTIVE;
327 		if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
328 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
329 			    "%s: failed to "
330 			    "configure phys on iport handle (0x%p), "
331 			    " unit address [%s]", __func__,
332 			    (void *)iport, iport_ua);
333 			mutex_exit(&iport->lock);
334 			goto iport_attach_fail2;
335 		}
336 	} else {
337 		iport->ua_state = UA_INACTIVE;
338 	}
339 	mutex_exit(&iport->lock);
340 
341 	/* Allocate string-based soft state pool for targets */
342 	iport->tgt_sstate = NULL;
343 	if (ddi_soft_state_bystr_init(&iport->tgt_sstate,
344 	    sizeof (pmcs_xscsi_t), PMCS_TGT_SSTATE_SZ) != 0) {
345 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
346 		    "cannot get iport tgt soft state");
347 		goto iport_attach_fail2;
348 	}
349 
350 	/* Create this iport's target map */
351 	if (pmcs_iport_tgtmap_create(iport) == B_FALSE) {
352 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
353 		    "Failed to create tgtmap on iport %d", inst);
354 		goto iport_attach_fail3;
355 	}
356 
357 	/* Set up the 'initiator-port' DDI property on this iport */
358 	init_port = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
359 	if (pwp->separate_ports) {
360 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
361 		    "%s: separate ports not supported", __func__);
362 	} else {
363 		/* Set initiator-port value to the HBA's base WWN */
364 		(void) scsi_wwn_to_wwnstr(pwp->sas_wwns[0], 1,
365 		    init_port);
366 	}
367 
368 	mutex_enter(&iport->lock);
369 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_STRING,
370 	    SCSI_ADDR_PROP_INITIATOR_PORT, init_port);
371 	kmem_free(init_port, PMCS_MAX_UA_SIZE);
372 
373 	/* Set up a 'num-phys' DDI property for the iport node */
374 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
375 	    &iport->nphy);
376 	mutex_exit(&iport->lock);
377 
378 	/* Create kstats for each of the phys in this port */
379 	pmcs_create_phy_stats(iport);
380 
381 	/*
382 	 * Insert this iport handle into our list and set
383 	 * iports_attached on the HBA node.
384 	 */
385 	rw_enter(&pwp->iports_lock, RW_WRITER);
386 	ASSERT(!list_link_active(&iport->list_node));
387 	list_insert_tail(&pwp->iports, iport);
388 	pwp->iports_attached = 1;
389 	pwp->num_iports++;
390 	rw_exit(&pwp->iports_lock);
391 
392 	pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
393 	    "iport%d attached", inst);
394 	ddi_report_dev(dip);
395 	return (DDI_SUCCESS);
396 
397 	/* teardown and fail */
398 iport_attach_fail3:
399 	ddi_soft_state_bystr_fini(&iport->tgt_sstate);
400 iport_attach_fail2:
401 	list_destroy(&iport->phys);
402 	strfree(iport->ua);
403 	mutex_destroy(&iport->refcnt_lock);
404 	mutex_destroy(&iport->smp_lock);
405 	cv_destroy(&iport->refcnt_cv);
406 	cv_destroy(&iport->smp_cv);
407 	mutex_destroy(&iport->lock);
408 iport_attach_fail1:
409 	ddi_soft_state_free(pmcs_iport_softstate, inst);
410 	return (DDI_FAILURE);
411 }
412 
413 static int
414 pmcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
415 {
416 	scsi_hba_tran_t *tran;
417 	char chiprev, *fwsupport, hw_rev[24], fw_rev[24];
418 	off_t set3size;
419 	int inst, i;
420 	int sm_hba = 1;
421 	int protocol = 0;
422 	int num_phys = 0;
423 	pmcs_hw_t *pwp;
424 	pmcs_phy_t *phyp;
425 	uint32_t num_threads;
426 	char buf[64];
427 
428 	switch (cmd) {
429 	case DDI_ATTACH:
430 		break;
431 
432 	case DDI_PM_RESUME:
433 	case DDI_RESUME:
434 		tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
435 		if (!tran) {
436 			return (DDI_FAILURE);
437 		}
438 		/* No DDI_?_RESUME on iport nodes */
439 		if (scsi_hba_iport_unit_address(dip) != NULL) {
440 			return (DDI_SUCCESS);
441 		}
442 		pwp = TRAN2PMC(tran);
443 		if (pwp == NULL) {
444 			return (DDI_FAILURE);
445 		}
446 
447 		mutex_enter(&pwp->lock);
448 		pwp->suspended = 0;
449 		if (pwp->tq) {
450 			ddi_taskq_resume(pwp->tq);
451 		}
452 		mutex_exit(&pwp->lock);
453 		return (DDI_SUCCESS);
454 
455 	default:
456 		return (DDI_FAILURE);
457 	}
458 
459 	/*
460 	 * If this is an iport node, invoke iport attach.
461 	 */
462 	if (scsi_hba_iport_unit_address(dip) != NULL) {
463 		return (pmcs_iport_attach(dip));
464 	}
465 
466 	/*
467 	 * From here on is attach for the HBA node
468 	 */
469 
470 #ifdef	DEBUG
471 	/*
472 	 * Check to see if this unit is to be disabled.  We can't disable
473 	 * on a per-iport node.  It's either the entire HBA or nothing.
474 	 */
475 	(void) snprintf(buf, sizeof (buf),
476 	    "disable-instance-%d", ddi_get_instance(dip));
477 	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
478 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, buf, 0)) {
479 		cmn_err(CE_NOTE, "pmcs%d: disabled by configuration",
480 		    ddi_get_instance(dip));
481 		return (DDI_FAILURE);
482 	}
483 #endif
484 
485 	/*
486 	 * Allocate softstate
487 	 */
488 	inst = ddi_get_instance(dip);
489 	if (ddi_soft_state_zalloc(pmcs_softc_state, inst) != DDI_SUCCESS) {
490 		cmn_err(CE_WARN, "pmcs%d: Failed to alloc soft state", inst);
491 		return (DDI_FAILURE);
492 	}
493 
494 	pwp = ddi_get_soft_state(pmcs_softc_state, inst);
495 	if (pwp == NULL) {
496 		cmn_err(CE_WARN, "pmcs%d: cannot get soft state", inst);
497 		ddi_soft_state_free(pmcs_softc_state, inst);
498 		return (DDI_FAILURE);
499 	}
500 	pwp->dip = dip;
501 	STAILQ_INIT(&pwp->dq);
502 	STAILQ_INIT(&pwp->cq);
503 	STAILQ_INIT(&pwp->wf);
504 	STAILQ_INIT(&pwp->pf);
505 	/*
506 	 * Create the list for iports
507 	 */
508 	list_create(&pwp->iports, sizeof (pmcs_iport_t),
509 	    offsetof(pmcs_iport_t, list_node));
510 
511 	pwp->state = STATE_PROBING;
512 
513 	/*
514 	 * Get driver.conf properties
515 	 */
516 	pwp->debug_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
517 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-debug-mask",
518 	    debug_mask);
519 	pwp->phyid_block_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
520 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phyid-block-mask",
521 	    block_mask);
522 	pwp->physpeed = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
523 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-physpeed", physpeed);
524 	pwp->phymode = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
525 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phymode", phymode);
526 	pwp->fwlog = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
527 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fwlog", fwlog_level);
528 	if (pwp->fwlog > PMCS_FWLOG_MAX) {
529 		pwp->fwlog = PMCS_FWLOG_MAX;
530 	}
531 
532 	mutex_enter(&pmcs_trace_lock);
533 	if (pmcs_tbuf == NULL) {
534 		/* Allocate trace buffer */
535 		pmcs_tbuf_num_elems = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
536 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-tbuf-num-elems",
537 		    PMCS_TBUF_NUM_ELEMS_DEF);
538 		if ((pmcs_tbuf_num_elems == DDI_PROP_NOT_FOUND) ||
539 		    (pmcs_tbuf_num_elems == 0)) {
540 			pmcs_tbuf_num_elems = PMCS_TBUF_NUM_ELEMS_DEF;
541 		}
542 
543 		pmcs_tbuf = kmem_zalloc(pmcs_tbuf_num_elems *
544 		    sizeof (pmcs_tbuf_t), KM_SLEEP);
545 		pmcs_tbuf_ptr = pmcs_tbuf;
546 		pmcs_tbuf_idx = 0;
547 	}
548 	mutex_exit(&pmcs_trace_lock);
549 
550 	disable_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
551 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msix",
552 	    disable_msix);
553 	disable_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
554 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msi",
555 	    disable_msi);
556 	maxqdepth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
557 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-maxqdepth", maxqdepth);
558 	pwp->fw_force_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
559 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fw-force-update", 0);
560 	if (pwp->fw_force_update == 0) {
561 		pwp->fw_disable_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
562 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
563 		    "pmcs-fw-disable-update", 0);
564 	}
565 	pwp->ioq_depth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
566 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-num-io-qentries",
567 	    PMCS_NQENTRY);
568 
569 	/*
570 	 * Initialize FMA
571 	 */
572 	pwp->dev_acc_attr = pwp->reg_acc_attr = rattr;
573 	pwp->iqp_dma_attr = pwp->oqp_dma_attr =
574 	    pwp->regdump_dma_attr = pwp->cip_dma_attr =
575 	    pwp->fwlog_dma_attr = pmcs_dattr;
576 	pwp->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, pwp->dip,
577 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "fm-capable",
578 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
579 	    DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
580 	pmcs_fm_init(pwp);
581 
582 	/*
583 	 * Map registers
584 	 */
585 	if (pci_config_setup(dip, &pwp->pci_acc_handle)) {
586 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
587 		    "pci config setup failed");
588 		ddi_soft_state_free(pmcs_softc_state, inst);
589 		return (DDI_FAILURE);
590 	}
591 
592 	/*
593 	 * Get the size of register set 3.
594 	 */
595 	if (ddi_dev_regsize(dip, PMCS_REGSET_3, &set3size) != DDI_SUCCESS) {
596 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
597 		    "unable to get size of register set %d", PMCS_REGSET_3);
598 		pci_config_teardown(&pwp->pci_acc_handle);
599 		ddi_soft_state_free(pmcs_softc_state, inst);
600 		return (DDI_FAILURE);
601 	}
602 
603 	/*
604 	 * Map registers
605 	 */
606 	pwp->reg_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
607 
608 	if (ddi_regs_map_setup(dip, PMCS_REGSET_0, (caddr_t *)&pwp->msg_regs,
609 	    0, 0, &pwp->reg_acc_attr, &pwp->msg_acc_handle)) {
610 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
611 		    "failed to map Message Unit registers");
612 		pci_config_teardown(&pwp->pci_acc_handle);
613 		ddi_soft_state_free(pmcs_softc_state, inst);
614 		return (DDI_FAILURE);
615 	}
616 
617 	if (ddi_regs_map_setup(dip, PMCS_REGSET_1, (caddr_t *)&pwp->top_regs,
618 	    0, 0, &pwp->reg_acc_attr, &pwp->top_acc_handle)) {
619 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
620 		    "failed to map TOP registers");
621 		ddi_regs_map_free(&pwp->msg_acc_handle);
622 		pci_config_teardown(&pwp->pci_acc_handle);
623 		ddi_soft_state_free(pmcs_softc_state, inst);
624 		return (DDI_FAILURE);
625 	}
626 
627 	if (ddi_regs_map_setup(dip, PMCS_REGSET_2, (caddr_t *)&pwp->gsm_regs,
628 	    0, 0, &pwp->reg_acc_attr, &pwp->gsm_acc_handle)) {
629 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
630 		    "failed to map GSM registers");
631 		ddi_regs_map_free(&pwp->top_acc_handle);
632 		ddi_regs_map_free(&pwp->msg_acc_handle);
633 		pci_config_teardown(&pwp->pci_acc_handle);
634 		ddi_soft_state_free(pmcs_softc_state, inst);
635 		return (DDI_FAILURE);
636 	}
637 
638 	if (ddi_regs_map_setup(dip, PMCS_REGSET_3, (caddr_t *)&pwp->mpi_regs,
639 	    0, 0, &pwp->reg_acc_attr, &pwp->mpi_acc_handle)) {
640 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
641 		    "failed to map MPI registers");
642 		ddi_regs_map_free(&pwp->top_acc_handle);
643 		ddi_regs_map_free(&pwp->gsm_acc_handle);
644 		ddi_regs_map_free(&pwp->msg_acc_handle);
645 		pci_config_teardown(&pwp->pci_acc_handle);
646 		ddi_soft_state_free(pmcs_softc_state, inst);
647 		return (DDI_FAILURE);
648 	}
649 	pwp->mpibar =
650 	    (((5U << 2) + 0x10) << PMCS_MSGU_MPI_BAR_SHIFT) | set3size;
651 
652 	/*
653 	 * Make sure we can support this card.
654 	 */
655 	pwp->chiprev = pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION);
656 
657 	switch (pwp->chiprev) {
658 	case PMCS_PM8001_REV_A:
659 	case PMCS_PM8001_REV_B:
660 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
661 		    "Rev A/B Card no longer supported");
662 		goto failure;
663 	case PMCS_PM8001_REV_C:
664 		break;
665 	default:
666 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
667 		    "Unknown chip revision (%d)", pwp->chiprev);
668 		goto failure;
669 	}
670 
671 	/*
672 	 * Allocate DMA addressable area for Inbound and Outbound Queue indices
673 	 * that the chip needs to access plus a space for scratch usage
674 	 */
675 	pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
676 	if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pwp->cip_acchdls,
677 	    &pwp->cip_handles, ptob(1), (caddr_t *)&pwp->cip,
678 	    &pwp->ciaddr) == B_FALSE) {
679 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
680 		    "Failed to setup DMA for index/scratch");
681 		goto failure;
682 	}
683 
684 	bzero(pwp->cip, ptob(1));
685 	pwp->scratch = &pwp->cip[PMCS_INDICES_SIZE];
686 	pwp->scratch_dma = pwp->ciaddr + PMCS_INDICES_SIZE;
687 
688 	/*
689 	 * Allocate DMA S/G list chunks
690 	 */
691 	(void) pmcs_add_more_chunks(pwp, ptob(1) * PMCS_MIN_CHUNK_PAGES);
692 
693 	/*
694 	 * Allocate a DMA addressable area for the firmware log (if needed)
695 	 */
696 	if (pwp->fwlog) {
697 		/*
698 		 * Align to event log header and entry size
699 		 */
700 		pwp->fwlog_dma_attr.dma_attr_align = 32;
701 		if (pmcs_dma_setup(pwp, &pwp->fwlog_dma_attr,
702 		    &pwp->fwlog_acchdl,
703 		    &pwp->fwlog_hndl, PMCS_FWLOG_SIZE,
704 		    (caddr_t *)&pwp->fwlogp,
705 		    &pwp->fwaddr) == B_FALSE) {
706 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
707 			    "Failed to setup DMA for fwlog area");
708 			pwp->fwlog = 0;
709 		} else {
710 			bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
711 		}
712 	}
713 
714 	if (pwp->flash_chunk_addr == NULL) {
715 		pwp->regdump_dma_attr.dma_attr_align = PMCS_FLASH_CHUNK_SIZE;
716 		if (pmcs_dma_setup(pwp, &pwp->regdump_dma_attr,
717 		    &pwp->regdump_acchdl,
718 		    &pwp->regdump_hndl, PMCS_FLASH_CHUNK_SIZE,
719 		    (caddr_t *)&pwp->flash_chunkp, &pwp->flash_chunk_addr) ==
720 		    B_FALSE) {
721 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
722 			    "Failed to setup DMA for register dump area");
723 			goto failure;
724 		}
725 		bzero(pwp->flash_chunkp, PMCS_FLASH_CHUNK_SIZE);
726 	}
727 
728 	/*
729 	 * More bits of local initialization...
730 	 */
731 	pwp->tq = ddi_taskq_create(dip, "_tq", 4, TASKQ_DEFAULTPRI, 0);
732 	if (pwp->tq == NULL) {
733 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
734 		    "unable to create worker taskq");
735 		goto failure;
736 	}
737 
738 	/*
739 	 * Cache of structures for dealing with I/O completion callbacks.
740 	 */
741 	(void) snprintf(buf, sizeof (buf), "pmcs_iocomp_cb_cache%d", inst);
742 	pwp->iocomp_cb_cache = kmem_cache_create(buf,
743 	    sizeof (pmcs_iocomp_cb_t), 16, NULL, NULL, NULL, NULL, NULL, 0);
744 
745 	/*
746 	 * Cache of PHY structures
747 	 */
748 	(void) snprintf(buf, sizeof (buf), "pmcs_phy_cache%d", inst);
749 	pwp->phy_cache = kmem_cache_create(buf, sizeof (pmcs_phy_t), 8,
750 	    pmcs_phy_constructor, pmcs_phy_destructor, NULL, (void *)pwp,
751 	    NULL, 0);
752 
753 	/*
754 	 * Allocate space for the I/O completion threads
755 	 */
756 	num_threads = ncpus_online;
757 	if (num_threads > PMCS_MAX_CQ_THREADS) {
758 		num_threads = PMCS_MAX_CQ_THREADS;
759 	}
760 
761 	pwp->cq_info.cq_thr_info = kmem_zalloc(sizeof (pmcs_cq_thr_info_t) *
762 	    num_threads, KM_SLEEP);
763 	pwp->cq_info.cq_threads = num_threads;
764 	pwp->cq_info.cq_next_disp_thr = 0;
765 	pwp->cq_info.cq_stop = B_FALSE;
766 
767 	/*
768 	 * Set the quantum value in clock ticks for the I/O interrupt
769 	 * coalescing timer.
770 	 */
771 	pwp->io_intr_coal.quantum = drv_usectohz(PMCS_QUANTUM_TIME_USECS);
772 
773 	/*
774 	 * We have a delicate dance here. We need to set up
775 	 * interrupts so we know how to set up some OQC
776 	 * tables. However, while we're setting up table
777 	 * access, we may need to flash new firmware and
778 	 * reset the card, which will take some finessing.
779 	 */
780 
781 	/*
782 	 * Set up interrupts here.
783 	 */
784 	switch (pmcs_setup_intr(pwp)) {
785 	case 0:
786 		break;
787 	case EIO:
788 		pwp->stuck = 1;
789 		/* FALLTHROUGH */
790 	default:
791 		goto failure;
792 	}
793 
794 	/*
795 	 * Set these up now becuase they are used to initialize the OQC tables.
796 	 *
797 	 * If we have MSI or MSI-X interrupts set up and we have enough
798 	 * vectors for each OQ, the Outbound Queue vectors can all be the
799 	 * same as the appropriate interrupt routine will have been called
800 	 * and the doorbell register automatically cleared.
801 	 * This keeps us from having to check the Outbound Doorbell register
802 	 * when the routines for these interrupts are called.
803 	 *
804 	 * If we have Legacy INT-X interrupts set up or we didn't have enough
805 	 * MSI/MSI-X vectors to uniquely identify each OQ, we point these
806 	 * vectors to the bits we would like to have set in the Outbound
807 	 * Doorbell register because pmcs_all_intr will read the doorbell
808 	 * register to find out why we have an interrupt and write the
809 	 * corresponding 'clear' bit for that interrupt.
810 	 */
811 
812 	switch (pwp->intr_cnt) {
813 	case 1:
814 		/*
815 		 * Only one vector, so we must check all OQs for MSI.  For
816 		 * INT-X, there's only one vector anyway, so we can just
817 		 * use the outbound queue bits to keep from having to
818 		 * check each queue for each interrupt.
819 		 */
820 		if (pwp->int_type == PMCS_INT_FIXED) {
821 			pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
822 			pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
823 			pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
824 		} else {
825 			pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
826 			pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_IODONE;
827 			pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_IODONE;
828 		}
829 		break;
830 	case 2:
831 		/* With 2, we can at least isolate IODONE */
832 		pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
833 		pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
834 		pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_GENERAL;
835 		break;
836 	case 4:
837 		/* With 4 vectors, everybody gets one */
838 		pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
839 		pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
840 		pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
841 		break;
842 	}
843 
844 	/*
845 	 * Do the first part of setup
846 	 */
847 	if (pmcs_setup(pwp)) {
848 		goto failure;
849 	}
850 	pmcs_report_fwversion(pwp);
851 
852 	/*
853 	 * Now do some additonal allocations based upon information
854 	 * gathered during MPI setup.
855 	 */
856 	pwp->root_phys = kmem_zalloc(pwp->nphy * sizeof (pmcs_phy_t), KM_SLEEP);
857 	ASSERT(pwp->nphy < SAS2_PHYNUM_MAX);
858 	phyp = pwp->root_phys;
859 	for (i = 0; i < pwp->nphy; i++) {
860 		if (i < pwp->nphy-1) {
861 			phyp->sibling = (phyp + 1);
862 		}
863 		mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
864 		    DDI_INTR_PRI(pwp->intr_pri));
865 		phyp->phynum = i & SAS2_PHYNUM_MASK;
866 		pmcs_phy_name(pwp, phyp, phyp->path, sizeof (phyp->path));
867 		phyp->pwp = pwp;
868 		phyp->device_id = PMCS_INVALID_DEVICE_ID;
869 		phyp->portid = PMCS_PHY_INVALID_PORT_ID;
870 		phyp++;
871 	}
872 
873 	pwp->work = kmem_zalloc(pwp->max_cmd * sizeof (pmcwork_t), KM_SLEEP);
874 	for (i = 0; i < pwp->max_cmd - 1; i++) {
875 		pmcwork_t *pwrk = &pwp->work[i];
876 		mutex_init(&pwrk->lock, NULL, MUTEX_DRIVER,
877 		    DDI_INTR_PRI(pwp->intr_pri));
878 		cv_init(&pwrk->sleep_cv, NULL, CV_DRIVER, NULL);
879 		STAILQ_INSERT_TAIL(&pwp->wf, pwrk, next);
880 
881 	}
882 	pwp->targets = (pmcs_xscsi_t **)
883 	    kmem_zalloc(pwp->max_dev * sizeof (pmcs_xscsi_t *), KM_SLEEP);
884 
885 	pwp->iqpt = (pmcs_iqp_trace_t *)
886 	    kmem_zalloc(sizeof (pmcs_iqp_trace_t), KM_SLEEP);
887 	pwp->iqpt->head = kmem_zalloc(PMCS_IQP_TRACE_BUFFER_SIZE, KM_SLEEP);
888 	pwp->iqpt->curpos = pwp->iqpt->head;
889 	pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
890 
891 	/*
892 	 * Start MPI communication.
893 	 */
894 	if (pmcs_start_mpi(pwp)) {
895 		if (pmcs_soft_reset(pwp, B_FALSE)) {
896 			goto failure;
897 		}
898 		pwp->last_reset_reason = PMCS_LAST_RST_ATTACH;
899 	}
900 
901 	/*
902 	 * Do some initial acceptance tests.
903 	 * This tests interrupts and queues.
904 	 */
905 	if (pmcs_echo_test(pwp)) {
906 		goto failure;
907 	}
908 
909 	/* Read VPD - if it exists */
910 	if (pmcs_get_nvmd(pwp, PMCS_NVMD_VPD, PMCIN_NVMD_VPD, 0, NULL, 0)) {
911 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
912 		    "%s: Unable to read VPD: "
913 		    "attempting to fabricate", __func__);
914 		/*
915 		 * When we release, this must goto failure and the call
916 		 * to pmcs_fabricate_wwid is removed.
917 		 */
918 		/* goto failure; */
919 		if (!pmcs_fabricate_wwid(pwp)) {
920 			goto failure;
921 		}
922 	}
923 
924 	/*
925 	 * We're now officially running
926 	 */
927 	pwp->state = STATE_RUNNING;
928 
929 	/*
930 	 * Check firmware versions and load new firmware
931 	 * if needed and reset.
932 	 */
933 	if (pmcs_firmware_update(pwp)) {
934 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
935 		    "%s: Firmware update failed", __func__);
936 		goto failure;
937 	}
938 
939 	/*
940 	 * Create completion threads.
941 	 */
942 	for (i = 0; i < pwp->cq_info.cq_threads; i++) {
943 		pwp->cq_info.cq_thr_info[i].cq_pwp = pwp;
944 		pwp->cq_info.cq_thr_info[i].cq_thread =
945 		    thread_create(NULL, 0, pmcs_scsa_cq_run,
946 		    &pwp->cq_info.cq_thr_info[i], 0, &p0, TS_RUN, minclsyspri);
947 	}
948 
949 	/*
950 	 * Create one thread to deal with the updating of the interrupt
951 	 * coalescing timer.
952 	 */
953 	pwp->ict_thread = thread_create(NULL, 0, pmcs_check_intr_coal,
954 	    pwp, 0, &p0, TS_RUN, minclsyspri);
955 
956 	/*
957 	 * Kick off the watchdog
958 	 */
959 	pwp->wdhandle = timeout(pmcs_watchdog, pwp,
960 	    drv_usectohz(PMCS_WATCH_INTERVAL));
961 	/*
962 	 * Do the SCSI attachment code (before starting phys)
963 	 */
964 	if (pmcs_scsa_init(pwp, &pmcs_dattr)) {
965 		goto failure;
966 	}
967 	pwp->hba_attached = 1;
968 
969 	/*
970 	 * Initialize the rwlock for the iport elements.
971 	 */
972 	rw_init(&pwp->iports_lock, NULL, RW_DRIVER, NULL);
973 
974 	/* Check all acc & dma handles allocated in attach */
975 	if (pmcs_check_acc_dma_handle(pwp)) {
976 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
977 		goto failure;
978 	}
979 
980 	/*
981 	 * Create the phymap for this HBA instance
982 	 */
983 	if (sas_phymap_create(dip, phymap_usec, PHYMAP_MODE_SIMPLE, NULL,
984 	    pwp, pmcs_phymap_activate, pmcs_phymap_deactivate,
985 	    &pwp->hss_phymap) != DDI_SUCCESS) {
986 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
987 		    "%s: pmcs%d phymap_create failed", __func__, inst);
988 		goto failure;
989 	}
990 	ASSERT(pwp->hss_phymap);
991 
992 	/*
993 	 * Create the iportmap for this HBA instance
994 	 */
995 	if (scsi_hba_iportmap_create(dip, iportmap_usec,
996 	    &pwp->hss_iportmap) != DDI_SUCCESS) {
997 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
998 		    "%s: pmcs%d iportmap_create failed", __func__, inst);
999 		goto failure;
1000 	}
1001 	ASSERT(pwp->hss_iportmap);
1002 
1003 	/*
1004 	 * Start the PHYs.
1005 	 */
1006 	if (pmcs_start_phys(pwp)) {
1007 		goto failure;
1008 	}
1009 
1010 	/*
1011 	 * From this point on, we can't fail.
1012 	 */
1013 	ddi_report_dev(dip);
1014 
1015 	/* SM-HBA */
1016 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SMHBA_SUPPORTED,
1017 	    &sm_hba);
1018 
1019 	/* SM-HBA */
1020 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_DRV_VERSION,
1021 	    pmcs_driver_rev);
1022 
1023 	/* SM-HBA */
1024 	chiprev = 'A' + pwp->chiprev;
1025 	(void) snprintf(hw_rev, 2, "%s", &chiprev);
1026 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_HWARE_VERSION,
1027 	    hw_rev);
1028 
1029 	/* SM-HBA */
1030 	switch (PMCS_FW_TYPE(pwp)) {
1031 	case PMCS_FW_TYPE_RELEASED:
1032 		fwsupport = "Released";
1033 		break;
1034 	case PMCS_FW_TYPE_DEVELOPMENT:
1035 		fwsupport = "Development";
1036 		break;
1037 	case PMCS_FW_TYPE_ALPHA:
1038 		fwsupport = "Alpha";
1039 		break;
1040 	case PMCS_FW_TYPE_BETA:
1041 		fwsupport = "Beta";
1042 		break;
1043 	default:
1044 		fwsupport = "Special";
1045 		break;
1046 	}
1047 	(void) snprintf(fw_rev, sizeof (fw_rev), "%x.%x.%x %s",
1048 	    PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp), PMCS_FW_MICRO(pwp),
1049 	    fwsupport);
1050 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_FWARE_VERSION,
1051 	    fw_rev);
1052 
1053 	/* SM-HBA */
1054 	num_phys = pwp->nphy;
1055 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_NUM_PHYS_HBA,
1056 	    &num_phys);
1057 
1058 	/* SM-HBA */
1059 	protocol = SAS_SSP_SUPPORT | SAS_SATA_SUPPORT | SAS_SMP_SUPPORT;
1060 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SUPPORTED_PROTOCOL,
1061 	    &protocol);
1062 
1063 	return (DDI_SUCCESS);
1064 
1065 failure:
1066 	if (pmcs_unattach(pwp)) {
1067 		pwp->stuck = 1;
1068 	}
1069 	return (DDI_FAILURE);
1070 }
1071 
1072 int
1073 pmcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1074 {
1075 	int inst = ddi_get_instance(dip);
1076 	pmcs_iport_t	*iport = NULL;
1077 	pmcs_hw_t	*pwp = NULL;
1078 	scsi_hba_tran_t	*tran;
1079 
1080 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1081 		/* iport node */
1082 		iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
1083 		ASSERT(iport);
1084 		if (iport == NULL) {
1085 			return (DDI_FAILURE);
1086 		}
1087 		pwp = iport->pwp;
1088 	} else {
1089 		/* hba node */
1090 		pwp = (pmcs_hw_t *)ddi_get_soft_state(pmcs_softc_state, inst);
1091 		ASSERT(pwp);
1092 		if (pwp == NULL) {
1093 			return (DDI_FAILURE);
1094 		}
1095 	}
1096 
1097 	switch (cmd) {
1098 	case DDI_DETACH:
1099 		if (iport) {
1100 			/* iport detach */
1101 			if (pmcs_iport_unattach(iport)) {
1102 				return (DDI_FAILURE);
1103 			}
1104 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1105 			    "iport%d detached", inst);
1106 			return (DDI_SUCCESS);
1107 		} else {
1108 			/* HBA detach */
1109 			if (pmcs_unattach(pwp)) {
1110 				return (DDI_FAILURE);
1111 			}
1112 			return (DDI_SUCCESS);
1113 		}
1114 
1115 	case DDI_SUSPEND:
1116 	case DDI_PM_SUSPEND:
1117 		/* No DDI_SUSPEND on iport nodes */
1118 		if (iport) {
1119 			return (DDI_SUCCESS);
1120 		}
1121 
1122 		if (pwp->stuck) {
1123 			return (DDI_FAILURE);
1124 		}
1125 		tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
1126 		if (!tran) {
1127 			return (DDI_FAILURE);
1128 		}
1129 
1130 		pwp = TRAN2PMC(tran);
1131 		if (pwp == NULL) {
1132 			return (DDI_FAILURE);
1133 		}
1134 		mutex_enter(&pwp->lock);
1135 		if (pwp->tq) {
1136 			ddi_taskq_suspend(pwp->tq);
1137 		}
1138 		pwp->suspended = 1;
1139 		mutex_exit(&pwp->lock);
1140 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "PMC8X6G suspending");
1141 		return (DDI_SUCCESS);
1142 
1143 	default:
1144 		return (DDI_FAILURE);
1145 	}
1146 }
1147 
1148 static int
1149 pmcs_iport_unattach(pmcs_iport_t *iport)
1150 {
1151 	pmcs_hw_t	*pwp = iport->pwp;
1152 
1153 	/*
1154 	 * First, check if there are still any configured targets on this
1155 	 * iport.  If so, we fail detach.
1156 	 */
1157 	if (pmcs_iport_has_targets(pwp, iport)) {
1158 		pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
1159 		    "iport%d detach failure: iport has targets (luns)",
1160 		    ddi_get_instance(iport->dip));
1161 		return (DDI_FAILURE);
1162 	}
1163 
1164 	/*
1165 	 * Remove this iport from our list if it is inactive in the phymap.
1166 	 */
1167 	rw_enter(&pwp->iports_lock, RW_WRITER);
1168 	mutex_enter(&iport->lock);
1169 
1170 	if (iport->ua_state == UA_ACTIVE) {
1171 		mutex_exit(&iport->lock);
1172 		rw_exit(&pwp->iports_lock);
1173 		pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
1174 		    "iport%d detach failure: "
1175 		    "iport unit address active in phymap",
1176 		    ddi_get_instance(iport->dip));
1177 		return (DDI_FAILURE);
1178 	}
1179 
1180 	/* If it's our only iport, clear iports_attached */
1181 	ASSERT(pwp->num_iports >= 1);
1182 	if (--pwp->num_iports == 0) {
1183 		pwp->iports_attached = 0;
1184 	}
1185 
1186 	ASSERT(list_link_active(&iport->list_node));
1187 	list_remove(&pwp->iports, iport);
1188 	rw_exit(&pwp->iports_lock);
1189 
1190 	/*
1191 	 * We have removed the iport handle from the HBA's iports list,
1192 	 * there will be no new references to it. Two things must be
1193 	 * guarded against here.  First, we could have PHY up events,
1194 	 * adding themselves to the iport->phys list and grabbing ref's
1195 	 * on our iport handle.  Second, we could have existing references
1196 	 * to this iport handle from a point in time prior to the list
1197 	 * removal above.
1198 	 *
1199 	 * So first, destroy the phys list. Remove any phys that have snuck
1200 	 * in after the phymap deactivate, dropping the refcnt accordingly.
1201 	 * If these PHYs are still up if and when the phymap reactivates
1202 	 * (i.e. when this iport reattaches), we'll populate the list with
1203 	 * them and bump the refcnt back up.
1204 	 */
1205 	pmcs_remove_phy_from_iport(iport, NULL);
1206 	ASSERT(list_is_empty(&iport->phys));
1207 	list_destroy(&iport->phys);
1208 	mutex_exit(&iport->lock);
1209 
1210 	/*
1211 	 * Second, wait for any other references to this iport to be
1212 	 * dropped, then continue teardown.
1213 	 */
1214 	mutex_enter(&iport->refcnt_lock);
1215 	while (iport->refcnt != 0) {
1216 		cv_wait(&iport->refcnt_cv, &iport->refcnt_lock);
1217 	}
1218 	mutex_exit(&iport->refcnt_lock);
1219 
1220 	/* Delete kstats */
1221 	pmcs_destroy_phy_stats(iport);
1222 
1223 	/* Destroy the iport target map */
1224 	if (pmcs_iport_tgtmap_destroy(iport) == B_FALSE) {
1225 		return (DDI_FAILURE);
1226 	}
1227 
1228 	/* Free the tgt soft state */
1229 	if (iport->tgt_sstate != NULL) {
1230 		ddi_soft_state_bystr_fini(&iport->tgt_sstate);
1231 	}
1232 
1233 	/* Free our unit address string */
1234 	strfree(iport->ua);
1235 
1236 	/* Finish teardown and free the softstate */
1237 	mutex_destroy(&iport->refcnt_lock);
1238 	mutex_destroy(&iport->smp_lock);
1239 	ASSERT(iport->refcnt == 0);
1240 	cv_destroy(&iport->refcnt_cv);
1241 	cv_destroy(&iport->smp_cv);
1242 	mutex_destroy(&iport->lock);
1243 	ddi_soft_state_free(pmcs_iport_softstate, ddi_get_instance(iport->dip));
1244 
1245 	return (DDI_SUCCESS);
1246 }
1247 
1248 static int
1249 pmcs_unattach(pmcs_hw_t *pwp)
1250 {
1251 	int i;
1252 	enum pwpstate curstate;
1253 	pmcs_cq_thr_info_t *cqti;
1254 
1255 	/*
1256 	 * Tear down the interrupt infrastructure.
1257 	 */
1258 	if (pmcs_teardown_intr(pwp)) {
1259 		pwp->stuck = 1;
1260 	}
1261 	pwp->intr_cnt = 0;
1262 
1263 	/*
1264 	 * Grab a lock, if initted, to set state.
1265 	 */
1266 	if (pwp->locks_initted) {
1267 		mutex_enter(&pwp->lock);
1268 		if (pwp->state != STATE_DEAD) {
1269 			pwp->state = STATE_UNPROBING;
1270 		}
1271 		curstate = pwp->state;
1272 		mutex_exit(&pwp->lock);
1273 
1274 		/*
1275 		 * Stop the I/O completion threads.
1276 		 */
1277 		mutex_enter(&pwp->cq_lock);
1278 		pwp->cq_info.cq_stop = B_TRUE;
1279 		for (i = 0; i < pwp->cq_info.cq_threads; i++) {
1280 			if (pwp->cq_info.cq_thr_info[i].cq_thread) {
1281 				cqti = &pwp->cq_info.cq_thr_info[i];
1282 				mutex_enter(&cqti->cq_thr_lock);
1283 				cv_signal(&cqti->cq_cv);
1284 				mutex_exit(&cqti->cq_thr_lock);
1285 				mutex_exit(&pwp->cq_lock);
1286 				thread_join(cqti->cq_thread->t_did);
1287 				mutex_enter(&pwp->cq_lock);
1288 			}
1289 		}
1290 		mutex_exit(&pwp->cq_lock);
1291 
1292 		/*
1293 		 * Stop the interrupt coalescing timer thread
1294 		 */
1295 		if (pwp->ict_thread) {
1296 			mutex_enter(&pwp->ict_lock);
1297 			pwp->io_intr_coal.stop_thread = B_TRUE;
1298 			cv_signal(&pwp->ict_cv);
1299 			mutex_exit(&pwp->ict_lock);
1300 			thread_join(pwp->ict_thread->t_did);
1301 		}
1302 	} else {
1303 		if (pwp->state != STATE_DEAD) {
1304 			pwp->state = STATE_UNPROBING;
1305 		}
1306 		curstate = pwp->state;
1307 	}
1308 
1309 	if (&pwp->iports != NULL) {
1310 		/* Destroy the iports lock */
1311 		rw_destroy(&pwp->iports_lock);
1312 		/* Destroy the iports list */
1313 		ASSERT(list_is_empty(&pwp->iports));
1314 		list_destroy(&pwp->iports);
1315 	}
1316 
1317 	if (pwp->hss_iportmap != NULL) {
1318 		/* Destroy the iportmap */
1319 		scsi_hba_iportmap_destroy(pwp->hss_iportmap);
1320 	}
1321 
1322 	if (pwp->hss_phymap != NULL) {
1323 		/* Destroy the phymap */
1324 		sas_phymap_destroy(pwp->hss_phymap);
1325 	}
1326 
1327 	/*
1328 	 * Make sure that any pending watchdog won't
1329 	 * be called from this point on out.
1330 	 */
1331 	(void) untimeout(pwp->wdhandle);
1332 	/*
1333 	 * After the above action, the watchdog
1334 	 * timer that starts up the worker task
1335 	 * may trigger but will exit immediately
1336 	 * on triggering.
1337 	 *
1338 	 * Now that this is done, we can destroy
1339 	 * the task queue, which will wait if we're
1340 	 * running something on it.
1341 	 */
1342 	if (pwp->tq) {
1343 		ddi_taskq_destroy(pwp->tq);
1344 		pwp->tq = NULL;
1345 	}
1346 
1347 	pmcs_fm_fini(pwp);
1348 
1349 	if (pwp->hba_attached) {
1350 		(void) scsi_hba_detach(pwp->dip);
1351 		pwp->hba_attached = 0;
1352 	}
1353 
1354 	/*
1355 	 * If the chip hasn't been marked dead, shut it down now
1356 	 * to bring it back to a known state without attempting
1357 	 * a soft reset.
1358 	 */
1359 	if (curstate != STATE_DEAD && pwp->locks_initted) {
1360 		/*
1361 		 * De-register all registered devices
1362 		 */
1363 		pmcs_deregister_devices(pwp, pwp->root_phys);
1364 
1365 		/*
1366 		 * Stop all the phys.
1367 		 */
1368 		pmcs_stop_phys(pwp);
1369 
1370 		/*
1371 		 * Shut Down Message Passing
1372 		 */
1373 		(void) pmcs_stop_mpi(pwp);
1374 
1375 		/*
1376 		 * Reset chip
1377 		 */
1378 		(void) pmcs_soft_reset(pwp, B_FALSE);
1379 		pwp->last_reset_reason = PMCS_LAST_RST_DETACH;
1380 	}
1381 
1382 	/*
1383 	 * Turn off interrupts on the chip
1384 	 */
1385 	if (pwp->mpi_acc_handle) {
1386 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1387 	}
1388 
1389 	/* Destroy pwp's lock */
1390 	if (pwp->locks_initted) {
1391 		mutex_destroy(&pwp->lock);
1392 		mutex_destroy(&pwp->dma_lock);
1393 		mutex_destroy(&pwp->axil_lock);
1394 		mutex_destroy(&pwp->cq_lock);
1395 		mutex_destroy(&pwp->config_lock);
1396 		mutex_destroy(&pwp->ict_lock);
1397 		mutex_destroy(&pwp->wfree_lock);
1398 		mutex_destroy(&pwp->pfree_lock);
1399 		mutex_destroy(&pwp->dead_phylist_lock);
1400 #ifdef	DEBUG
1401 		mutex_destroy(&pwp->dbglock);
1402 #endif
1403 		cv_destroy(&pwp->ict_cv);
1404 		cv_destroy(&pwp->drain_cv);
1405 		pwp->locks_initted = 0;
1406 	}
1407 
1408 	/*
1409 	 * Free DMA handles and associated consistent memory
1410 	 */
1411 	if (pwp->regdump_hndl) {
1412 		if (ddi_dma_unbind_handle(pwp->regdump_hndl) != DDI_SUCCESS) {
1413 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1414 			    "Condition check failed "
1415 			    "at %s():%d", __func__, __LINE__);
1416 		}
1417 		ddi_dma_free_handle(&pwp->regdump_hndl);
1418 		ddi_dma_mem_free(&pwp->regdump_acchdl);
1419 		pwp->regdump_hndl = 0;
1420 	}
1421 	if (pwp->fwlog_hndl) {
1422 		if (ddi_dma_unbind_handle(pwp->fwlog_hndl) != DDI_SUCCESS) {
1423 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1424 			    "Condition check failed "
1425 			    "at %s():%d", __func__, __LINE__);
1426 		}
1427 		ddi_dma_free_handle(&pwp->fwlog_hndl);
1428 		ddi_dma_mem_free(&pwp->fwlog_acchdl);
1429 		pwp->fwlog_hndl = 0;
1430 	}
1431 	if (pwp->cip_handles) {
1432 		if (ddi_dma_unbind_handle(pwp->cip_handles) != DDI_SUCCESS) {
1433 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1434 			    "Condition check failed "
1435 			    "at %s():%d", __func__, __LINE__);
1436 		}
1437 		ddi_dma_free_handle(&pwp->cip_handles);
1438 		ddi_dma_mem_free(&pwp->cip_acchdls);
1439 		pwp->cip_handles = 0;
1440 	}
1441 	for (i = 0; i < PMCS_NOQ; i++) {
1442 		if (pwp->oqp_handles[i]) {
1443 			if (ddi_dma_unbind_handle(pwp->oqp_handles[i]) !=
1444 			    DDI_SUCCESS) {
1445 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1446 				    "Condition check failed at %s():%d",
1447 				    __func__, __LINE__);
1448 			}
1449 			ddi_dma_free_handle(&pwp->oqp_handles[i]);
1450 			ddi_dma_mem_free(&pwp->oqp_acchdls[i]);
1451 			pwp->oqp_handles[i] = 0;
1452 		}
1453 	}
1454 	for (i = 0; i < PMCS_NIQ; i++) {
1455 		if (pwp->iqp_handles[i]) {
1456 			if (ddi_dma_unbind_handle(pwp->iqp_handles[i]) !=
1457 			    DDI_SUCCESS) {
1458 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1459 				    "Condition check failed at %s():%d",
1460 				    __func__, __LINE__);
1461 			}
1462 			ddi_dma_free_handle(&pwp->iqp_handles[i]);
1463 			ddi_dma_mem_free(&pwp->iqp_acchdls[i]);
1464 			pwp->iqp_handles[i] = 0;
1465 		}
1466 	}
1467 
1468 	pmcs_free_dma_chunklist(pwp);
1469 
1470 	/*
1471 	 * Unmap registers and destroy access handles
1472 	 */
1473 	if (pwp->mpi_acc_handle) {
1474 		ddi_regs_map_free(&pwp->mpi_acc_handle);
1475 		pwp->mpi_acc_handle = 0;
1476 	}
1477 	if (pwp->top_acc_handle) {
1478 		ddi_regs_map_free(&pwp->top_acc_handle);
1479 		pwp->top_acc_handle = 0;
1480 	}
1481 	if (pwp->gsm_acc_handle) {
1482 		ddi_regs_map_free(&pwp->gsm_acc_handle);
1483 		pwp->gsm_acc_handle = 0;
1484 	}
1485 	if (pwp->msg_acc_handle) {
1486 		ddi_regs_map_free(&pwp->msg_acc_handle);
1487 		pwp->msg_acc_handle = 0;
1488 	}
1489 	if (pwp->pci_acc_handle) {
1490 		pci_config_teardown(&pwp->pci_acc_handle);
1491 		pwp->pci_acc_handle = 0;
1492 	}
1493 
1494 	/*
1495 	 * Do memory allocation cleanup.
1496 	 */
1497 	while (pwp->dma_freelist) {
1498 		pmcs_dmachunk_t *this = pwp->dma_freelist;
1499 		pwp->dma_freelist = this->nxt;
1500 		kmem_free(this, sizeof (pmcs_dmachunk_t));
1501 	}
1502 
1503 	/*
1504 	 * Free pools
1505 	 */
1506 	if (pwp->iocomp_cb_cache) {
1507 		kmem_cache_destroy(pwp->iocomp_cb_cache);
1508 	}
1509 
1510 	/*
1511 	 * Free all PHYs (at level > 0), then free the cache
1512 	 */
1513 	pmcs_free_all_phys(pwp, pwp->root_phys);
1514 	if (pwp->phy_cache) {
1515 		kmem_cache_destroy(pwp->phy_cache);
1516 	}
1517 
1518 	/*
1519 	 * Free root PHYs
1520 	 */
1521 	if (pwp->root_phys) {
1522 		pmcs_phy_t *phyp = pwp->root_phys;
1523 		for (i = 0; i < pwp->nphy; i++) {
1524 			mutex_destroy(&phyp->phy_lock);
1525 			phyp = phyp->sibling;
1526 		}
1527 		kmem_free(pwp->root_phys, pwp->nphy * sizeof (pmcs_phy_t));
1528 		pwp->root_phys = NULL;
1529 		pwp->nphy = 0;
1530 	}
1531 
1532 	/* Free the targets list */
1533 	if (pwp->targets) {
1534 		kmem_free(pwp->targets,
1535 		    sizeof (pmcs_xscsi_t *) * pwp->max_dev);
1536 	}
1537 
1538 	/*
1539 	 * Free work structures
1540 	 */
1541 
1542 	if (pwp->work && pwp->max_cmd) {
1543 		for (i = 0; i < pwp->max_cmd - 1; i++) {
1544 			pmcwork_t *pwrk = &pwp->work[i];
1545 			mutex_destroy(&pwrk->lock);
1546 			cv_destroy(&pwrk->sleep_cv);
1547 		}
1548 		kmem_free(pwp->work, sizeof (pmcwork_t) * pwp->max_cmd);
1549 		pwp->work = NULL;
1550 		pwp->max_cmd = 0;
1551 	}
1552 
1553 	/*
1554 	 * Do last property and SCSA cleanup
1555 	 */
1556 	if (pwp->tran) {
1557 		scsi_hba_tran_free(pwp->tran);
1558 		pwp->tran = NULL;
1559 	}
1560 	if (pwp->reset_notify_listf) {
1561 		scsi_hba_reset_notify_tear_down(pwp->reset_notify_listf);
1562 		pwp->reset_notify_listf = NULL;
1563 	}
1564 	ddi_prop_remove_all(pwp->dip);
1565 	if (pwp->stuck) {
1566 		return (-1);
1567 	}
1568 
1569 	/* Free register dump area if allocated */
1570 	if (pwp->regdumpp) {
1571 		kmem_free(pwp->regdumpp, PMCS_REG_DUMP_SIZE);
1572 		pwp->regdumpp = NULL;
1573 	}
1574 	if (pwp->iqpt && pwp->iqpt->head) {
1575 		kmem_free(pwp->iqpt->head, PMCS_IQP_TRACE_BUFFER_SIZE);
1576 		pwp->iqpt->head = pwp->iqpt->curpos = NULL;
1577 	}
1578 	if (pwp->iqpt) {
1579 		kmem_free(pwp->iqpt, sizeof (pmcs_iqp_trace_t));
1580 		pwp->iqpt = NULL;
1581 	}
1582 
1583 	ddi_soft_state_free(pmcs_softc_state, ddi_get_instance(pwp->dip));
1584 	return (0);
1585 }
1586 
1587 /*
1588  * quiesce (9E) entry point
1589  *
1590  * This function is called when the system is single-threaded at high PIL
1591  * with preemption disabled. Therefore, the function must not block/wait/sleep.
1592  *
1593  * Returns DDI_SUCCESS or DDI_FAILURE.
1594  *
1595  */
1596 static int
1597 pmcs_quiesce(dev_info_t *dip)
1598 {
1599 	pmcs_hw_t	*pwp;
1600 	scsi_hba_tran_t	*tran;
1601 
1602 	if ((tran = ddi_get_driver_private(dip)) == NULL)
1603 		return (DDI_SUCCESS);
1604 
1605 	/* No quiesce necessary on a per-iport basis */
1606 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1607 		return (DDI_SUCCESS);
1608 	}
1609 
1610 	if ((pwp = TRAN2PMC(tran)) == NULL)
1611 		return (DDI_SUCCESS);
1612 
1613 	/* Stop MPI & Reset chip (no need to re-initialize) */
1614 	(void) pmcs_stop_mpi(pwp);
1615 	(void) pmcs_soft_reset(pwp, B_TRUE);
1616 	pwp->last_reset_reason = PMCS_LAST_RST_QUIESCE;
1617 
1618 	return (DDI_SUCCESS);
1619 }
1620 
1621 /*
1622  * Called with xp->statlock and PHY lock and scratch acquired.
1623  */
1624 static int
1625 pmcs_add_sata_device(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
1626 {
1627 	ata_identify_t *ati;
1628 	int result, i;
1629 	pmcs_phy_t *pptr;
1630 	uint16_t *a;
1631 	union {
1632 		uint8_t nsa[8];
1633 		uint16_t nsb[4];
1634 	} u;
1635 
1636 	/*
1637 	 * Safe defaults - use only if this target is brand new (i.e. doesn't
1638 	 * already have these settings configured)
1639 	 */
1640 	if (xp->capacity == 0) {
1641 		xp->capacity = (uint64_t)-1;
1642 		xp->ca = 1;
1643 		xp->qdepth = 1;
1644 		xp->pio = 1;
1645 	}
1646 
1647 	pptr = xp->phy;
1648 
1649 	/*
1650 	 * We only try and issue an IDENTIFY for first level
1651 	 * (direct attached) devices. We don't try and
1652 	 * set other quirks here (this will happen later,
1653 	 * if the device is fully configured)
1654 	 */
1655 	if (pptr->level) {
1656 		return (0);
1657 	}
1658 
1659 	mutex_exit(&xp->statlock);
1660 	result = pmcs_sata_identify(pwp, pptr);
1661 	mutex_enter(&xp->statlock);
1662 
1663 	if (result) {
1664 		return (result);
1665 	}
1666 	ati = pwp->scratch;
1667 	a = &ati->word108;
1668 	for (i = 0; i < 4; i++) {
1669 		u.nsb[i] = ddi_swap16(*a++);
1670 	}
1671 
1672 	/*
1673 	 * Check the returned data for being a valid (NAA=5) WWN.
1674 	 * If so, use that and override the SAS address we were
1675 	 * given at Link Up time.
1676 	 */
1677 	if ((u.nsa[0] >> 4) == 5) {
1678 		(void) memcpy(pptr->sas_address, u.nsa, 8);
1679 	}
1680 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
1681 	    "%s: %s has SAS ADDRESS " SAS_ADDR_FMT,
1682 	    __func__, pptr->path, SAS_ADDR_PRT(pptr->sas_address));
1683 	return (0);
1684 }
1685 
1686 /*
1687  * Called with PHY lock and target statlock held and scratch acquired
1688  */
1689 static boolean_t
1690 pmcs_add_new_device(pmcs_hw_t *pwp, pmcs_xscsi_t *target)
1691 {
1692 	ASSERT(target != NULL);
1693 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, target, "%s: target = 0x%p",
1694 	    __func__, (void *) target);
1695 
1696 	switch (target->phy->dtype) {
1697 	case SATA:
1698 		if (pmcs_add_sata_device(pwp, target) != 0) {
1699 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, target->phy,
1700 			    target, "%s: add_sata_device failed for tgt 0x%p",
1701 			    __func__, (void *) target);
1702 			return (B_FALSE);
1703 		}
1704 		break;
1705 	case SAS:
1706 		target->qdepth = maxqdepth;
1707 		break;
1708 	case EXPANDER:
1709 		target->qdepth = 1;
1710 		break;
1711 	}
1712 
1713 	target->new = 0;
1714 	target->assigned = 1;
1715 	target->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
1716 	target->dtype = target->phy->dtype;
1717 
1718 	/*
1719 	 * Set the PHY's config stop time to 0.  This is one of the final
1720 	 * stops along the config path, so we're indicating that we
1721 	 * successfully configured the PHY.
1722 	 */
1723 	target->phy->config_stop = 0;
1724 
1725 	return (B_TRUE);
1726 }
1727 
1728 void
1729 pmcs_worker(void *arg)
1730 {
1731 	pmcs_hw_t *pwp = arg;
1732 	ulong_t work_flags;
1733 
1734 	DTRACE_PROBE2(pmcs__worker, ulong_t, pwp->work_flags, boolean_t,
1735 	    pwp->config_changed);
1736 
1737 	if (pwp->state != STATE_RUNNING) {
1738 		return;
1739 	}
1740 
1741 	work_flags = atomic_swap_ulong(&pwp->work_flags, 0);
1742 
1743 	if (work_flags & PMCS_WORK_FLAG_SAS_HW_ACK) {
1744 		pmcs_ack_events(pwp);
1745 	}
1746 
1747 	if (work_flags & PMCS_WORK_FLAG_SPINUP_RELEASE) {
1748 		mutex_enter(&pwp->lock);
1749 		pmcs_spinup_release(pwp, NULL);
1750 		mutex_exit(&pwp->lock);
1751 	}
1752 
1753 	if (work_flags & PMCS_WORK_FLAG_SSP_EVT_RECOVERY) {
1754 		pmcs_ssp_event_recovery(pwp);
1755 	}
1756 
1757 	if (work_flags & PMCS_WORK_FLAG_DS_ERR_RECOVERY) {
1758 		pmcs_dev_state_recovery(pwp, NULL);
1759 	}
1760 
1761 	if (work_flags & PMCS_WORK_FLAG_DEREGISTER_DEV) {
1762 		pmcs_deregister_device_work(pwp, NULL);
1763 	}
1764 
1765 	if (work_flags & PMCS_WORK_FLAG_DISCOVER) {
1766 		pmcs_discover(pwp);
1767 	}
1768 
1769 	if (work_flags & PMCS_WORK_FLAG_ABORT_HANDLE) {
1770 		if (pmcs_abort_handler(pwp)) {
1771 			SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
1772 		}
1773 	}
1774 
1775 	if (work_flags & PMCS_WORK_FLAG_SATA_RUN) {
1776 		pmcs_sata_work(pwp);
1777 	}
1778 
1779 	if (work_flags & PMCS_WORK_FLAG_RUN_QUEUES) {
1780 		pmcs_scsa_wq_run(pwp);
1781 		mutex_enter(&pwp->lock);
1782 		PMCS_CQ_RUN(pwp);
1783 		mutex_exit(&pwp->lock);
1784 	}
1785 
1786 	if (work_flags & PMCS_WORK_FLAG_ADD_DMA_CHUNKS) {
1787 		if (pmcs_add_more_chunks(pwp,
1788 		    ptob(1) * PMCS_ADDTL_CHUNK_PAGES)) {
1789 			SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
1790 		} else {
1791 			SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
1792 		}
1793 	}
1794 }
1795 
1796 static int
1797 pmcs_add_more_chunks(pmcs_hw_t *pwp, unsigned long nsize)
1798 {
1799 	pmcs_dmachunk_t *dc;
1800 	unsigned long dl;
1801 	pmcs_chunk_t	*pchunk = NULL;
1802 
1803 	pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
1804 
1805 	pchunk = kmem_zalloc(sizeof (pmcs_chunk_t), KM_SLEEP);
1806 	if (pchunk == NULL) {
1807 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1808 		    "Not enough memory for DMA chunks");
1809 		return (-1);
1810 	}
1811 
1812 	if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pchunk->acc_handle,
1813 	    &pchunk->dma_handle, nsize, (caddr_t *)&pchunk->addrp,
1814 	    &pchunk->dma_addr) == B_FALSE) {
1815 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1816 		    "Failed to setup DMA for chunks");
1817 		kmem_free(pchunk, sizeof (pmcs_chunk_t));
1818 		return (-1);
1819 	}
1820 
1821 	if ((pmcs_check_acc_handle(pchunk->acc_handle) != DDI_SUCCESS) ||
1822 	    (pmcs_check_dma_handle(pchunk->dma_handle) != DDI_SUCCESS)) {
1823 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_UNAFFECTED);
1824 		return (-1);
1825 	}
1826 
1827 	bzero(pchunk->addrp, nsize);
1828 	dc = NULL;
1829 	for (dl = 0; dl < (nsize / PMCS_SGL_CHUNKSZ); dl++) {
1830 		pmcs_dmachunk_t *tmp;
1831 		tmp = kmem_alloc(sizeof (pmcs_dmachunk_t), KM_SLEEP);
1832 		tmp->nxt = dc;
1833 		dc = tmp;
1834 	}
1835 	mutex_enter(&pwp->dma_lock);
1836 	pmcs_idma_chunks(pwp, dc, pchunk, nsize);
1837 	pwp->nchunks++;
1838 	mutex_exit(&pwp->dma_lock);
1839 	return (0);
1840 }
1841 
1842 static void
1843 pmcs_check_forward_progress(pmcs_hw_t *pwp)
1844 {
1845 	uint32_t	cur_iqci;
1846 	uint32_t	cur_msgu_tick;
1847 	uint32_t	cur_iop_tick;
1848 	int 		i;
1849 
1850 	mutex_enter(&pwp->lock);
1851 
1852 	if (pwp->state == STATE_IN_RESET) {
1853 		mutex_exit(&pwp->lock);
1854 		return;
1855 	}
1856 
1857 	/* Ensure that inbound work is getting picked up */
1858 	for (i = 0; i < PMCS_NIQ; i++) {
1859 		cur_iqci = pmcs_rd_iqci(pwp, i);
1860 		if (cur_iqci == pwp->shadow_iqpi[i]) {
1861 			pwp->last_iqci[i] = cur_iqci;
1862 			continue;
1863 		}
1864 		if (cur_iqci == pwp->last_iqci[i]) {
1865 			pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1866 			    "Inbound Queue stall detected, issuing reset");
1867 			goto hot_reset;
1868 		}
1869 		pwp->last_iqci[i] = cur_iqci;
1870 	}
1871 
1872 	/* Check heartbeat on both the MSGU and IOP */
1873 	cur_msgu_tick = pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK);
1874 	if (cur_msgu_tick == pwp->last_msgu_tick) {
1875 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1876 		    "Stall detected on MSGU, issuing reset");
1877 		goto hot_reset;
1878 	}
1879 	pwp->last_msgu_tick = cur_msgu_tick;
1880 
1881 	cur_iop_tick  = pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK);
1882 	if (cur_iop_tick == pwp->last_iop_tick) {
1883 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1884 		    "Stall detected on IOP, issuing reset");
1885 		goto hot_reset;
1886 	}
1887 	pwp->last_iop_tick = cur_iop_tick;
1888 
1889 	mutex_exit(&pwp->lock);
1890 	return;
1891 
1892 hot_reset:
1893 	pwp->state = STATE_DEAD;
1894 	/*
1895 	 * We've detected a stall. Attempt to recover service via hot
1896 	 * reset. In case of failure, pmcs_hot_reset() will handle the
1897 	 * failure and issue any required FM notifications.
1898 	 * See pmcs_subr.c for more details.
1899 	 */
1900 	if (pmcs_hot_reset(pwp)) {
1901 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1902 		    "%s: hot reset failure", __func__);
1903 	} else {
1904 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1905 		    "%s: hot reset complete", __func__);
1906 		pwp->last_reset_reason = PMCS_LAST_RST_STALL;
1907 	}
1908 	mutex_exit(&pwp->lock);
1909 }
1910 
1911 static void
1912 pmcs_check_commands(pmcs_hw_t *pwp)
1913 {
1914 	pmcs_cmd_t *sp;
1915 	size_t amt;
1916 	char path[32];
1917 	pmcwork_t *pwrk;
1918 	pmcs_xscsi_t *target;
1919 	pmcs_phy_t *phyp;
1920 	int rval;
1921 
1922 	for (pwrk = pwp->work; pwrk < &pwp->work[pwp->max_cmd]; pwrk++) {
1923 		mutex_enter(&pwrk->lock);
1924 
1925 		/*
1926 		 * If the command isn't active, we can't be timing it still.
1927 		 * Active means the tag is not free and the state is "on chip".
1928 		 */
1929 		if (!PMCS_COMMAND_ACTIVE(pwrk)) {
1930 			mutex_exit(&pwrk->lock);
1931 			continue;
1932 		}
1933 
1934 		/*
1935 		 * No timer active for this command.
1936 		 */
1937 		if (pwrk->timer == 0) {
1938 			mutex_exit(&pwrk->lock);
1939 			continue;
1940 		}
1941 
1942 		/*
1943 		 * Knock off bits for the time interval.
1944 		 */
1945 		if (pwrk->timer >= US2WT(PMCS_WATCH_INTERVAL)) {
1946 			pwrk->timer -= US2WT(PMCS_WATCH_INTERVAL);
1947 		} else {
1948 			pwrk->timer = 0;
1949 		}
1950 		if (pwrk->timer > 0) {
1951 			mutex_exit(&pwrk->lock);
1952 			continue;
1953 		}
1954 
1955 		/*
1956 		 * The command has now officially timed out.
1957 		 * Get the path for it. If it doesn't have
1958 		 * a phy pointer any more, it's really dead
1959 		 * and can just be put back on the free list.
1960 		 * There should *not* be any commands associated
1961 		 * with it any more.
1962 		 */
1963 		if (pwrk->phy == NULL) {
1964 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1965 			    "dead command with gone phy being recycled");
1966 			ASSERT(pwrk->xp == NULL);
1967 			pmcs_pwork(pwp, pwrk);
1968 			continue;
1969 		}
1970 		amt = sizeof (path);
1971 		amt = min(sizeof (pwrk->phy->path), amt);
1972 		(void) memcpy(path, pwrk->phy->path, amt);
1973 
1974 		/*
1975 		 * If this is a non-SCSA command, stop here. Eventually
1976 		 * we might do something with non-SCSA commands here-
1977 		 * but so far their timeout mechanisms are handled in
1978 		 * the WAIT_FOR macro.
1979 		 */
1980 		if (pwrk->xp == NULL) {
1981 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1982 			    "%s: non-SCSA cmd tag 0x%x timed out",
1983 			    path, pwrk->htag);
1984 			mutex_exit(&pwrk->lock);
1985 			continue;
1986 		}
1987 
1988 		sp = pwrk->arg;
1989 		ASSERT(sp != NULL);
1990 
1991 		/*
1992 		 * Mark it as timed out.
1993 		 */
1994 		CMD2PKT(sp)->pkt_reason = CMD_TIMEOUT;
1995 		CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
1996 #ifdef	DEBUG
1997 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
1998 		    "%s: SCSA cmd tag 0x%x timed out (state %x) onwire=%d",
1999 		    path, pwrk->htag, pwrk->state, pwrk->onwire);
2000 #else
2001 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
2002 		    "%s: SCSA cmd tag 0x%x timed out (state %x)",
2003 		    path, pwrk->htag, pwrk->state);
2004 #endif
2005 		/*
2006 		 * Mark the work structure as timed out.
2007 		 */
2008 		pwrk->state = PMCS_WORK_STATE_TIMED_OUT;
2009 		phyp = pwrk->phy;
2010 		target = pwrk->xp;
2011 		mutex_exit(&pwrk->lock);
2012 
2013 		pmcs_lock_phy(phyp);
2014 		mutex_enter(&target->statlock);
2015 
2016 		/*
2017 		 * No point attempting recovery if the device is gone
2018 		 */
2019 		if (target->dev_gone) {
2020 			mutex_exit(&target->statlock);
2021 			pmcs_unlock_phy(phyp);
2022 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2023 			    "%s: tgt(0x%p) is gone. Returning CMD_DEV_GONE "
2024 			    "for htag 0x%08x", __func__,
2025 			    (void *)target, pwrk->htag);
2026 			mutex_enter(&pwrk->lock);
2027 			if (!PMCS_COMMAND_DONE(pwrk)) {
2028 				/* Complete this command here */
2029 				pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2030 				    "%s: Completing cmd (htag 0x%08x) "
2031 				    "anyway", __func__, pwrk->htag);
2032 				pwrk->dead = 1;
2033 				CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
2034 				CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
2035 				pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
2036 			} else {
2037 				mutex_exit(&pwrk->lock);
2038 			}
2039 			continue;
2040 		}
2041 
2042 		mutex_exit(&target->statlock);
2043 		rval = pmcs_abort(pwp, phyp, pwrk->htag, 0, 1);
2044 		if (rval) {
2045 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2046 			    "%s: Bad status (%d) on abort of HTAG 0x%08x",
2047 			    __func__, rval, pwrk->htag);
2048 			pmcs_unlock_phy(phyp);
2049 			mutex_enter(&pwrk->lock);
2050 			if (!PMCS_COMMAND_DONE(pwrk)) {
2051 				/* Complete this command here */
2052 				pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2053 				    "%s: Completing cmd (htag 0x%08x) "
2054 				    "anyway", __func__, pwrk->htag);
2055 				if (target->dev_gone) {
2056 					pwrk->dead = 1;
2057 					CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
2058 					CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
2059 				}
2060 				pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
2061 			} else {
2062 				mutex_exit(&pwrk->lock);
2063 			}
2064 			pmcs_lock_phy(phyp);
2065 			/*
2066 			 * No need to reschedule ABORT if we get any other
2067 			 * status
2068 			 */
2069 			if (rval == ENOMEM) {
2070 				phyp->abort_sent = 0;
2071 				phyp->abort_pending = 1;
2072 				SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
2073 			}
2074 		}
2075 		pmcs_unlock_phy(phyp);
2076 	}
2077 	/*
2078 	 * Run any completions that may have been queued up.
2079 	 */
2080 	PMCS_CQ_RUN(pwp);
2081 }
2082 
2083 static void
2084 pmcs_watchdog(void *arg)
2085 {
2086 	pmcs_hw_t *pwp = arg;
2087 
2088 	DTRACE_PROBE2(pmcs__watchdog, ulong_t, pwp->work_flags, boolean_t,
2089 	    pwp->config_changed);
2090 
2091 	/*
2092 	 * Check forward progress on the chip
2093 	 */
2094 	if (++pwp->watchdog_count == PMCS_FWD_PROG_TRIGGER) {
2095 		pwp->watchdog_count = 0;
2096 		pmcs_check_forward_progress(pwp);
2097 	}
2098 
2099 	/*
2100 	 * Check to see if we need to kick discovery off again
2101 	 */
2102 	mutex_enter(&pwp->config_lock);
2103 	if (pwp->config_restart &&
2104 	    (ddi_get_lbolt() >= pwp->config_restart_time)) {
2105 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2106 		    "%s: Timer expired for re-enumeration: Start discovery",
2107 		    __func__);
2108 		pwp->config_restart = B_FALSE;
2109 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2110 	}
2111 	mutex_exit(&pwp->config_lock);
2112 
2113 	mutex_enter(&pwp->lock);
2114 	if (pwp->state != STATE_RUNNING) {
2115 		mutex_exit(&pwp->lock);
2116 		return;
2117 	}
2118 
2119 	if (atomic_cas_ulong(&pwp->work_flags, 0, 0) != 0) {
2120 		if (ddi_taskq_dispatch(pwp->tq, pmcs_worker, pwp,
2121 		    DDI_NOSLEEP) != DDI_SUCCESS) {
2122 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2123 			    "Could not dispatch to worker thread");
2124 		}
2125 	}
2126 	pwp->wdhandle = timeout(pmcs_watchdog, pwp,
2127 	    drv_usectohz(PMCS_WATCH_INTERVAL));
2128 
2129 	mutex_exit(&pwp->lock);
2130 
2131 	pmcs_check_commands(pwp);
2132 	pmcs_handle_dead_phys(pwp);
2133 }
2134 
2135 static int
2136 pmcs_remove_ihandlers(pmcs_hw_t *pwp, int icnt)
2137 {
2138 	int i, r, rslt = 0;
2139 	for (i = 0; i < icnt; i++) {
2140 		r = ddi_intr_remove_handler(pwp->ih_table[i]);
2141 		if (r == DDI_SUCCESS) {
2142 			continue;
2143 		}
2144 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2145 		    "%s: unable to remove interrupt handler %d", __func__, i);
2146 		rslt = -1;
2147 		break;
2148 	}
2149 	return (rslt);
2150 }
2151 
2152 static int
2153 pmcs_disable_intrs(pmcs_hw_t *pwp, int icnt)
2154 {
2155 	if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
2156 		int r = ddi_intr_block_disable(&pwp->ih_table[0],
2157 		    pwp->intr_cnt);
2158 		if (r != DDI_SUCCESS) {
2159 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2160 			    "unable to disable interrupt block");
2161 			return (-1);
2162 		}
2163 	} else {
2164 		int i;
2165 		for (i = 0; i < icnt; i++) {
2166 			if (ddi_intr_disable(pwp->ih_table[i]) == DDI_SUCCESS) {
2167 				continue;
2168 			}
2169 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2170 			    "unable to disable interrupt %d", i);
2171 			return (-1);
2172 		}
2173 	}
2174 	return (0);
2175 }
2176 
2177 static int
2178 pmcs_free_intrs(pmcs_hw_t *pwp, int icnt)
2179 {
2180 	int i;
2181 	for (i = 0; i < icnt; i++) {
2182 		if (ddi_intr_free(pwp->ih_table[i]) == DDI_SUCCESS) {
2183 			continue;
2184 		}
2185 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2186 		    "unable to free interrupt %d", i);
2187 		return (-1);
2188 	}
2189 	kmem_free(pwp->ih_table, pwp->ih_table_size);
2190 	pwp->ih_table_size = 0;
2191 	return (0);
2192 }
2193 
2194 /*
2195  * Try to set up interrupts of type "type" with a minimum number of interrupts
2196  * of "min".
2197  */
2198 static void
2199 pmcs_setup_intr_impl(pmcs_hw_t *pwp, int type, int min)
2200 {
2201 	int rval, avail, count, actual, max;
2202 
2203 	rval = ddi_intr_get_nintrs(pwp->dip, type, &count);
2204 	if ((rval != DDI_SUCCESS) || (count < min)) {
2205 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2206 		    "%s: get_nintrs failed; type: %d rc: %d count: %d min: %d",
2207 		    __func__, type, rval, count, min);
2208 		return;
2209 	}
2210 
2211 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2212 	    "%s: nintrs = %d for type: %d", __func__, count, type);
2213 
2214 	rval = ddi_intr_get_navail(pwp->dip, type, &avail);
2215 	if ((rval != DDI_SUCCESS) || (avail < min)) {
2216 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2217 		    "%s: get_navail failed; type: %d rc: %d avail: %d min: %d",
2218 		    __func__, type, rval, avail, min);
2219 		return;
2220 	}
2221 
2222 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2223 	    "%s: navail = %d for type: %d", __func__, avail, type);
2224 
2225 	pwp->ih_table_size = avail * sizeof (ddi_intr_handle_t);
2226 	pwp->ih_table = kmem_alloc(pwp->ih_table_size, KM_SLEEP);
2227 
2228 	switch (type) {
2229 	case DDI_INTR_TYPE_MSIX:
2230 		pwp->int_type = PMCS_INT_MSIX;
2231 		max = PMCS_MAX_MSIX;
2232 		break;
2233 	case DDI_INTR_TYPE_MSI:
2234 		pwp->int_type = PMCS_INT_MSI;
2235 		max = PMCS_MAX_MSI;
2236 		break;
2237 	case DDI_INTR_TYPE_FIXED:
2238 	default:
2239 		pwp->int_type = PMCS_INT_FIXED;
2240 		max = PMCS_MAX_FIXED;
2241 		break;
2242 	}
2243 
2244 	rval = ddi_intr_alloc(pwp->dip, pwp->ih_table, type, 0, max, &actual,
2245 	    DDI_INTR_ALLOC_NORMAL);
2246 	if (rval != DDI_SUCCESS) {
2247 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2248 		    "%s: ddi_intr_alloc failed; type: %d rc: %d",
2249 		    __func__, type, rval);
2250 		kmem_free(pwp->ih_table, pwp->ih_table_size);
2251 		pwp->ih_table = NULL;
2252 		pwp->ih_table_size = 0;
2253 		pwp->intr_cnt = 0;
2254 		pwp->int_type = PMCS_INT_NONE;
2255 		return;
2256 	}
2257 
2258 	pwp->intr_cnt = actual;
2259 }
2260 
2261 /*
2262  * Set up interrupts.
2263  * We return one of three values:
2264  *
2265  * 0 - success
2266  * EAGAIN - failure to set up interrupts
2267  * EIO - "" + we're now stuck partly enabled
2268  *
2269  * If EIO is returned, we can't unload the driver.
2270  */
2271 static int
2272 pmcs_setup_intr(pmcs_hw_t *pwp)
2273 {
2274 	int i, r, itypes, oqv_count;
2275 	ddi_intr_handler_t **iv_table;
2276 	size_t iv_table_size;
2277 	uint_t pri;
2278 
2279 	if (ddi_intr_get_supported_types(pwp->dip, &itypes) != DDI_SUCCESS) {
2280 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2281 		    "cannot get interrupt types");
2282 		return (EAGAIN);
2283 	}
2284 
2285 	if (disable_msix) {
2286 		itypes &= ~DDI_INTR_TYPE_MSIX;
2287 	}
2288 	if (disable_msi) {
2289 		itypes &= ~DDI_INTR_TYPE_MSI;
2290 	}
2291 
2292 	/*
2293 	 * We won't know what firmware we're running until we call pmcs_setup,
2294 	 * and we can't call pmcs_setup until we establish interrupts.
2295 	 */
2296 
2297 	pwp->int_type = PMCS_INT_NONE;
2298 
2299 	/*
2300 	 * We want PMCS_MAX_MSIX vectors for MSI-X.  Anything less would be
2301 	 * uncivilized.
2302 	 */
2303 	if (itypes & DDI_INTR_TYPE_MSIX) {
2304 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSIX, PMCS_MAX_MSIX);
2305 		if (pwp->int_type == PMCS_INT_MSIX) {
2306 			itypes = 0;
2307 		}
2308 	}
2309 
2310 	if (itypes & DDI_INTR_TYPE_MSI) {
2311 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSI, 1);
2312 		if (pwp->int_type == PMCS_INT_MSI) {
2313 			itypes = 0;
2314 		}
2315 	}
2316 
2317 	if (itypes & DDI_INTR_TYPE_FIXED) {
2318 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_FIXED, 1);
2319 		if (pwp->int_type == PMCS_INT_FIXED) {
2320 			itypes = 0;
2321 		}
2322 	}
2323 
2324 	if (pwp->intr_cnt == 0) {
2325 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2326 		    "No interrupts available");
2327 		return (EAGAIN);
2328 	}
2329 
2330 	iv_table_size = sizeof (ddi_intr_handler_t *) * pwp->intr_cnt;
2331 	iv_table = kmem_alloc(iv_table_size, KM_SLEEP);
2332 
2333 	/*
2334 	 * Get iblock cookie and add handlers.
2335 	 */
2336 	switch (pwp->intr_cnt) {
2337 	case 1:
2338 		iv_table[0] = pmcs_all_intr;
2339 		break;
2340 	case 2:
2341 		iv_table[0] = pmcs_iodone_ix;
2342 		iv_table[1] = pmcs_nonio_ix;
2343 		break;
2344 	case 4:
2345 		iv_table[PMCS_MSIX_GENERAL] = pmcs_general_ix;
2346 		iv_table[PMCS_MSIX_IODONE] = pmcs_iodone_ix;
2347 		iv_table[PMCS_MSIX_EVENTS] = pmcs_event_ix;
2348 		iv_table[PMCS_MSIX_FATAL] = pmcs_fatal_ix;
2349 		break;
2350 	default:
2351 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2352 		    "%s: intr_cnt = %d - unexpected", __func__, pwp->intr_cnt);
2353 		kmem_free(iv_table, iv_table_size);
2354 		return (EAGAIN);
2355 	}
2356 
2357 	for (i = 0; i < pwp->intr_cnt; i++) {
2358 		r = ddi_intr_add_handler(pwp->ih_table[i], iv_table[i],
2359 		    (caddr_t)pwp, NULL);
2360 		if (r != DDI_SUCCESS) {
2361 			kmem_free(iv_table, iv_table_size);
2362 			if (pmcs_remove_ihandlers(pwp, i)) {
2363 				return (EIO);
2364 			}
2365 			if (pmcs_free_intrs(pwp, i)) {
2366 				return (EIO);
2367 			}
2368 			pwp->intr_cnt = 0;
2369 			return (EAGAIN);
2370 		}
2371 	}
2372 
2373 	kmem_free(iv_table, iv_table_size);
2374 
2375 	if (ddi_intr_get_cap(pwp->ih_table[0], &pwp->intr_cap) != DDI_SUCCESS) {
2376 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2377 		    "unable to get int capabilities");
2378 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2379 			return (EIO);
2380 		}
2381 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2382 			return (EIO);
2383 		}
2384 		pwp->intr_cnt = 0;
2385 		return (EAGAIN);
2386 	}
2387 
2388 	if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
2389 		r = ddi_intr_block_enable(&pwp->ih_table[0], pwp->intr_cnt);
2390 		if (r != DDI_SUCCESS) {
2391 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2392 			    "intr blk enable failed");
2393 			if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2394 				return (EIO);
2395 			}
2396 			if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2397 				return (EIO);
2398 			}
2399 			pwp->intr_cnt = 0;
2400 			return (EFAULT);
2401 		}
2402 	} else {
2403 		for (i = 0; i < pwp->intr_cnt; i++) {
2404 			r = ddi_intr_enable(pwp->ih_table[i]);
2405 			if (r == DDI_SUCCESS) {
2406 				continue;
2407 			}
2408 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2409 			    "unable to enable interrupt %d", i);
2410 			if (pmcs_disable_intrs(pwp, i)) {
2411 				return (EIO);
2412 			}
2413 			if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2414 				return (EIO);
2415 			}
2416 			if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2417 				return (EIO);
2418 			}
2419 			pwp->intr_cnt = 0;
2420 			return (EAGAIN);
2421 		}
2422 	}
2423 
2424 	/*
2425 	 * Set up locks.
2426 	 */
2427 	if (ddi_intr_get_pri(pwp->ih_table[0], &pri) != DDI_SUCCESS) {
2428 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2429 		    "unable to get interrupt priority");
2430 		if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
2431 			return (EIO);
2432 		}
2433 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2434 			return (EIO);
2435 		}
2436 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2437 			return (EIO);
2438 		}
2439 		pwp->intr_cnt = 0;
2440 		return (EAGAIN);
2441 	}
2442 
2443 	pwp->locks_initted = 1;
2444 	pwp->intr_pri = pri;
2445 	mutex_init(&pwp->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2446 	mutex_init(&pwp->dma_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2447 	mutex_init(&pwp->axil_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2448 	mutex_init(&pwp->cq_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2449 	mutex_init(&pwp->ict_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2450 	mutex_init(&pwp->config_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2451 	mutex_init(&pwp->wfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2452 	mutex_init(&pwp->pfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2453 	mutex_init(&pwp->dead_phylist_lock, NULL, MUTEX_DRIVER,
2454 	    DDI_INTR_PRI(pri));
2455 #ifdef	DEBUG
2456 	mutex_init(&pwp->dbglock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2457 #endif
2458 	cv_init(&pwp->ict_cv, NULL, CV_DRIVER, NULL);
2459 	cv_init(&pwp->drain_cv, NULL, CV_DRIVER, NULL);
2460 	for (i = 0; i < PMCS_NIQ; i++) {
2461 		mutex_init(&pwp->iqp_lock[i], NULL,
2462 		    MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
2463 	}
2464 	for (i = 0; i < pwp->cq_info.cq_threads; i++) {
2465 		mutex_init(&pwp->cq_info.cq_thr_info[i].cq_thr_lock, NULL,
2466 		    MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
2467 		cv_init(&pwp->cq_info.cq_thr_info[i].cq_cv, NULL,
2468 		    CV_DRIVER, NULL);
2469 	}
2470 
2471 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "%d %s interrup%s configured",
2472 	    pwp->intr_cnt, (pwp->int_type == PMCS_INT_MSIX)? "MSI-X" :
2473 	    ((pwp->int_type == PMCS_INT_MSI)? "MSI" : "INT-X"),
2474 	    pwp->intr_cnt == 1? "t" : "ts");
2475 
2476 
2477 	/*
2478 	 * Enable Interrupts
2479 	 */
2480 	if (pwp->intr_cnt > PMCS_NOQ) {
2481 		oqv_count = pwp->intr_cnt;
2482 	} else {
2483 		oqv_count = PMCS_NOQ;
2484 	}
2485 	for (pri = 0xffffffff, i = 0; i < oqv_count; i++) {
2486 		pri ^= (1 << i);
2487 	}
2488 
2489 	mutex_enter(&pwp->lock);
2490 	pwp->intr_mask = pri;
2491 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
2492 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
2493 	mutex_exit(&pwp->lock);
2494 
2495 	return (0);
2496 }
2497 
2498 static int
2499 pmcs_teardown_intr(pmcs_hw_t *pwp)
2500 {
2501 	if (pwp->intr_cnt) {
2502 		if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
2503 			return (EIO);
2504 		}
2505 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2506 			return (EIO);
2507 		}
2508 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2509 			return (EIO);
2510 		}
2511 		pwp->intr_cnt = 0;
2512 	}
2513 	return (0);
2514 }
2515 
2516 static uint_t
2517 pmcs_general_ix(caddr_t arg1, caddr_t arg2)
2518 {
2519 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2520 	_NOTE(ARGUNUSED(arg2));
2521 	pmcs_general_intr(pwp);
2522 	return (DDI_INTR_CLAIMED);
2523 }
2524 
2525 static uint_t
2526 pmcs_event_ix(caddr_t arg1, caddr_t arg2)
2527 {
2528 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2529 	_NOTE(ARGUNUSED(arg2));
2530 	pmcs_event_intr(pwp);
2531 	return (DDI_INTR_CLAIMED);
2532 }
2533 
2534 static uint_t
2535 pmcs_iodone_ix(caddr_t arg1, caddr_t arg2)
2536 {
2537 	_NOTE(ARGUNUSED(arg2));
2538 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2539 
2540 	/*
2541 	 * It's possible that if we just turned interrupt coalescing off
2542 	 * (and thus, re-enabled auto clear for interrupts on the I/O outbound
2543 	 * queue) that there was an interrupt already pending.  We use
2544 	 * io_intr_coal.int_cleared to ensure that we still drop in here and
2545 	 * clear the appropriate interrupt bit one last time.
2546 	 */
2547 	mutex_enter(&pwp->ict_lock);
2548 	if (pwp->io_intr_coal.timer_on ||
2549 	    (pwp->io_intr_coal.int_cleared == B_FALSE)) {
2550 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2551 		    (1 << PMCS_OQ_IODONE));
2552 		pwp->io_intr_coal.int_cleared = B_TRUE;
2553 	}
2554 	mutex_exit(&pwp->ict_lock);
2555 
2556 	pmcs_iodone_intr(pwp);
2557 
2558 	return (DDI_INTR_CLAIMED);
2559 }
2560 
2561 static uint_t
2562 pmcs_fatal_ix(caddr_t arg1, caddr_t arg2)
2563 {
2564 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2565 	_NOTE(ARGUNUSED(arg2));
2566 	pmcs_fatal_handler(pwp);
2567 	return (DDI_INTR_CLAIMED);
2568 }
2569 
2570 static uint_t
2571 pmcs_nonio_ix(caddr_t arg1, caddr_t arg2)
2572 {
2573 	_NOTE(ARGUNUSED(arg2));
2574 	pmcs_hw_t *pwp = (void *)arg1;
2575 	uint32_t obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
2576 
2577 	/*
2578 	 * Check for Fatal Interrupts
2579 	 */
2580 	if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
2581 		pmcs_fatal_handler(pwp);
2582 		return (DDI_INTR_CLAIMED);
2583 	}
2584 
2585 	if (obdb & (1 << PMCS_OQ_GENERAL)) {
2586 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2587 		    (1 << PMCS_OQ_GENERAL));
2588 		pmcs_general_intr(pwp);
2589 		pmcs_event_intr(pwp);
2590 	}
2591 
2592 	return (DDI_INTR_CLAIMED);
2593 }
2594 
2595 static uint_t
2596 pmcs_all_intr(caddr_t arg1, caddr_t arg2)
2597 {
2598 	_NOTE(ARGUNUSED(arg2));
2599 	pmcs_hw_t *pwp = (void *) arg1;
2600 	uint32_t obdb;
2601 	int handled = 0;
2602 
2603 	obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
2604 
2605 	/*
2606 	 * Check for Fatal Interrupts
2607 	 */
2608 	if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
2609 		pmcs_fatal_handler(pwp);
2610 		return (DDI_INTR_CLAIMED);
2611 	}
2612 
2613 	/*
2614 	 * Check for Outbound Queue service needed
2615 	 */
2616 	if (obdb & (1 << PMCS_OQ_IODONE)) {
2617 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2618 		    (1 << PMCS_OQ_IODONE));
2619 		obdb ^= (1 << PMCS_OQ_IODONE);
2620 		handled++;
2621 		pmcs_iodone_intr(pwp);
2622 	}
2623 	if (obdb & (1 << PMCS_OQ_GENERAL)) {
2624 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2625 		    (1 << PMCS_OQ_GENERAL));
2626 		obdb ^= (1 << PMCS_OQ_GENERAL);
2627 		handled++;
2628 		pmcs_general_intr(pwp);
2629 	}
2630 	if (obdb & (1 << PMCS_OQ_EVENTS)) {
2631 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2632 		    (1 << PMCS_OQ_EVENTS));
2633 		obdb ^= (1 << PMCS_OQ_EVENTS);
2634 		handled++;
2635 		pmcs_event_intr(pwp);
2636 	}
2637 	if (obdb) {
2638 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2639 		    "interrupt bits not handled (0x%x)", obdb);
2640 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, obdb);
2641 		handled++;
2642 	}
2643 	if (pwp->int_type == PMCS_INT_MSI) {
2644 		handled++;
2645 	}
2646 	return (handled? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
2647 }
2648 
2649 void
2650 pmcs_fatal_handler(pmcs_hw_t *pwp)
2651 {
2652 	pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, "Fatal Interrupt caught");
2653 
2654 	mutex_enter(&pwp->lock);
2655 	pwp->state = STATE_DEAD;
2656 
2657 	/*
2658 	 * Attempt a hot reset. In case of failure, pmcs_hot_reset() will
2659 	 * handle the failure and issue any required FM notifications.
2660 	 * See pmcs_subr.c for more details.
2661 	 */
2662 	if (pmcs_hot_reset(pwp)) {
2663 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2664 		    "%s: hot reset failure", __func__);
2665 	} else {
2666 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2667 		    "%s: hot reset complete", __func__);
2668 		pwp->last_reset_reason = PMCS_LAST_RST_FATAL_ERROR;
2669 	}
2670 	mutex_exit(&pwp->lock);
2671 }
2672 
2673 /*
2674  * Called with PHY lock and target statlock held and scratch acquired.
2675  */
2676 boolean_t
2677 pmcs_assign_device(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt)
2678 {
2679 	pmcs_phy_t *pptr = tgt->phy;
2680 
2681 	switch (pptr->dtype) {
2682 	case SAS:
2683 	case EXPANDER:
2684 		break;
2685 	case SATA:
2686 		tgt->ca = 1;
2687 		break;
2688 	default:
2689 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2690 		    "%s: Target %p has PHY %p with invalid dtype",
2691 		    __func__, (void *)tgt, (void *)pptr);
2692 		return (B_FALSE);
2693 	}
2694 
2695 	tgt->new = 1;
2696 	tgt->dev_gone = 0;
2697 	tgt->recover_wait = 0;
2698 
2699 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2700 	    "%s: config %s vtgt %u for " SAS_ADDR_FMT, __func__,
2701 	    pptr->path, tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
2702 
2703 	if (pmcs_add_new_device(pwp, tgt) != B_TRUE) {
2704 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2705 		    "%s: Failed for vtgt %u / WWN " SAS_ADDR_FMT, __func__,
2706 		    tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
2707 		mutex_destroy(&tgt->statlock);
2708 		mutex_destroy(&tgt->wqlock);
2709 		mutex_destroy(&tgt->aqlock);
2710 		return (B_FALSE);
2711 	}
2712 
2713 	return (B_TRUE);
2714 }
2715 
2716 /*
2717  * Called with softstate lock held
2718  */
2719 void
2720 pmcs_remove_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2721 {
2722 	pmcs_xscsi_t *xp;
2723 	unsigned int vtgt;
2724 
2725 	ASSERT(mutex_owned(&pwp->lock));
2726 
2727 	for (vtgt = 0; vtgt < pwp->max_dev; vtgt++) {
2728 		xp = pwp->targets[vtgt];
2729 		if (xp == NULL) {
2730 			continue;
2731 		}
2732 
2733 		mutex_enter(&xp->statlock);
2734 		if (xp->phy == pptr) {
2735 			if (xp->new) {
2736 				xp->new = 0;
2737 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
2738 				    "cancel config of vtgt %u", vtgt);
2739 			} else {
2740 				pmcs_clear_xp(pwp, xp);
2741 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
2742 				    "Removed tgt 0x%p vtgt %u",
2743 				    (void *)xp, vtgt);
2744 			}
2745 			mutex_exit(&xp->statlock);
2746 			break;
2747 		}
2748 		mutex_exit(&xp->statlock);
2749 	}
2750 }
2751 
2752 void
2753 pmcs_prt_impl(pmcs_hw_t *pwp, pmcs_prt_level_t level,
2754     pmcs_phy_t *phyp, pmcs_xscsi_t *target, const char *fmt, ...)
2755 {
2756 	va_list	ap;
2757 	int written = 0;
2758 	char *ptr;
2759 	uint32_t elem_size = PMCS_TBUF_ELEM_SIZE - 1;
2760 	boolean_t system_log;
2761 	int system_log_level;
2762 
2763 	switch (level) {
2764 	case PMCS_PRT_DEBUG_DEVEL:
2765 	case PMCS_PRT_DEBUG_DEV_STATE:
2766 	case PMCS_PRT_DEBUG_PHY_LOCKING:
2767 	case PMCS_PRT_DEBUG_SCSI_STATUS:
2768 	case PMCS_PRT_DEBUG_UNDERFLOW:
2769 	case PMCS_PRT_DEBUG_CONFIG:
2770 	case PMCS_PRT_DEBUG_IPORT:
2771 	case PMCS_PRT_DEBUG_MAP:
2772 	case PMCS_PRT_DEBUG3:
2773 	case PMCS_PRT_DEBUG2:
2774 	case PMCS_PRT_DEBUG1:
2775 	case PMCS_PRT_DEBUG:
2776 		system_log = B_FALSE;
2777 		break;
2778 	case PMCS_PRT_INFO:
2779 		system_log = B_TRUE;
2780 		system_log_level = CE_CONT;
2781 		break;
2782 	case PMCS_PRT_WARN:
2783 		system_log = B_TRUE;
2784 		system_log_level = CE_NOTE;
2785 		break;
2786 	case PMCS_PRT_ERR:
2787 		system_log = B_TRUE;
2788 		system_log_level = CE_WARN;
2789 		break;
2790 	default:
2791 		return;
2792 	}
2793 
2794 	mutex_enter(&pmcs_trace_lock);
2795 	gethrestime(&pmcs_tbuf_ptr->timestamp);
2796 	ptr = pmcs_tbuf_ptr->buf;
2797 
2798 	/*
2799 	 * Store the pertinent PHY and target information if there is any
2800 	 */
2801 	if (target == NULL) {
2802 		pmcs_tbuf_ptr->target_num = PMCS_INVALID_TARGET_NUM;
2803 		pmcs_tbuf_ptr->target_ua[0] = '\0';
2804 	} else {
2805 		pmcs_tbuf_ptr->target_num = target->target_num;
2806 		(void) strncpy(pmcs_tbuf_ptr->target_ua, target->ua,
2807 		    PMCS_TBUF_UA_MAX_SIZE);
2808 	}
2809 
2810 	if (phyp == NULL) {
2811 		(void) memset(pmcs_tbuf_ptr->phy_sas_address, 0, 8);
2812 		pmcs_tbuf_ptr->phy_path[0] = '\0';
2813 		pmcs_tbuf_ptr->phy_dtype = NOTHING;
2814 	} else {
2815 		(void) memcpy(pmcs_tbuf_ptr->phy_sas_address,
2816 		    phyp->sas_address, 8);
2817 		(void) strncpy(pmcs_tbuf_ptr->phy_path, phyp->path, 32);
2818 		pmcs_tbuf_ptr->phy_dtype = phyp->dtype;
2819 	}
2820 
2821 	written += snprintf(ptr, elem_size, "pmcs%d:%d: ",
2822 	    ddi_get_instance(pwp->dip), level);
2823 	ptr += strlen(ptr);
2824 	va_start(ap, fmt);
2825 	written += vsnprintf(ptr, elem_size - written, fmt, ap);
2826 	va_end(ap);
2827 	if (written > elem_size - 1) {
2828 		/* Indicate truncation */
2829 		pmcs_tbuf_ptr->buf[elem_size - 1] = '+';
2830 	}
2831 	if (++pmcs_tbuf_idx == pmcs_tbuf_num_elems) {
2832 		pmcs_tbuf_ptr = pmcs_tbuf;
2833 		pmcs_tbuf_wrap = B_TRUE;
2834 		pmcs_tbuf_idx = 0;
2835 	} else {
2836 		++pmcs_tbuf_ptr;
2837 	}
2838 	mutex_exit(&pmcs_trace_lock);
2839 
2840 	/*
2841 	 * When pmcs_force_syslog in non-zero, everything goes also
2842 	 * to syslog, at CE_CONT level.
2843 	 */
2844 	if (pmcs_force_syslog) {
2845 		system_log = B_TRUE;
2846 		system_log_level = CE_CONT;
2847 	}
2848 
2849 	/*
2850 	 * Anything that comes in with PMCS_PRT_INFO, WARN, or ERR also
2851 	 * goes to syslog.
2852 	 */
2853 	if (system_log) {
2854 		char local[196];
2855 
2856 		switch (system_log_level) {
2857 		case CE_CONT:
2858 			(void) snprintf(local, sizeof (local), "%sINFO: ",
2859 			    pmcs_console ? "" : "?");
2860 			break;
2861 		case CE_NOTE:
2862 		case CE_WARN:
2863 			local[0] = 0;
2864 			break;
2865 		default:
2866 			return;
2867 		}
2868 
2869 		ptr = local;
2870 		ptr += strlen(local);
2871 		(void) snprintf(ptr, (sizeof (local)) -
2872 		    ((size_t)ptr - (size_t)local), "pmcs%d: ",
2873 		    ddi_get_instance(pwp->dip));
2874 		ptr += strlen(ptr);
2875 		va_start(ap, fmt);
2876 		(void) vsnprintf(ptr,
2877 		    (sizeof (local)) - ((size_t)ptr - (size_t)local), fmt, ap);
2878 		va_end(ap);
2879 		if (level == CE_CONT) {
2880 			(void) strlcat(local, "\n", sizeof (local));
2881 		}
2882 		cmn_err(system_log_level, local);
2883 	}
2884 
2885 }
2886 
2887 /*
2888  * pmcs_acquire_scratch
2889  *
2890  * If "wait" is true, the caller will wait until it can acquire the scratch.
2891  * This implies the caller needs to be in a context where spinning for an
2892  * indeterminate amount of time is acceptable.
2893  */
2894 int
2895 pmcs_acquire_scratch(pmcs_hw_t *pwp, boolean_t wait)
2896 {
2897 	int rval;
2898 
2899 	if (!wait) {
2900 		return (atomic_swap_8(&pwp->scratch_locked, 1));
2901 	}
2902 
2903 	/*
2904 	 * Caller will wait for scratch.
2905 	 */
2906 	while ((rval = atomic_swap_8(&pwp->scratch_locked, 1)) != 0) {
2907 		drv_usecwait(100);
2908 	}
2909 
2910 	return (rval);
2911 }
2912 
2913 void
2914 pmcs_release_scratch(pmcs_hw_t *pwp)
2915 {
2916 	pwp->scratch_locked = 0;
2917 }
2918 
2919 static void
2920 pmcs_create_phy_stats(pmcs_iport_t *iport)
2921 {
2922 	sas_phy_stats_t		*ps;
2923 	pmcs_hw_t		*pwp;
2924 	pmcs_phy_t		*phyp;
2925 	int			ndata;
2926 	char			ks_name[KSTAT_STRLEN];
2927 
2928 	ASSERT(iport != NULL);
2929 	pwp = iport->pwp;
2930 	ASSERT(pwp != NULL);
2931 
2932 	mutex_enter(&iport->lock);
2933 
2934 	for (phyp = list_head(&iport->phys);
2935 	    phyp != NULL;
2936 	    phyp = list_next(&iport->phys, phyp)) {
2937 
2938 		pmcs_lock_phy(phyp);
2939 
2940 		if (phyp->phy_stats != NULL) {
2941 			pmcs_unlock_phy(phyp);
2942 			/* We've already created this kstat instance */
2943 			continue;
2944 		}
2945 
2946 		ndata = (sizeof (sas_phy_stats_t)/sizeof (kstat_named_t));
2947 
2948 		(void) snprintf(ks_name, sizeof (ks_name),
2949 		    "%s.%llx.%d.%d", ddi_driver_name(iport->dip),
2950 		    (longlong_t)pwp->sas_wwns[0],
2951 		    ddi_get_instance(iport->dip), phyp->phynum);
2952 
2953 		phyp->phy_stats = kstat_create("pmcs",
2954 		    ddi_get_instance(iport->dip), ks_name, KSTAT_SAS_PHY_CLASS,
2955 		    KSTAT_TYPE_NAMED, ndata, 0);
2956 
2957 		if (phyp->phy_stats == NULL) {
2958 			pmcs_unlock_phy(phyp);
2959 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
2960 			    "%s: Failed to create %s kstats", __func__,
2961 			    ks_name);
2962 			continue;
2963 		}
2964 
2965 		ps = (sas_phy_stats_t *)phyp->phy_stats->ks_data;
2966 
2967 		kstat_named_init(&ps->seconds_since_last_reset,
2968 		    "SecondsSinceLastReset", KSTAT_DATA_ULONGLONG);
2969 		kstat_named_init(&ps->tx_frames,
2970 		    "TxFrames", KSTAT_DATA_ULONGLONG);
2971 		kstat_named_init(&ps->rx_frames,
2972 		    "RxFrames", KSTAT_DATA_ULONGLONG);
2973 		kstat_named_init(&ps->tx_words,
2974 		    "TxWords", KSTAT_DATA_ULONGLONG);
2975 		kstat_named_init(&ps->rx_words,
2976 		    "RxWords", KSTAT_DATA_ULONGLONG);
2977 		kstat_named_init(&ps->invalid_dword_count,
2978 		    "InvalidDwordCount", KSTAT_DATA_ULONGLONG);
2979 		kstat_named_init(&ps->running_disparity_error_count,
2980 		    "RunningDisparityErrorCount", KSTAT_DATA_ULONGLONG);
2981 		kstat_named_init(&ps->loss_of_dword_sync_count,
2982 		    "LossofDwordSyncCount", KSTAT_DATA_ULONGLONG);
2983 		kstat_named_init(&ps->phy_reset_problem_count,
2984 		    "PhyResetProblemCount", KSTAT_DATA_ULONGLONG);
2985 
2986 		phyp->phy_stats->ks_private = phyp;
2987 		phyp->phy_stats->ks_update = pmcs_update_phy_stats;
2988 		kstat_install(phyp->phy_stats);
2989 		pmcs_unlock_phy(phyp);
2990 	}
2991 
2992 	mutex_exit(&iport->lock);
2993 }
2994 
2995 int
2996 pmcs_update_phy_stats(kstat_t *ks, int rw)
2997 {
2998 	int		val, ret = DDI_FAILURE;
2999 	pmcs_phy_t	*pptr = (pmcs_phy_t *)ks->ks_private;
3000 	pmcs_hw_t	*pwp = pptr->pwp;
3001 	sas_phy_stats_t	*ps = ks->ks_data;
3002 
3003 	_NOTE(ARGUNUSED(rw));
3004 	ASSERT((pptr != NULL) && (pwp != NULL));
3005 
3006 	/*
3007 	 * We just want to lock against other invocations of kstat;
3008 	 * we don't need to pmcs_lock_phy() for this.
3009 	 */
3010 	mutex_enter(&pptr->phy_lock);
3011 
3012 	/* Get Stats from Chip */
3013 	val = pmcs_get_diag_report(pwp, PMCS_INVALID_DWORD_CNT, pptr->phynum);
3014 	if (val == DDI_FAILURE)
3015 		goto fail;
3016 	ps->invalid_dword_count.value.ull = (unsigned long long)val;
3017 
3018 	val = pmcs_get_diag_report(pwp, PMCS_DISPARITY_ERR_CNT, pptr->phynum);
3019 	if (val == DDI_FAILURE)
3020 		goto fail;
3021 	ps->running_disparity_error_count.value.ull = (unsigned long long)val;
3022 
3023 	val = pmcs_get_diag_report(pwp, PMCS_LOST_DWORD_SYNC_CNT, pptr->phynum);
3024 	if (val == DDI_FAILURE)
3025 		goto fail;
3026 	ps->loss_of_dword_sync_count.value.ull = (unsigned long long)val;
3027 
3028 	val = pmcs_get_diag_report(pwp, PMCS_RESET_FAILED_CNT, pptr->phynum);
3029 	if (val == DDI_FAILURE)
3030 		goto fail;
3031 	ps->phy_reset_problem_count.value.ull = (unsigned long long)val;
3032 
3033 	ret = DDI_SUCCESS;
3034 fail:
3035 	mutex_exit(&pptr->phy_lock);
3036 	return (ret);
3037 }
3038 
3039 static void
3040 pmcs_destroy_phy_stats(pmcs_iport_t *iport)
3041 {
3042 	pmcs_phy_t		*phyp;
3043 
3044 	ASSERT(iport != NULL);
3045 	mutex_enter(&iport->lock);
3046 	phyp = iport->pptr;
3047 	if (phyp == NULL) {
3048 		mutex_exit(&iport->lock);
3049 		return;
3050 	}
3051 
3052 	pmcs_lock_phy(phyp);
3053 	if (phyp->phy_stats != NULL) {
3054 		kstat_delete(phyp->phy_stats);
3055 		phyp->phy_stats = NULL;
3056 	}
3057 	pmcs_unlock_phy(phyp);
3058 
3059 	mutex_exit(&iport->lock);
3060 }
3061 
3062 /*ARGSUSED*/
3063 static int
3064 pmcs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
3065 {
3066 	/*
3067 	 * as the driver can always deal with an error in any dma or
3068 	 * access handle, we can just return the fme_status value.
3069 	 */
3070 	pci_ereport_post(dip, err, NULL);
3071 	return (err->fme_status);
3072 }
3073 
3074 static void
3075 pmcs_fm_init(pmcs_hw_t *pwp)
3076 {
3077 	ddi_iblock_cookie_t	fm_ibc;
3078 
3079 	/* Only register with IO Fault Services if we have some capability */
3080 	if (pwp->fm_capabilities) {
3081 		/* Adjust access and dma attributes for FMA */
3082 		pwp->reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
3083 		pwp->iqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3084 		pwp->oqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3085 		pwp->cip_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3086 		pwp->fwlog_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3087 
3088 		/*
3089 		 * Register capabilities with IO Fault Services.
3090 		 */
3091 		ddi_fm_init(pwp->dip, &pwp->fm_capabilities, &fm_ibc);
3092 
3093 		/*
3094 		 * Initialize pci ereport capabilities if ereport
3095 		 * capable (should always be.)
3096 		 */
3097 		if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
3098 		    DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3099 			pci_ereport_setup(pwp->dip);
3100 		}
3101 
3102 		/*
3103 		 * Register error callback if error callback capable.
3104 		 */
3105 		if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3106 			ddi_fm_handler_register(pwp->dip,
3107 			    pmcs_fm_error_cb, (void *) pwp);
3108 		}
3109 	}
3110 }
3111 
3112 static void
3113 pmcs_fm_fini(pmcs_hw_t *pwp)
3114 {
3115 	/* Only unregister FMA capabilities if registered */
3116 	if (pwp->fm_capabilities) {
3117 		/*
3118 		 * Un-register error callback if error callback capable.
3119 		 */
3120 		if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3121 			ddi_fm_handler_unregister(pwp->dip);
3122 		}
3123 
3124 		/*
3125 		 * Release any resources allocated by pci_ereport_setup()
3126 		 */
3127 		if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
3128 		    DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3129 			pci_ereport_teardown(pwp->dip);
3130 		}
3131 
3132 		/* Unregister from IO Fault Services */
3133 		ddi_fm_fini(pwp->dip);
3134 
3135 		/* Adjust access and dma attributes for FMA */
3136 		pwp->reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
3137 		pwp->iqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3138 		pwp->oqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3139 		pwp->cip_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3140 		pwp->fwlog_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3141 	}
3142 }
3143 
3144 static boolean_t
3145 pmcs_fabricate_wwid(pmcs_hw_t *pwp)
3146 {
3147 	char *cp, c;
3148 	uint64_t adr;
3149 	int i;
3150 
3151 	cp = &c;
3152 	(void) ddi_strtoul(hw_serial, &cp, 10, (unsigned long *)&adr);
3153 
3154 	if (adr == 0) {
3155 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
3156 		    "%s: No serial number available to fabricate WWN",
3157 		    __func__);
3158 
3159 		adr = (uint64_t)gethrtime();
3160 	}
3161 
3162 	adr <<= 8;
3163 	adr |= ((uint64_t)ddi_get_instance(pwp->dip) << 52);
3164 	adr |= (5ULL << 60);
3165 
3166 	for (i = 0; i < PMCS_MAX_PORTS; i++) {
3167 		pwp->sas_wwns[i] = adr + i;
3168 	}
3169 
3170 	return (B_TRUE);
3171 }
3172