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