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