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