xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c (revision af68568220d139fee6e01579437e660dbfee20a8)
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 
26 /*
27  * This file contains various support routines.
28  */
29 
30 #include <sys/scsi/adapters/pmcs/pmcs.h>
31 
32 /*
33  * Local static data
34  */
35 static int tgtmap_usec = MICROSEC;
36 
37 /*
38  * SAS Topology Configuration
39  */
40 static void pmcs_new_tport(pmcs_hw_t *, pmcs_phy_t *);
41 static void pmcs_configure_expander(pmcs_hw_t *, pmcs_phy_t *, pmcs_iport_t *);
42 
43 static boolean_t pmcs_check_expanders(pmcs_hw_t *, pmcs_phy_t *);
44 static void pmcs_check_expander(pmcs_hw_t *, pmcs_phy_t *);
45 static void pmcs_clear_expander(pmcs_hw_t *, pmcs_phy_t *, int);
46 
47 static int pmcs_expander_get_nphy(pmcs_hw_t *, pmcs_phy_t *);
48 static int pmcs_expander_content_discover(pmcs_hw_t *, pmcs_phy_t *,
49     pmcs_phy_t *);
50 
51 static int pmcs_smp_function_result(pmcs_hw_t *, smp_response_frame_t *);
52 static boolean_t pmcs_validate_devid(pmcs_phy_t *, pmcs_phy_t *, uint32_t);
53 static void pmcs_clear_phys(pmcs_hw_t *, pmcs_phy_t *);
54 static int pmcs_configure_new_devices(pmcs_hw_t *, pmcs_phy_t *);
55 static boolean_t pmcs_report_observations(pmcs_hw_t *);
56 static boolean_t pmcs_report_iport_observations(pmcs_hw_t *, pmcs_iport_t *,
57     pmcs_phy_t *);
58 static pmcs_phy_t *pmcs_find_phy_needing_work(pmcs_hw_t *, pmcs_phy_t *);
59 static int pmcs_kill_devices(pmcs_hw_t *, pmcs_phy_t *);
60 static void pmcs_lock_phy_impl(pmcs_phy_t *, int);
61 static void pmcs_unlock_phy_impl(pmcs_phy_t *, int);
62 static pmcs_phy_t *pmcs_clone_phy(pmcs_phy_t *);
63 static boolean_t pmcs_configure_phy(pmcs_hw_t *, pmcs_phy_t *);
64 static void pmcs_reap_dead_phy(pmcs_phy_t *);
65 static pmcs_iport_t *pmcs_get_iport_by_ua(pmcs_hw_t *, char *);
66 static boolean_t pmcs_phy_target_match(pmcs_phy_t *);
67 static void pmcs_handle_ds_recovery_error(pmcs_phy_t *phyp,
68     pmcs_xscsi_t *tgt, pmcs_hw_t *pwp, const char *func_name, int line,
69     char *reason_string);
70 
71 /*
72  * Often used strings
73  */
74 const char pmcs_nowrk[] = "%s: unable to get work structure";
75 const char pmcs_nomsg[] = "%s: unable to get Inbound Message entry";
76 const char pmcs_timeo[] = "!%s: command timed out";
77 
78 extern const ddi_dma_attr_t pmcs_dattr;
79 
80 /*
81  * Some Initial setup steps.
82  */
83 
84 int
85 pmcs_setup(pmcs_hw_t *pwp)
86 {
87 	uint32_t barval = pwp->mpibar;
88 	uint32_t i, scratch, regbar, regoff, barbar, baroff;
89 	uint32_t new_ioq_depth, ferr = 0;
90 
91 	/*
92 	 * Check current state. If we're not at READY state,
93 	 * we can't go further.
94 	 */
95 	scratch = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
96 	if ((scratch & PMCS_MSGU_AAP_STATE_MASK) == PMCS_MSGU_AAP_STATE_ERROR) {
97 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
98 		    "%s: AAP Error State (0x%x)",
99 		    __func__, pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
100 		    PMCS_MSGU_AAP_ERROR_MASK);
101 		pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
102 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
103 		return (-1);
104 	}
105 	if ((scratch & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
106 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
107 		    "%s: AAP unit not ready (state 0x%x)",
108 		    __func__, scratch & PMCS_MSGU_AAP_STATE_MASK);
109 		pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
110 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
111 		return (-1);
112 	}
113 
114 	/*
115 	 * Read the offset from the Message Unit scratchpad 0 register.
116 	 * This allows us to read the MPI Configuration table.
117 	 *
118 	 * Check its signature for validity.
119 	 */
120 	baroff = barval;
121 	barbar = barval >> PMCS_MSGU_MPI_BAR_SHIFT;
122 	baroff &= PMCS_MSGU_MPI_OFFSET_MASK;
123 
124 	regoff = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0);
125 	regbar = regoff >> PMCS_MSGU_MPI_BAR_SHIFT;
126 	regoff &= PMCS_MSGU_MPI_OFFSET_MASK;
127 
128 	if (regoff > baroff) {
129 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
130 		    "%s: bad MPI Table Length (register offset=0x%08x, "
131 		    "passed offset=0x%08x)", __func__, regoff, baroff);
132 		return (-1);
133 	}
134 	if (regbar != barbar) {
135 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
136 		    "%s: bad MPI BAR (register BAROFF=0x%08x, "
137 		    "passed BAROFF=0x%08x)", __func__, regbar, barbar);
138 		return (-1);
139 	}
140 	pwp->mpi_offset = regoff;
141 	if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS) != PMCS_SIGNATURE) {
142 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
143 		    "%s: Bad MPI Configuration Table Signature 0x%x", __func__,
144 		    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
145 		return (-1);
146 	}
147 
148 	if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR) != PMCS_MPI_REVISION1) {
149 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
150 		    "%s: Bad MPI Configuration Revision 0x%x", __func__,
151 		    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR));
152 		return (-1);
153 	}
154 
155 	/*
156 	 * Generate offsets for the General System, Inbound Queue Configuration
157 	 * and Outbound Queue configuration tables. This way the macros to
158 	 * access those tables will work correctly.
159 	 */
160 	pwp->mpi_gst_offset =
161 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO);
162 	pwp->mpi_iqc_offset =
163 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO);
164 	pwp->mpi_oqc_offset =
165 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO);
166 
167 	pwp->fw = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FW);
168 
169 	pwp->max_cmd = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO);
170 	pwp->max_dev = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0) >> 16;
171 
172 	pwp->max_iq = PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
173 	pwp->max_oq = PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
174 	pwp->nphy = PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
175 	if (pwp->max_iq <= PMCS_NIQ) {
176 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
177 		    "%s: not enough Inbound Queues supported "
178 		    "(need %d, max_oq=%d)", __func__, pwp->max_iq, PMCS_NIQ);
179 		return (-1);
180 	}
181 	if (pwp->max_oq <= PMCS_NOQ) {
182 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
183 		    "%s: not enough Outbound Queues supported "
184 		    "(need %d, max_oq=%d)", __func__, pwp->max_oq, PMCS_NOQ);
185 		return (-1);
186 	}
187 	if (pwp->nphy == 0) {
188 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
189 		    "%s: zero phys reported", __func__);
190 		return (-1);
191 	}
192 	if (PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))) {
193 		pwp->hipri_queue = (1 << PMCS_IQ_OTHER);
194 	}
195 
196 
197 	for (i = 0; i < pwp->nphy; i++) {
198 		PMCS_MPI_EVQSET(pwp, PMCS_OQ_EVENTS, i);
199 		PMCS_MPI_NCQSET(pwp, PMCS_OQ_EVENTS, i);
200 	}
201 
202 	pmcs_wr_mpi_tbl(pwp, PMCS_MPI_INFO2,
203 	    (PMCS_OQ_EVENTS << GENERAL_EVENT_OQ_SHIFT) |
204 	    (PMCS_OQ_EVENTS << DEVICE_HANDLE_REMOVED_SHIFT));
205 
206 	/*
207 	 * Verify that ioq_depth is valid (> 0 and not so high that it
208 	 * would cause us to overrun the chip with commands).
209 	 */
210 	if (pwp->ioq_depth == 0) {
211 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
212 		    "%s: I/O queue depth set to 0. Setting to %d",
213 		    __func__, PMCS_NQENTRY);
214 		pwp->ioq_depth = PMCS_NQENTRY;
215 	}
216 
217 	if (pwp->ioq_depth < PMCS_MIN_NQENTRY) {
218 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
219 		    "%s: I/O queue depth set too low (%d). Setting to %d",
220 		    __func__, pwp->ioq_depth, PMCS_MIN_NQENTRY);
221 		pwp->ioq_depth = PMCS_MIN_NQENTRY;
222 	}
223 
224 	if (pwp->ioq_depth > (pwp->max_cmd / (PMCS_IO_IQ_MASK + 1))) {
225 		new_ioq_depth = pwp->max_cmd / (PMCS_IO_IQ_MASK + 1);
226 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
227 		    "%s: I/O queue depth set too high (%d). Setting to %d",
228 		    __func__, pwp->ioq_depth, new_ioq_depth);
229 		pwp->ioq_depth = new_ioq_depth;
230 	}
231 
232 	/*
233 	 * Allocate consistent memory for OQs and IQs.
234 	 */
235 	pwp->iqp_dma_attr = pwp->oqp_dma_attr = pmcs_dattr;
236 	pwp->iqp_dma_attr.dma_attr_align =
237 	    pwp->oqp_dma_attr.dma_attr_align = PMCS_QENTRY_SIZE;
238 
239 	/*
240 	 * The Rev C chip has the ability to do PIO to or from consistent
241 	 * memory anywhere in a 64 bit address space, but the firmware is
242 	 * not presently set up to do so.
243 	 */
244 	pwp->iqp_dma_attr.dma_attr_addr_hi =
245 	    pwp->oqp_dma_attr.dma_attr_addr_hi = 0x000000FFFFFFFFFFull;
246 
247 	for (i = 0; i < PMCS_NIQ; i++) {
248 		if (pmcs_dma_setup(pwp, &pwp->iqp_dma_attr,
249 		    &pwp->iqp_acchdls[i],
250 		    &pwp->iqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
251 		    (caddr_t *)&pwp->iqp[i], &pwp->iqaddr[i]) == B_FALSE) {
252 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
253 			    "Failed to setup DMA for iqp[%d]", i);
254 			return (-1);
255 		}
256 		bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
257 	}
258 
259 	for (i = 0; i < PMCS_NOQ; i++) {
260 		if (pmcs_dma_setup(pwp, &pwp->oqp_dma_attr,
261 		    &pwp->oqp_acchdls[i],
262 		    &pwp->oqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
263 		    (caddr_t *)&pwp->oqp[i], &pwp->oqaddr[i]) == B_FALSE) {
264 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
265 			    "Failed to setup DMA for oqp[%d]", i);
266 			return (-1);
267 		}
268 		bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
269 	}
270 
271 	/*
272 	 * Install the IQ and OQ addresses (and null out the rest).
273 	 */
274 	for (i = 0; i < pwp->max_iq; i++) {
275 		pwp->iqpi_offset[i] = pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i));
276 		if (i < PMCS_NIQ) {
277 			if (i != PMCS_IQ_OTHER) {
278 				pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
279 				    pwp->ioq_depth | (PMCS_QENTRY_SIZE << 16));
280 			} else {
281 				pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
282 				    (1 << 30) | pwp->ioq_depth |
283 				    (PMCS_QENTRY_SIZE << 16));
284 			}
285 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i),
286 			    DWORD1(pwp->iqaddr[i]));
287 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i),
288 			    DWORD0(pwp->iqaddr[i]));
289 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i),
290 			    DWORD1(pwp->ciaddr+IQ_OFFSET(i)));
291 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i),
292 			    DWORD0(pwp->ciaddr+IQ_OFFSET(i)));
293 		} else {
294 			pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
295 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
296 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
297 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
298 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
299 		}
300 	}
301 
302 	for (i = 0; i < pwp->max_oq; i++) {
303 		pwp->oqci_offset[i] = pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i));
304 		if (i < PMCS_NOQ) {
305 			pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), pwp->ioq_depth |
306 			    (PMCS_QENTRY_SIZE << 16) | OQIEX);
307 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i),
308 			    DWORD1(pwp->oqaddr[i]));
309 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i),
310 			    DWORD0(pwp->oqaddr[i]));
311 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i),
312 			    DWORD1(pwp->ciaddr+OQ_OFFSET(i)));
313 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i),
314 			    DWORD0(pwp->ciaddr+OQ_OFFSET(i)));
315 			pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i),
316 			    pwp->oqvec[i] << 24);
317 			pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
318 		} else {
319 			pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
320 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
321 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
322 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
323 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
324 			pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
325 			pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
326 		}
327 	}
328 
329 	/*
330 	 * Set up logging, if defined.
331 	 */
332 	if (pwp->fwlog) {
333 		uint64_t logdma = pwp->fwaddr;
334 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAH, DWORD1(logdma));
335 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAL, DWORD0(logdma));
336 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBS, PMCS_FWLOG_SIZE >> 1);
337 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELSEV, pwp->fwlog);
338 		logdma += (PMCS_FWLOG_SIZE >> 1);
339 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAH, DWORD1(logdma));
340 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAL, DWORD0(logdma));
341 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBS, PMCS_FWLOG_SIZE >> 1);
342 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELSEV, pwp->fwlog);
343 	}
344 
345 	/*
346 	 * Interrupt vectors, outbound queues, and odb_auto_clear
347 	 *
348 	 * MSI/MSI-X:
349 	 * If we got 4 interrupt vectors, we'll assign one to each outbound
350 	 * queue as well as the fatal interrupt, and auto clear can be set
351 	 * for each.
352 	 *
353 	 * If we only got 2 vectors, one will be used for I/O completions
354 	 * and the other for the other two vectors.  In this case, auto_
355 	 * clear can only be set for I/Os, which is fine.  The fatal
356 	 * interrupt will be mapped to the PMCS_FATAL_INTERRUPT bit, which
357 	 * is not an interrupt vector.
358 	 *
359 	 * MSI/MSI-X/INT-X:
360 	 * If we only got 1 interrupt vector, auto_clear must be set to 0,
361 	 * and again the fatal interrupt will be mapped to the
362 	 * PMCS_FATAL_INTERRUPT bit (again, not an interrupt vector).
363 	 */
364 
365 	switch (pwp->int_type) {
366 	case PMCS_INT_MSIX:
367 	case PMCS_INT_MSI:
368 		switch (pwp->intr_cnt) {
369 		case 1:
370 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
371 			    (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
372 			pwp->odb_auto_clear = 0;
373 			break;
374 		case 2:
375 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
376 			    (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
377 			pwp->odb_auto_clear = (1 << PMCS_FATAL_INTERRUPT) |
378 			    (1 << PMCS_MSIX_IODONE);
379 			break;
380 		case 4:
381 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
382 			    (PMCS_MSIX_FATAL << PMCS_FERIV_SHIFT));
383 			pwp->odb_auto_clear = (1 << PMCS_MSIX_FATAL) |
384 			    (1 << PMCS_MSIX_GENERAL) | (1 << PMCS_MSIX_IODONE) |
385 			    (1 << PMCS_MSIX_EVENTS);
386 			break;
387 		}
388 		break;
389 
390 	case PMCS_INT_FIXED:
391 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR,
392 		    PMCS_FERRIE | (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
393 		pwp->odb_auto_clear = 0;
394 		break;
395 	}
396 
397 	/*
398 	 * Enable Interrupt Reassertion
399 	 * Default Delay 1000us
400 	 */
401 	ferr = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR);
402 	if ((ferr & PMCS_MPI_IRAE) == 0) {
403 		ferr &= ~(PMCS_MPI_IRAU | PMCS_MPI_IRAD_MASK);
404 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, ferr | PMCS_MPI_IRAE);
405 	}
406 
407 	pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR, pwp->odb_auto_clear);
408 	pwp->mpi_table_setup = 1;
409 	return (0);
410 }
411 
412 /*
413  * Start the Message Passing protocol with the PMC chip.
414  */
415 int
416 pmcs_start_mpi(pmcs_hw_t *pwp)
417 {
418 	int i;
419 
420 	pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPIINI);
421 	for (i = 0; i < 1000; i++) {
422 		if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
423 		    PMCS_MSGU_IBDB_MPIINI) == 0) {
424 			break;
425 		}
426 		drv_usecwait(1000);
427 	}
428 	if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPIINI) {
429 		return (-1);
430 	}
431 	drv_usecwait(500000);
432 
433 	/*
434 	 * Check to make sure we got to INIT state.
435 	 */
436 	if (PMCS_MPI_S(pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE)) !=
437 	    PMCS_MPI_STATE_INIT) {
438 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
439 		    "%s: MPI launch failed (GST 0x%x DBCLR 0x%x)", __func__,
440 		    pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE),
441 		    pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
442 		return (-1);
443 	}
444 	return (0);
445 }
446 
447 /*
448  * Stop the Message Passing protocol with the PMC chip.
449  */
450 int
451 pmcs_stop_mpi(pmcs_hw_t *pwp)
452 {
453 	int i;
454 
455 	for (i = 0; i < pwp->max_iq; i++) {
456 		pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
457 		pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
458 		pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
459 		pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
460 		pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
461 	}
462 	for (i = 0; i < pwp->max_oq; i++) {
463 		pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
464 		pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
465 		pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
466 		pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
467 		pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
468 		pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
469 		pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
470 	}
471 	pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, 0);
472 	pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPICTU);
473 	for (i = 0; i < 2000; i++) {
474 		if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
475 		    PMCS_MSGU_IBDB_MPICTU) == 0) {
476 			break;
477 		}
478 		drv_usecwait(1000);
479 	}
480 	if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPICTU) {
481 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
482 		    "%s: MPI stop failed", __func__);
483 		return (-1);
484 	}
485 	return (0);
486 }
487 
488 /*
489  * Do a sequence of ECHO messages to test for MPI functionality,
490  * all inbound and outbound queue functionality and interrupts.
491  */
492 int
493 pmcs_echo_test(pmcs_hw_t *pwp)
494 {
495 	echo_test_t fred;
496 	struct pmcwork *pwrk;
497 	uint32_t *msg, count;
498 	int iqe = 0, iqo = 0, result, rval = 0;
499 	int iterations;
500 	hrtime_t echo_start, echo_end, echo_total;
501 
502 	ASSERT(pwp->max_cmd > 0);
503 
504 	/*
505 	 * We want iterations to be max_cmd * 3 to ensure that we run the
506 	 * echo test enough times to iterate through every inbound queue
507 	 * at least twice.
508 	 */
509 	iterations = pwp->max_cmd * 3;
510 
511 	echo_total = 0;
512 	count = 0;
513 
514 	while (count < iterations) {
515 		pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
516 		if (pwrk == NULL) {
517 			pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
518 			    pmcs_nowrk, __func__);
519 			rval = -1;
520 			break;
521 		}
522 
523 		mutex_enter(&pwp->iqp_lock[iqe]);
524 		msg = GET_IQ_ENTRY(pwp, iqe);
525 		if (msg == NULL) {
526 			mutex_exit(&pwp->iqp_lock[iqe]);
527 			pmcs_pwork(pwp, pwrk);
528 			pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
529 			    pmcs_nomsg, __func__);
530 			rval = -1;
531 			break;
532 		}
533 
534 		bzero(msg, PMCS_QENTRY_SIZE);
535 
536 		if (iqe == PMCS_IQ_OTHER) {
537 			/* This is on the high priority queue */
538 			msg[0] = LE_32(PMCS_HIPRI(pwp, iqo, PMCIN_ECHO));
539 		} else {
540 			msg[0] = LE_32(PMCS_IOMB_IN_SAS(iqo, PMCIN_ECHO));
541 		}
542 		msg[1] = LE_32(pwrk->htag);
543 		fred.signature = 0xdeadbeef;
544 		fred.count = count;
545 		fred.ptr = &count;
546 		(void) memcpy(&msg[2], &fred, sizeof (fred));
547 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
548 
549 		INC_IQ_ENTRY(pwp, iqe);
550 
551 		echo_start = gethrtime();
552 		DTRACE_PROBE2(pmcs__echo__test__wait__start,
553 		    hrtime_t, echo_start, uint32_t, pwrk->htag);
554 
555 		if (++iqe == PMCS_NIQ) {
556 			iqe = 0;
557 		}
558 		if (++iqo == PMCS_NOQ) {
559 			iqo = 0;
560 		}
561 
562 		WAIT_FOR(pwrk, 250, result);
563 
564 		echo_end = gethrtime();
565 		DTRACE_PROBE2(pmcs__echo__test__wait__end,
566 		    hrtime_t, echo_end, int, result);
567 
568 		echo_total += (echo_end - echo_start);
569 
570 		pmcs_pwork(pwp, pwrk);
571 		if (result) {
572 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
573 			    "%s: command timed out on echo test #%d",
574 			    __func__, count);
575 			rval = -1;
576 			break;
577 		}
578 	}
579 
580 	/*
581 	 * The intr_threshold is adjusted by PMCS_INTR_THRESHOLD in order to
582 	 * remove the overhead of things like the delay in getting signaled
583 	 * for completion.
584 	 */
585 	if (echo_total != 0) {
586 		pwp->io_intr_coal.intr_latency =
587 		    (echo_total / iterations) / 2;
588 		pwp->io_intr_coal.intr_threshold =
589 		    PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
590 		    pwp->io_intr_coal.intr_latency);
591 	}
592 
593 	return (rval);
594 }
595 
596 /*
597  * Start the (real) phys
598  */
599 int
600 pmcs_start_phy(pmcs_hw_t *pwp, int phynum, int linkmode, int speed)
601 {
602 	int result;
603 	uint32_t *msg;
604 	struct pmcwork *pwrk;
605 	pmcs_phy_t *pptr;
606 	sas_identify_af_t sap;
607 
608 	mutex_enter(&pwp->lock);
609 	pptr = pwp->root_phys + phynum;
610 	if (pptr == NULL) {
611 		mutex_exit(&pwp->lock);
612 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
613 		    "%s: cannot find port %d", __func__, phynum);
614 		return (0);
615 	}
616 
617 	pmcs_lock_phy(pptr);
618 	mutex_exit(&pwp->lock);
619 
620 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
621 	if (pwrk == NULL) {
622 		pmcs_unlock_phy(pptr);
623 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
624 		return (-1);
625 	}
626 
627 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
628 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
629 
630 	if (msg == NULL) {
631 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
632 		pmcs_unlock_phy(pptr);
633 		pmcs_pwork(pwp, pwrk);
634 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
635 		return (-1);
636 	}
637 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_START));
638 	msg[1] = LE_32(pwrk->htag);
639 	msg[2] = LE_32(linkmode | speed | phynum);
640 	bzero(&sap, sizeof (sap));
641 	sap.device_type = SAS_IF_DTYPE_ENDPOINT;
642 	sap.ssp_ini_port = 1;
643 
644 	if (pwp->separate_ports) {
645 		pmcs_wwn2barray(pwp->sas_wwns[phynum], sap.sas_address);
646 	} else {
647 		pmcs_wwn2barray(pwp->sas_wwns[0], sap.sas_address);
648 	}
649 
650 	ASSERT(phynum < SAS2_PHYNUM_MAX);
651 	sap.phy_identifier = phynum & SAS2_PHYNUM_MASK;
652 	(void) memcpy(&msg[3], &sap, sizeof (sas_identify_af_t));
653 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
654 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
655 
656 	pptr->state.prog_min_rate = (lowbit((ulong_t)speed) - 1);
657 	pptr->state.prog_max_rate = (highbit((ulong_t)speed) - 1);
658 	pptr->state.hw_min_rate = PMCS_HW_MIN_LINK_RATE;
659 	pptr->state.hw_max_rate = PMCS_HW_MAX_LINK_RATE;
660 
661 	pmcs_unlock_phy(pptr);
662 	WAIT_FOR(pwrk, 1000, result);
663 	pmcs_pwork(pwp, pwrk);
664 
665 	if (result) {
666 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_timeo, __func__);
667 	} else {
668 		mutex_enter(&pwp->lock);
669 		pwp->phys_started |= (1 << phynum);
670 		mutex_exit(&pwp->lock);
671 	}
672 
673 	return (0);
674 }
675 
676 int
677 pmcs_start_phys(pmcs_hw_t *pwp)
678 {
679 	int i;
680 
681 	for (i = 0; i < pwp->nphy; i++) {
682 		if ((pwp->phyid_block_mask & (1 << i)) == 0) {
683 			if (pmcs_start_phy(pwp, i,
684 			    (pwp->phymode << PHY_MODE_SHIFT),
685 			    pwp->physpeed << PHY_LINK_SHIFT)) {
686 				return (-1);
687 			}
688 			if (pmcs_clear_diag_counters(pwp, i)) {
689 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
690 				    "%s: failed to reset counters on PHY (%d)",
691 				    __func__, i);
692 			}
693 		}
694 	}
695 	return (0);
696 }
697 
698 /*
699  * Called with PHY locked
700  */
701 int
702 pmcs_reset_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t type)
703 {
704 	uint32_t *msg;
705 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
706 	const char *mbar;
707 	uint32_t amt;
708 	uint32_t pdevid;
709 	uint32_t stsoff;
710 	uint32_t status;
711 	int result, level, phynum;
712 	struct pmcwork *pwrk;
713 	uint32_t htag;
714 
715 	ASSERT(mutex_owned(&pptr->phy_lock));
716 
717 	bzero(iomb, PMCS_QENTRY_SIZE);
718 	phynum = pptr->phynum;
719 	level = pptr->level;
720 	if (level > 0) {
721 		pdevid = pptr->parent->device_id;
722 	}
723 
724 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
725 
726 	if (pwrk == NULL) {
727 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
728 		return (ENOMEM);
729 	}
730 
731 	pwrk->arg = iomb;
732 
733 	/*
734 	 * If level > 0, we need to issue an SMP_REQUEST with a PHY_CONTROL
735 	 * function to do either a link reset or hard reset.  If level == 0,
736 	 * then we do a LOCAL_PHY_CONTROL IOMB to do link/hard reset to the
737 	 * root (local) PHY
738 	 */
739 	if (level) {
740 		stsoff = 2;
741 		iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
742 		    PMCIN_SMP_REQUEST));
743 		iomb[1] = LE_32(pwrk->htag);
744 		iomb[2] = LE_32(pdevid);
745 		iomb[3] = LE_32(40 << SMP_REQUEST_LENGTH_SHIFT);
746 		/*
747 		 * Send SMP PHY CONTROL/HARD or LINK RESET
748 		 */
749 		iomb[4] = BE_32(0x40910000);
750 		iomb[5] = 0;
751 
752 		if (type == PMCS_PHYOP_HARD_RESET) {
753 			mbar = "SMP PHY CONTROL/HARD RESET";
754 			iomb[6] = BE_32((phynum << 24) |
755 			    (PMCS_PHYOP_HARD_RESET << 16));
756 		} else {
757 			mbar = "SMP PHY CONTROL/LINK RESET";
758 			iomb[6] = BE_32((phynum << 24) |
759 			    (PMCS_PHYOP_LINK_RESET << 16));
760 		}
761 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
762 		    "%s: sending %s to %s for phy 0x%x",
763 		    __func__, mbar, pptr->parent->path, pptr->phynum);
764 		amt = 7;
765 	} else {
766 		/*
767 		 * Unlike most other Outbound messages, status for
768 		 * a local phy operation is in DWORD 3.
769 		 */
770 		stsoff = 3;
771 		iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
772 		    PMCIN_LOCAL_PHY_CONTROL));
773 		iomb[1] = LE_32(pwrk->htag);
774 		if (type == PMCS_PHYOP_LINK_RESET) {
775 			mbar = "LOCAL PHY LINK RESET";
776 			iomb[2] = LE_32((PMCS_PHYOP_LINK_RESET << 8) | phynum);
777 		} else {
778 			mbar = "LOCAL PHY HARD RESET";
779 			iomb[2] = LE_32((PMCS_PHYOP_HARD_RESET << 8) | phynum);
780 		}
781 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
782 		    "%s: sending %s to %s", __func__, mbar, pptr->path);
783 		amt = 3;
784 	}
785 
786 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
787 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
788 	if (msg == NULL) {
789 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
790 		pmcs_pwork(pwp, pwrk);
791 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
792 		return (ENOMEM);
793 	}
794 	COPY_MESSAGE(msg, iomb, amt);
795 	htag = pwrk->htag;
796 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
797 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
798 
799 	pmcs_unlock_phy(pptr);
800 	WAIT_FOR(pwrk, 1000, result);
801 	pmcs_pwork(pwp, pwrk);
802 	pmcs_lock_phy(pptr);
803 
804 	if (result) {
805 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_timeo, __func__);
806 
807 		if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
808 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
809 			    "%s: Unable to issue SMP abort for htag 0x%08x",
810 			    __func__, htag);
811 		} else {
812 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
813 			    "%s: Issuing SMP ABORT for htag 0x%08x",
814 			    __func__, htag);
815 		}
816 		return (EIO);
817 	}
818 	status = LE_32(iomb[stsoff]);
819 
820 	if (status != PMCOUT_STATUS_OK) {
821 		char buf[32];
822 		const char *es =  pmcs_status_str(status);
823 		if (es == NULL) {
824 			(void) snprintf(buf, sizeof (buf), "Status 0x%x",
825 			    status);
826 			es = buf;
827 		}
828 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
829 		    "%s: %s action returned %s for %s", __func__, mbar, es,
830 		    pptr->path);
831 		return (EIO);
832 	}
833 
834 	return (0);
835 }
836 
837 /*
838  * Stop the (real) phys.  No PHY or softstate locks are required as this only
839  * happens during detach.
840  */
841 void
842 pmcs_stop_phy(pmcs_hw_t *pwp, int phynum)
843 {
844 	int result;
845 	pmcs_phy_t *pptr;
846 	uint32_t *msg;
847 	struct pmcwork *pwrk;
848 
849 	pptr =  pwp->root_phys + phynum;
850 	if (pptr == NULL) {
851 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
852 		    "%s: unable to find port %d", __func__, phynum);
853 		return;
854 	}
855 
856 	if (pwp->phys_started & (1 << phynum)) {
857 		pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
858 
859 		if (pwrk == NULL) {
860 			pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL,
861 			    pmcs_nowrk, __func__);
862 			return;
863 		}
864 
865 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
866 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
867 
868 		if (msg == NULL) {
869 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
870 			pmcs_pwork(pwp, pwrk);
871 			pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL,
872 			    pmcs_nomsg, __func__);
873 			return;
874 		}
875 
876 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_STOP));
877 		msg[1] = LE_32(pwrk->htag);
878 		msg[2] = LE_32(phynum);
879 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
880 		/*
881 		 * Make this unconfigured now.
882 		 */
883 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
884 		WAIT_FOR(pwrk, 1000, result);
885 
886 		pmcs_pwork(pwp, pwrk);
887 		if (result) {
888 			pmcs_prt(pwp, PMCS_PRT_ERR,
889 			    pptr, NULL, pmcs_timeo, __func__);
890 		}
891 
892 		pwp->phys_started &= ~(1 << phynum);
893 	}
894 
895 	pptr->configured = 0;
896 }
897 
898 /*
899  * No locks should be required as this is only called during detach
900  */
901 void
902 pmcs_stop_phys(pmcs_hw_t *pwp)
903 {
904 	int i;
905 	for (i = 0; i < pwp->nphy; i++) {
906 		if ((pwp->phyid_block_mask & (1 << i)) == 0) {
907 			pmcs_stop_phy(pwp, i);
908 		}
909 	}
910 }
911 
912 /*
913  * Run SAS_DIAG_EXECUTE with cmd and cmd_desc passed.
914  * 	ERR_CNT_RESET: return status of cmd
915  *	DIAG_REPORT_GET: return value of the counter
916  */
917 int
918 pmcs_sas_diag_execute(pmcs_hw_t *pwp, uint32_t cmd, uint32_t cmd_desc,
919     uint8_t phynum)
920 {
921 	uint32_t htag, *ptr, status, msg[PMCS_MSG_SIZE << 1];
922 	int result;
923 	struct pmcwork *pwrk;
924 
925 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
926 	if (pwrk == NULL) {
927 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nowrk, __func__);
928 		return (DDI_FAILURE);
929 	}
930 	pwrk->arg = msg;
931 	htag = pwrk->htag;
932 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_SAS_DIAG_EXECUTE));
933 	msg[1] = LE_32(htag);
934 	msg[2] = LE_32((cmd << PMCS_DIAG_CMD_SHIFT) |
935 	    (cmd_desc << PMCS_DIAG_CMD_DESC_SHIFT) | phynum);
936 
937 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
938 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
939 	if (ptr == NULL) {
940 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
941 		pmcs_pwork(pwp, pwrk);
942 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nomsg, __func__);
943 		return (DDI_FAILURE);
944 	}
945 	COPY_MESSAGE(ptr, msg, 3);
946 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
947 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
948 
949 	WAIT_FOR(pwrk, 1000, result);
950 
951 	pmcs_pwork(pwp, pwrk);
952 
953 	if (result) {
954 		pmcs_timed_out(pwp, htag, __func__);
955 		return (DDI_FAILURE);
956 	}
957 
958 	status = LE_32(msg[3]);
959 
960 	/* Return for counter reset */
961 	if (cmd == PMCS_ERR_CNT_RESET)
962 		return (status);
963 
964 	/* Return for counter value */
965 	if (status) {
966 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
967 		    "%s: failed, status (0x%x)", __func__, status);
968 		return (DDI_FAILURE);
969 	}
970 	return (LE_32(msg[4]));
971 }
972 
973 /* Get the current value of the counter for desc on phynum and return it. */
974 int
975 pmcs_get_diag_report(pmcs_hw_t *pwp, uint32_t desc, uint8_t phynum)
976 {
977 	return (pmcs_sas_diag_execute(pwp, PMCS_DIAG_REPORT_GET, desc, phynum));
978 }
979 
980 /* Clear all of the counters for phynum. Returns the status of the command. */
981 int
982 pmcs_clear_diag_counters(pmcs_hw_t *pwp, uint8_t phynum)
983 {
984 	uint32_t	cmd = PMCS_ERR_CNT_RESET;
985 	uint32_t	cmd_desc;
986 
987 	cmd_desc = PMCS_INVALID_DWORD_CNT;
988 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
989 		return (DDI_FAILURE);
990 
991 	cmd_desc = PMCS_DISPARITY_ERR_CNT;
992 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
993 		return (DDI_FAILURE);
994 
995 	cmd_desc = PMCS_LOST_DWORD_SYNC_CNT;
996 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
997 		return (DDI_FAILURE);
998 
999 	cmd_desc = PMCS_RESET_FAILED_CNT;
1000 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
1001 		return (DDI_FAILURE);
1002 
1003 	return (DDI_SUCCESS);
1004 }
1005 
1006 /*
1007  * Get firmware timestamp
1008  */
1009 int
1010 pmcs_get_time_stamp(pmcs_hw_t *pwp, uint64_t *ts)
1011 {
1012 	uint32_t htag, *ptr, msg[PMCS_MSG_SIZE << 1];
1013 	int result;
1014 	struct pmcwork *pwrk;
1015 
1016 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
1017 	if (pwrk == NULL) {
1018 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nowrk, __func__);
1019 		return (-1);
1020 	}
1021 	pwrk->arg = msg;
1022 	htag = pwrk->htag;
1023 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_GET_TIME_STAMP));
1024 	msg[1] = LE_32(pwrk->htag);
1025 
1026 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1027 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1028 	if (ptr == NULL) {
1029 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1030 		pmcs_pwork(pwp, pwrk);
1031 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nomsg, __func__);
1032 		return (-1);
1033 	}
1034 	COPY_MESSAGE(ptr, msg, 2);
1035 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1036 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1037 
1038 	WAIT_FOR(pwrk, 1000, result);
1039 
1040 	pmcs_pwork(pwp, pwrk);
1041 
1042 	if (result) {
1043 		pmcs_timed_out(pwp, htag, __func__);
1044 		return (-1);
1045 	}
1046 	*ts = LE_32(msg[2]) | (((uint64_t)LE_32(msg[3])) << 32);
1047 	return (0);
1048 }
1049 
1050 /*
1051  * Dump all pertinent registers
1052  */
1053 
1054 void
1055 pmcs_register_dump(pmcs_hw_t *pwp)
1056 {
1057 	int i;
1058 	uint32_t val;
1059 
1060 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "pmcs%d: Register dump start",
1061 	    ddi_get_instance(pwp->dip));
1062 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1063 	    "OBDB (intr): 0x%08x (mask): 0x%08x (clear): 0x%08x",
1064 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB),
1065 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK),
1066 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
1067 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH0: 0x%08x",
1068 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
1069 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH1: 0x%08x",
1070 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
1071 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH2: 0x%08x",
1072 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
1073 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH3: 0x%08x",
1074 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
1075 	for (i = 0; i < PMCS_NIQ; i++) {
1076 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "IQ %d: CI %u PI %u",
1077 		    i, pmcs_rd_iqci(pwp, i), pmcs_rd_iqpi(pwp, i));
1078 	}
1079 	for (i = 0; i < PMCS_NOQ; i++) {
1080 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "OQ %d: CI %u PI %u",
1081 		    i, pmcs_rd_oqci(pwp, i), pmcs_rd_oqpi(pwp, i));
1082 	}
1083 	val = pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE);
1084 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1085 	    "GST TABLE BASE: 0x%08x (STATE=0x%x QF=%d GSTLEN=%d HMI_ERR=0x%x)",
1086 	    val, PMCS_MPI_S(val), PMCS_QF(val), PMCS_GSTLEN(val) * 4,
1087 	    PMCS_HMI_ERR(val));
1088 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IQFRZ0: 0x%08x",
1089 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
1090 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IQFRZ1: 0x%08x",
1091 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
1092 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE MSGU TICK: 0x%08x",
1093 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
1094 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IOP TICK: 0x%08x",
1095 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
1096 	for (i = 0; i < pwp->nphy; i++) {
1097 		uint32_t rerrf, pinfo, started = 0, link = 0;
1098 		pinfo = pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i));
1099 		if (pinfo & 1) {
1100 			started = 1;
1101 			link = pinfo & 2;
1102 		}
1103 		rerrf = pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i));
1104 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1105 		    "GST TABLE PHY%d STARTED=%d LINK=%d RERR=0x%08x",
1106 		    i, started, link, rerrf);
1107 	}
1108 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "pmcs%d: Register dump end",
1109 	    ddi_get_instance(pwp->dip));
1110 }
1111 
1112 /*
1113  * Handle SATA Abort and other error processing
1114  */
1115 int
1116 pmcs_abort_handler(pmcs_hw_t *pwp)
1117 {
1118 	pmcs_phy_t *pptr, *pnext, *pnext_uplevel[PMCS_MAX_XPND];
1119 	int r, level = 0;
1120 
1121 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s", __func__);
1122 
1123 	mutex_enter(&pwp->lock);
1124 	pptr = pwp->root_phys;
1125 	mutex_exit(&pwp->lock);
1126 
1127 	while (pptr) {
1128 		/*
1129 		 * XXX: Need to make sure this doesn't happen
1130 		 * XXX: when non-NCQ commands are running.
1131 		 */
1132 		pmcs_lock_phy(pptr);
1133 		if (pptr->need_rl_ext) {
1134 			ASSERT(pptr->dtype == SATA);
1135 			if (pmcs_acquire_scratch(pwp, B_FALSE)) {
1136 				goto next_phy;
1137 			}
1138 			r = pmcs_sata_abort_ncq(pwp, pptr);
1139 			pmcs_release_scratch(pwp);
1140 			if (r == ENOMEM) {
1141 				goto next_phy;
1142 			}
1143 			if (r) {
1144 				r = pmcs_reset_phy(pwp, pptr,
1145 				    PMCS_PHYOP_LINK_RESET);
1146 				if (r == ENOMEM) {
1147 					goto next_phy;
1148 				}
1149 				/* what if other failures happened? */
1150 				pptr->abort_pending = 1;
1151 				pptr->abort_sent = 0;
1152 			}
1153 		}
1154 		if (pptr->abort_pending == 0 || pptr->abort_sent) {
1155 			goto next_phy;
1156 		}
1157 		pptr->abort_pending = 0;
1158 		if (pmcs_abort(pwp, pptr, pptr->device_id, 1, 1) == ENOMEM) {
1159 			pptr->abort_pending = 1;
1160 			goto next_phy;
1161 		}
1162 		pptr->abort_sent = 1;
1163 
1164 next_phy:
1165 		if (pptr->children) {
1166 			pnext = pptr->children;
1167 			pnext_uplevel[level++] = pptr->sibling;
1168 		} else {
1169 			pnext = pptr->sibling;
1170 			while ((pnext == NULL) && (level > 0)) {
1171 				pnext = pnext_uplevel[--level];
1172 			}
1173 		}
1174 
1175 		pmcs_unlock_phy(pptr);
1176 		pptr = pnext;
1177 	}
1178 
1179 	return (0);
1180 }
1181 
1182 /*
1183  * Register a device (get a device handle for it).
1184  * Called with PHY lock held.
1185  */
1186 int
1187 pmcs_register_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1188 {
1189 	struct pmcwork *pwrk;
1190 	int result = 0;
1191 	uint32_t *msg;
1192 	uint32_t tmp, status;
1193 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
1194 
1195 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1196 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1197 
1198 	if (msg == NULL ||
1199 	    (pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
1200 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1201 		result = ENOMEM;
1202 		goto out;
1203 	}
1204 
1205 	pwrk->arg = iomb;
1206 	pwrk->dtype = pptr->dtype;
1207 
1208 	msg[1] = LE_32(pwrk->htag);
1209 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_REGISTER_DEVICE));
1210 	tmp = PMCS_DEVREG_TLR |
1211 	    (pptr->link_rate << PMCS_DEVREG_LINK_RATE_SHIFT);
1212 	if (IS_ROOT_PHY(pptr)) {
1213 		msg[2] = LE_32(pptr->portid |
1214 		    (pptr->phynum << PMCS_PHYID_SHIFT));
1215 	} else {
1216 		msg[2] = LE_32(pptr->portid);
1217 	}
1218 	if (pptr->dtype == SATA) {
1219 		if (IS_ROOT_PHY(pptr)) {
1220 			tmp |= PMCS_DEVREG_TYPE_SATA_DIRECT;
1221 		} else {
1222 			tmp |= PMCS_DEVREG_TYPE_SATA;
1223 		}
1224 	} else {
1225 		tmp |= PMCS_DEVREG_TYPE_SAS;
1226 	}
1227 	msg[3] = LE_32(tmp);
1228 	msg[4] = LE_32(PMCS_DEVREG_IT_NEXUS_TIMEOUT);
1229 	(void) memcpy(&msg[5], pptr->sas_address, 8);
1230 
1231 	CLEAN_MESSAGE(msg, 7);
1232 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1233 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1234 
1235 	pmcs_unlock_phy(pptr);
1236 	WAIT_FOR(pwrk, 250, result);
1237 	pmcs_lock_phy(pptr);
1238 	pmcs_pwork(pwp, pwrk);
1239 
1240 	if (result) {
1241 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_timeo, __func__);
1242 		result = ETIMEDOUT;
1243 		goto out;
1244 	}
1245 	status = LE_32(iomb[2]);
1246 	tmp = LE_32(iomb[3]);
1247 	switch (status) {
1248 	case PMCS_DEVREG_OK:
1249 	case PMCS_DEVREG_DEVICE_ALREADY_REGISTERED:
1250 	case PMCS_DEVREG_PHY_ALREADY_REGISTERED:
1251 		if (pmcs_validate_devid(pwp->root_phys, pptr, tmp) == B_FALSE) {
1252 			result = EEXIST;
1253 			goto out;
1254 		} else if (status != PMCS_DEVREG_OK) {
1255 			if (tmp == 0xffffffff) {	/* F/W bug */
1256 				pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
1257 				    "%s: phy %s already has bogus devid 0x%x",
1258 				    __func__, pptr->path, tmp);
1259 				result = EIO;
1260 				goto out;
1261 			} else {
1262 				pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
1263 				    "%s: phy %s already has a device id 0x%x",
1264 				    __func__, pptr->path, tmp);
1265 			}
1266 		}
1267 		break;
1268 	default:
1269 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1270 		    "%s: status 0x%x when trying to register device %s",
1271 		    __func__, status, pptr->path);
1272 		result = EIO;
1273 		goto out;
1274 	}
1275 	pptr->device_id = tmp;
1276 	pptr->valid_device_id = 1;
1277 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "Phy %s/" SAS_ADDR_FMT
1278 	    " registered with device_id 0x%x (portid %d)", pptr->path,
1279 	    SAS_ADDR_PRT(pptr->sas_address), tmp, pptr->portid);
1280 out:
1281 	return (result);
1282 }
1283 
1284 /*
1285  * Deregister a device (remove a device handle).
1286  * Called with PHY locked.
1287  */
1288 void
1289 pmcs_deregister_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1290 {
1291 	struct pmcwork *pwrk;
1292 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
1293 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
1294 	int result;
1295 
1296 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
1297 	if (pwrk == NULL) {
1298 		return;
1299 	}
1300 
1301 	pwrk->arg = iomb;
1302 	pwrk->dtype = pptr->dtype;
1303 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1304 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1305 	if (ptr == NULL) {
1306 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1307 		pmcs_pwork(pwp, pwrk);
1308 		return;
1309 	}
1310 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
1311 	    PMCIN_DEREGISTER_DEVICE_HANDLE));
1312 	msg[1] = LE_32(pwrk->htag);
1313 	msg[2] = LE_32(pptr->device_id);
1314 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1315 	COPY_MESSAGE(ptr, msg, 3);
1316 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1317 
1318 	pmcs_unlock_phy(pptr);
1319 	WAIT_FOR(pwrk, 250, result);
1320 	pmcs_pwork(pwp, pwrk);
1321 	pmcs_lock_phy(pptr);
1322 
1323 	if (result) {
1324 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_timeo, __func__);
1325 		return;
1326 	}
1327 	status = LE_32(iomb[2]);
1328 	if (status != PMCOUT_STATUS_OK) {
1329 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1330 		    "%s: status 0x%x when trying to deregister device %s",
1331 		    __func__, status, pptr->path);
1332 	} else {
1333 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1334 		    "%s: device %s deregistered", __func__, pptr->path);
1335 		pptr->valid_device_id = 0;
1336 		pptr->device_id = PMCS_INVALID_DEVICE_ID;
1337 	}
1338 }
1339 
1340 /*
1341  * Deregister all registered devices.
1342  */
1343 void
1344 pmcs_deregister_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
1345 {
1346 	/*
1347 	 * Start at the maximum level and walk back to level 0.  This only
1348 	 * gets done during detach after all threads and timers have been
1349 	 * destroyed, so there's no need to hold the softstate or PHY lock.
1350 	 */
1351 	while (phyp) {
1352 		if (phyp->children) {
1353 			pmcs_deregister_devices(pwp, phyp->children);
1354 		}
1355 		if (phyp->valid_device_id) {
1356 			pmcs_deregister_device(pwp, phyp);
1357 		}
1358 		phyp = phyp->sibling;
1359 	}
1360 }
1361 
1362 /*
1363  * Perform a 'soft' reset on the PMC chip
1364  */
1365 int
1366 pmcs_soft_reset(pmcs_hw_t *pwp, boolean_t no_restart)
1367 {
1368 	uint32_t s2, sfrbits, gsm, rapchk, wapchk, wdpchk, spc, tsmode;
1369 	pmcs_phy_t *pptr;
1370 	char *msg = NULL;
1371 	int i;
1372 
1373 	/*
1374 	 * Disable interrupts
1375 	 */
1376 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1377 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1378 
1379 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "%s", __func__);
1380 
1381 	if (pwp->locks_initted) {
1382 		mutex_enter(&pwp->lock);
1383 	}
1384 	pwp->blocked = 1;
1385 
1386 	/*
1387 	 * Step 1
1388 	 */
1389 	s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2);
1390 	if ((s2 & PMCS_MSGU_HOST_SOFT_RESET_READY) == 0) {
1391 		pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
1392 		pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
1393 		for (i = 0; i < 100; i++) {
1394 			s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1395 			    PMCS_MSGU_HOST_SOFT_RESET_READY;
1396 			if (s2) {
1397 				break;
1398 			}
1399 			drv_usecwait(10000);
1400 		}
1401 		s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1402 		    PMCS_MSGU_HOST_SOFT_RESET_READY;
1403 		if (s2 == 0) {
1404 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1405 			    "%s: PMCS_MSGU_HOST_SOFT_RESET_READY never came "
1406 			    "ready", __func__);
1407 			pmcs_register_dump(pwp);
1408 			if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1409 			    PMCS_MSGU_CPU_SOFT_RESET_READY) == 0 ||
1410 			    (pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1411 			    PMCS_MSGU_CPU_SOFT_RESET_READY) == 0) {
1412 				pwp->state = STATE_DEAD;
1413 				pwp->blocked = 0;
1414 				if (pwp->locks_initted) {
1415 					mutex_exit(&pwp->lock);
1416 				}
1417 				return (-1);
1418 			}
1419 		}
1420 	}
1421 
1422 	/*
1423 	 * Step 2
1424 	 */
1425 	pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_IOP, 0);
1426 	drv_usecwait(10);
1427 	pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_AAP1, 0);
1428 	drv_usecwait(10);
1429 	pmcs_wr_topunit(pwp, PMCS_EVENT_INT_ENABLE, 0);
1430 	drv_usecwait(10);
1431 	pmcs_wr_topunit(pwp, PMCS_EVENT_INT_STAT,
1432 	    pmcs_rd_topunit(pwp, PMCS_EVENT_INT_STAT));
1433 	drv_usecwait(10);
1434 	pmcs_wr_topunit(pwp, PMCS_ERROR_INT_ENABLE, 0);
1435 	drv_usecwait(10);
1436 	pmcs_wr_topunit(pwp, PMCS_ERROR_INT_STAT,
1437 	    pmcs_rd_topunit(pwp, PMCS_ERROR_INT_STAT));
1438 	drv_usecwait(10);
1439 
1440 	sfrbits = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1441 	    PMCS_MSGU_AAP_SFR_PROGRESS;
1442 	sfrbits ^= PMCS_MSGU_AAP_SFR_PROGRESS;
1443 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "PMCS_MSGU_HOST_SCRATCH0 "
1444 	    "%08x -> %08x", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0),
1445 	    HST_SFT_RESET_SIG);
1446 	pmcs_wr_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0, HST_SFT_RESET_SIG);
1447 
1448 	/*
1449 	 * Step 3
1450 	 */
1451 	gsm = pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET);
1452 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GSM %08x -> %08x", gsm,
1453 	    gsm & ~PMCS_SOFT_RESET_BITS);
1454 	pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm & ~PMCS_SOFT_RESET_BITS);
1455 
1456 	/*
1457 	 * Step 4
1458 	 */
1459 	rapchk = pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN);
1460 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "READ_ADR_PARITY_CHK_EN "
1461 	    "%08x -> %08x", rapchk, 0);
1462 	pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, 0);
1463 	wapchk = pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN);
1464 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_ADR_PARITY_CHK_EN "
1465 	    "%08x -> %08x", wapchk, 0);
1466 	pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, 0);
1467 	wdpchk = pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN);
1468 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_DATA_PARITY_CHK_EN "
1469 	    "%08x -> %08x", wdpchk, 0);
1470 	pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, 0);
1471 
1472 	/*
1473 	 * Step 5
1474 	 */
1475 	drv_usecwait(100);
1476 
1477 	/*
1478 	 * Step 5.5 (Temporary workaround for 1.07.xx Beta)
1479 	 */
1480 	tsmode = pmcs_rd_gsm_reg(pwp, PMCS_GPIO_TRISTATE_MODE_ADDR);
1481 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GPIO TSMODE %08x -> %08x",
1482 	    tsmode, tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
1483 	pmcs_wr_gsm_reg(pwp, PMCS_GPIO_TRISTATE_MODE_ADDR,
1484 	    tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
1485 	drv_usecwait(10);
1486 
1487 	/*
1488 	 * Step 6
1489 	 */
1490 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1491 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1492 	    spc, spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1493 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
1494 	    spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1495 	drv_usecwait(10);
1496 
1497 	/*
1498 	 * Step 7
1499 	 */
1500 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1501 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1502 	    spc, spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
1503 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
1504 
1505 	/*
1506 	 * Step 8
1507 	 */
1508 	drv_usecwait(100);
1509 
1510 	/*
1511 	 * Step 9
1512 	 */
1513 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1514 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1515 	    spc, spc | (BDMA_CORE_RSTB|OSSP_RSTB));
1516 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc | (BDMA_CORE_RSTB|OSSP_RSTB));
1517 
1518 	/*
1519 	 * Step 10
1520 	 */
1521 	drv_usecwait(100);
1522 
1523 	/*
1524 	 * Step 11
1525 	 */
1526 	gsm = pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET);
1527 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GSM %08x -> %08x", gsm,
1528 	    gsm | PMCS_SOFT_RESET_BITS);
1529 	pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm | PMCS_SOFT_RESET_BITS);
1530 	drv_usecwait(10);
1531 
1532 	/*
1533 	 * Step 12
1534 	 */
1535 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "READ_ADR_PARITY_CHK_EN "
1536 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN),
1537 	    rapchk);
1538 	pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, rapchk);
1539 	drv_usecwait(10);
1540 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_ADR_PARITY_CHK_EN "
1541 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN),
1542 	    wapchk);
1543 	pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, wapchk);
1544 	drv_usecwait(10);
1545 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_DATA_PARITY_CHK_EN "
1546 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN),
1547 	    wapchk);
1548 	pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, wdpchk);
1549 	drv_usecwait(10);
1550 
1551 	/*
1552 	 * Step 13
1553 	 */
1554 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1555 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1556 	    spc, spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1557 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
1558 	    spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1559 
1560 	/*
1561 	 * Step 14
1562 	 */
1563 	drv_usecwait(100);
1564 
1565 	/*
1566 	 * Step 15
1567 	 */
1568 	for (spc = 0, i = 0; i < 1000; i++) {
1569 		drv_usecwait(1000);
1570 		spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
1571 		if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) == sfrbits) {
1572 			break;
1573 		}
1574 	}
1575 
1576 	if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) != sfrbits) {
1577 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1578 		    "SFR didn't toggle (sfr 0x%x)", spc);
1579 		pwp->state = STATE_DEAD;
1580 		pwp->blocked = 0;
1581 		if (pwp->locks_initted) {
1582 			mutex_exit(&pwp->lock);
1583 		}
1584 		return (-1);
1585 	}
1586 
1587 	/*
1588 	 * Step 16
1589 	 */
1590 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1591 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1592 
1593 	/*
1594 	 * Wait for up to 5 seconds for AAP state to come either ready or error.
1595 	 */
1596 	for (i = 0; i < 50; i++) {
1597 		spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1598 		    PMCS_MSGU_AAP_STATE_MASK;
1599 		if (spc == PMCS_MSGU_AAP_STATE_ERROR ||
1600 		    spc == PMCS_MSGU_AAP_STATE_READY) {
1601 			break;
1602 		}
1603 		drv_usecwait(100000);
1604 	}
1605 	spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
1606 	if ((spc & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
1607 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1608 		    "soft reset failed (state 0x%x)", spc);
1609 		pwp->state = STATE_DEAD;
1610 		pwp->blocked = 0;
1611 		if (pwp->locks_initted) {
1612 			mutex_exit(&pwp->lock);
1613 		}
1614 		return (-1);
1615 	}
1616 
1617 
1618 	if (pwp->state == STATE_DEAD || pwp->state == STATE_UNPROBING ||
1619 	    pwp->state == STATE_PROBING || pwp->locks_initted == 0) {
1620 		pwp->blocked = 0;
1621 		if (pwp->locks_initted) {
1622 			mutex_exit(&pwp->lock);
1623 		}
1624 		return (0);
1625 	}
1626 
1627 	/*
1628 	 * Return at this point if we dont need to startup.
1629 	 */
1630 	if (no_restart) {
1631 		return (0);
1632 	}
1633 
1634 	ASSERT(pwp->locks_initted != 0);
1635 
1636 	/*
1637 	 * Clean up various soft state.
1638 	 */
1639 	bzero(pwp->ports, sizeof (pwp->ports));
1640 
1641 	pmcs_free_all_phys(pwp, pwp->root_phys);
1642 
1643 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
1644 		pmcs_lock_phy(pptr);
1645 		pmcs_clear_phy(pwp, pptr);
1646 		pmcs_unlock_phy(pptr);
1647 	}
1648 
1649 	if (pwp->targets) {
1650 		for (i = 0; i < pwp->max_dev; i++) {
1651 			pmcs_xscsi_t *xp = pwp->targets[i];
1652 
1653 			if (xp == NULL) {
1654 				continue;
1655 			}
1656 			mutex_enter(&xp->statlock);
1657 			pmcs_clear_xp(pwp, xp);
1658 			mutex_exit(&xp->statlock);
1659 		}
1660 	}
1661 
1662 	bzero(pwp->shadow_iqpi, sizeof (pwp->shadow_iqpi));
1663 	for (i = 0; i < PMCS_NIQ; i++) {
1664 		if (pwp->iqp[i]) {
1665 			bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
1666 			pmcs_wr_iqpi(pwp, i, 0);
1667 			pmcs_wr_iqci(pwp, i, 0);
1668 		}
1669 	}
1670 	for (i = 0; i < PMCS_NOQ; i++) {
1671 		if (pwp->oqp[i]) {
1672 			bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
1673 			pmcs_wr_oqpi(pwp, i, 0);
1674 			pmcs_wr_oqci(pwp, i, 0);
1675 		}
1676 
1677 	}
1678 	if (pwp->fwlogp) {
1679 		bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
1680 	}
1681 	STAILQ_INIT(&pwp->wf);
1682 	bzero(pwp->work, sizeof (pmcwork_t) * pwp->max_cmd);
1683 	for (i = 0; i < pwp->max_cmd - 1; i++) {
1684 		pmcwork_t *pwrk = &pwp->work[i];
1685 		STAILQ_INSERT_TAIL(&pwp->wf, pwrk, next);
1686 	}
1687 
1688 	/*
1689 	 * Clear out any leftover commands sitting in the work list
1690 	 */
1691 	for (i = 0; i < pwp->max_cmd; i++) {
1692 		pmcwork_t *pwrk = &pwp->work[i];
1693 		mutex_enter(&pwrk->lock);
1694 		if (pwrk->state == PMCS_WORK_STATE_ONCHIP) {
1695 			switch (PMCS_TAG_TYPE(pwrk->htag)) {
1696 			case PMCS_TAG_TYPE_WAIT:
1697 				mutex_exit(&pwrk->lock);
1698 				break;
1699 			case PMCS_TAG_TYPE_CBACK:
1700 			case PMCS_TAG_TYPE_NONE:
1701 				pmcs_pwork(pwp, pwrk);
1702 				break;
1703 			default:
1704 				break;
1705 			}
1706 		} else if (pwrk->state == PMCS_WORK_STATE_IOCOMPQ) {
1707 			pwrk->dead = 1;
1708 			mutex_exit(&pwrk->lock);
1709 		} else {
1710 			/*
1711 			 * The other states of NIL, READY and INTR
1712 			 * should not be visible outside of a lock being held.
1713 			 */
1714 			pmcs_pwork(pwp, pwrk);
1715 		}
1716 	}
1717 
1718 	/*
1719 	 * Restore Interrupt Mask
1720 	 */
1721 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
1722 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1723 
1724 	pwp->blocked = 0;
1725 	pwp->mpi_table_setup = 0;
1726 	mutex_exit(&pwp->lock);
1727 
1728 	/*
1729 	 * Set up MPI again.
1730 	 */
1731 	if (pmcs_setup(pwp)) {
1732 		msg = "unable to setup MPI tables again";
1733 		goto fail_restart;
1734 	}
1735 	pmcs_report_fwversion(pwp);
1736 
1737 	/*
1738 	 * Restart MPI
1739 	 */
1740 	if (pmcs_start_mpi(pwp)) {
1741 		msg = "unable to restart MPI again";
1742 		goto fail_restart;
1743 	}
1744 
1745 	mutex_enter(&pwp->lock);
1746 	pwp->blocked = 0;
1747 	SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
1748 	mutex_exit(&pwp->lock);
1749 
1750 	/*
1751 	 * Run any completions
1752 	 */
1753 	PMCS_CQ_RUN(pwp);
1754 
1755 	/*
1756 	 * Delay
1757 	 */
1758 	drv_usecwait(1000000);
1759 	return (0);
1760 
1761 fail_restart:
1762 	mutex_enter(&pwp->lock);
1763 	pwp->state = STATE_DEAD;
1764 	mutex_exit(&pwp->lock);
1765 	pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1766 	    "%s: Failed: %s", __func__, msg);
1767 	return (-1);
1768 }
1769 
1770 /*
1771  * Reset a device or a logical unit.
1772  */
1773 int
1774 pmcs_reset_dev(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint64_t lun)
1775 {
1776 	int rval = 0;
1777 
1778 	if (pptr == NULL) {
1779 		return (ENXIO);
1780 	}
1781 
1782 	pmcs_lock_phy(pptr);
1783 	if (pptr->dtype == SAS) {
1784 		/*
1785 		 * Some devices do not support SAS_I_T_NEXUS_RESET as
1786 		 * it is not a mandatory (in SAM4) task management
1787 		 * function, while LOGIC_UNIT_RESET is mandatory.
1788 		 *
1789 		 * The problem here is that we need to iterate over
1790 		 * all known LUNs to emulate the semantics of
1791 		 * "RESET_TARGET".
1792 		 *
1793 		 * XXX: FIX ME
1794 		 */
1795 		if (lun == (uint64_t)-1) {
1796 			lun = 0;
1797 		}
1798 		rval = pmcs_ssp_tmf(pwp, pptr, SAS_LOGICAL_UNIT_RESET, 0, lun,
1799 		    NULL);
1800 	} else if (pptr->dtype == SATA) {
1801 		if (lun != 0ull) {
1802 			pmcs_unlock_phy(pptr);
1803 			return (EINVAL);
1804 		}
1805 		rval = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_LINK_RESET);
1806 	} else {
1807 		pmcs_unlock_phy(pptr);
1808 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1809 		    "%s: cannot reset a SMP device yet (%s)",
1810 		    __func__, pptr->path);
1811 		return (EINVAL);
1812 	}
1813 
1814 	/*
1815 	 * Now harvest any commands killed by this action
1816 	 * by issuing an ABORT for all commands on this device.
1817 	 *
1818 	 * We do this even if the the tmf or reset fails (in case there
1819 	 * are any dead commands around to be harvested *anyway*).
1820 	 * We don't have to await for the abort to complete.
1821 	 */
1822 	if (pmcs_abort(pwp, pptr, 0, 1, 0)) {
1823 		pptr->abort_pending = 1;
1824 		SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
1825 	}
1826 
1827 	pmcs_unlock_phy(pptr);
1828 	return (rval);
1829 }
1830 
1831 /*
1832  * Called with PHY locked.
1833  */
1834 static int
1835 pmcs_get_device_handle(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1836 {
1837 	if (pptr->valid_device_id == 0) {
1838 		int result = pmcs_register_device(pwp, pptr);
1839 
1840 		/*
1841 		 * If we changed while registering, punt
1842 		 */
1843 		if (pptr->changed) {
1844 			RESTART_DISCOVERY(pwp);
1845 			return (-1);
1846 		}
1847 
1848 		/*
1849 		 * If we had a failure to register, check against errors.
1850 		 * An ENOMEM error means we just retry (temp resource shortage).
1851 		 */
1852 		if (result == ENOMEM) {
1853 			PHY_CHANGED(pwp, pptr);
1854 			RESTART_DISCOVERY(pwp);
1855 			return (-1);
1856 		}
1857 
1858 		/*
1859 		 * An ETIMEDOUT error means we retry (if our counter isn't
1860 		 * exhausted)
1861 		 */
1862 		if (result == ETIMEDOUT) {
1863 			if (ddi_get_lbolt() < pptr->config_stop) {
1864 				PHY_CHANGED(pwp, pptr);
1865 				RESTART_DISCOVERY(pwp);
1866 			} else {
1867 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
1868 				    "%s: Retries exhausted for %s, killing",
1869 				    __func__, pptr->path);
1870 				pptr->config_stop = 0;
1871 				pmcs_kill_changed(pwp, pptr, 0);
1872 			}
1873 			return (-1);
1874 		}
1875 		/*
1876 		 * Other errors or no valid device id is fatal, but don't
1877 		 * preclude a future action.
1878 		 */
1879 		if (result || pptr->valid_device_id == 0) {
1880 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
1881 			    "%s: %s could not be registered", __func__,
1882 			    pptr->path);
1883 			return (-1);
1884 		}
1885 	}
1886 	return (0);
1887 }
1888 
1889 int
1890 pmcs_iport_tgtmap_create(pmcs_iport_t *iport)
1891 {
1892 	ASSERT(iport);
1893 	if (iport == NULL)
1894 		return (B_FALSE);
1895 
1896 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s", __func__);
1897 
1898 	/* create target map */
1899 	if (scsi_hba_tgtmap_create(iport->dip, SCSI_TM_FULLSET, tgtmap_usec,
1900 	    NULL, NULL, NULL, &iport->iss_tgtmap) != DDI_SUCCESS) {
1901 		pmcs_prt(iport->pwp, PMCS_PRT_DEBUG, NULL, NULL,
1902 		    "%s: failed to create tgtmap", __func__);
1903 		return (B_FALSE);
1904 	}
1905 	return (B_TRUE);
1906 }
1907 
1908 int
1909 pmcs_iport_tgtmap_destroy(pmcs_iport_t *iport)
1910 {
1911 	ASSERT(iport && iport->iss_tgtmap);
1912 	if ((iport == NULL) || (iport->iss_tgtmap == NULL))
1913 		return (B_FALSE);
1914 
1915 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s", __func__);
1916 
1917 	/* destroy target map */
1918 	scsi_hba_tgtmap_destroy(iport->iss_tgtmap);
1919 	return (B_TRUE);
1920 }
1921 
1922 /*
1923  * Query the phymap and populate the iport handle passed in.
1924  * Called with iport lock held.
1925  */
1926 int
1927 pmcs_iport_configure_phys(pmcs_iport_t *iport)
1928 {
1929 	pmcs_hw_t		*pwp;
1930 	pmcs_phy_t		*pptr;
1931 	sas_phymap_phys_t	*phys;
1932 	int			phynum;
1933 	int			inst;
1934 
1935 	ASSERT(iport);
1936 	ASSERT(mutex_owned(&iport->lock));
1937 	pwp = iport->pwp;
1938 	ASSERT(pwp);
1939 	inst = ddi_get_instance(iport->dip);
1940 
1941 	mutex_enter(&pwp->lock);
1942 	ASSERT(pwp->root_phys != NULL);
1943 
1944 	/*
1945 	 * Query the phymap regarding the phys in this iport and populate
1946 	 * the iport's phys list. Hereafter this list is maintained via
1947 	 * port up and down events in pmcs_intr.c
1948 	 */
1949 	ASSERT(list_is_empty(&iport->phys));
1950 	phys = sas_phymap_ua2phys(pwp->hss_phymap, iport->ua);
1951 	while ((phynum = sas_phymap_phys_next(phys)) != -1) {
1952 		/* Grab the phy pointer from root_phys */
1953 		pptr = pwp->root_phys + phynum;
1954 		ASSERT(pptr);
1955 		pmcs_lock_phy(pptr);
1956 		ASSERT(pptr->phynum == phynum);
1957 
1958 		/*
1959 		 * Set a back pointer in the phy to this iport.
1960 		 */
1961 		pptr->iport = iport;
1962 
1963 		/*
1964 		 * If this phy is the primary, set a pointer to it on our
1965 		 * iport handle, and set our portid from it.
1966 		 */
1967 		if (!pptr->subsidiary) {
1968 			iport->pptr = pptr;
1969 			iport->portid = pptr->portid;
1970 		}
1971 
1972 		/*
1973 		 * Finally, insert the phy into our list
1974 		 */
1975 		pmcs_add_phy_to_iport(iport, pptr);
1976 		pmcs_unlock_phy(pptr);
1977 
1978 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: found "
1979 		    "phy %d [0x%p] on iport%d, refcnt(%d)", __func__, phynum,
1980 		    (void *)pptr, inst, iport->refcnt);
1981 	}
1982 	mutex_exit(&pwp->lock);
1983 	sas_phymap_phys_free(phys);
1984 	RESTART_DISCOVERY(pwp);
1985 	return (DDI_SUCCESS);
1986 }
1987 
1988 /*
1989  * Return the iport that ua is associated with, or NULL.  If an iport is
1990  * returned, it will be held and the caller must release the hold.
1991  */
1992 static pmcs_iport_t *
1993 pmcs_get_iport_by_ua(pmcs_hw_t *pwp, char *ua)
1994 {
1995 	pmcs_iport_t	*iport = NULL;
1996 
1997 	rw_enter(&pwp->iports_lock, RW_READER);
1998 	for (iport = list_head(&pwp->iports);
1999 	    iport != NULL;
2000 	    iport = list_next(&pwp->iports, iport)) {
2001 		mutex_enter(&iport->lock);
2002 		if (strcmp(iport->ua, ua) == 0) {
2003 			mutex_exit(&iport->lock);
2004 			mutex_enter(&iport->refcnt_lock);
2005 			iport->refcnt++;
2006 			mutex_exit(&iport->refcnt_lock);
2007 			break;
2008 		}
2009 		mutex_exit(&iport->lock);
2010 	}
2011 	rw_exit(&pwp->iports_lock);
2012 
2013 	return (iport);
2014 }
2015 
2016 /*
2017  * Return the iport that pptr is associated with, or NULL.
2018  * If an iport is returned, there is a hold that the caller must release.
2019  */
2020 pmcs_iport_t *
2021 pmcs_get_iport_by_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2022 {
2023 	pmcs_iport_t	*iport = NULL;
2024 	char		*ua;
2025 
2026 	ua = sas_phymap_lookup_ua(pwp->hss_phymap, pwp->sas_wwns[0],
2027 	    pmcs_barray2wwn(pptr->sas_address));
2028 	if (ua) {
2029 		iport = pmcs_get_iport_by_ua(pwp, ua);
2030 		if (iport) {
2031 			mutex_enter(&iport->lock);
2032 			iport->ua_state = UA_ACTIVE;
2033 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: "
2034 			    "found iport [0x%p] on ua (%s) for phy [0x%p], "
2035 			    "refcnt (%d)", __func__, (void *)iport, ua,
2036 			    (void *)pptr, iport->refcnt);
2037 			mutex_exit(&iport->lock);
2038 		}
2039 	}
2040 
2041 	return (iport);
2042 }
2043 
2044 void
2045 pmcs_rele_iport(pmcs_iport_t *iport)
2046 {
2047 	/*
2048 	 * Release a refcnt on this iport. If this is the last reference,
2049 	 * signal the potential waiter in pmcs_iport_unattach().
2050 	 */
2051 	ASSERT(iport->refcnt > 0);
2052 	mutex_enter(&iport->refcnt_lock);
2053 	iport->refcnt--;
2054 	mutex_exit(&iport->refcnt_lock);
2055 	if (iport->refcnt == 0) {
2056 		cv_signal(&iport->refcnt_cv);
2057 	}
2058 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: iport "
2059 	    "[0x%p] refcnt (%d)", __func__, (void *)iport, iport->refcnt);
2060 }
2061 
2062 void
2063 pmcs_phymap_activate(void *arg, char *ua, void **privp)
2064 {
2065 	_NOTE(ARGUNUSED(privp));
2066 	pmcs_hw_t	*pwp = arg;
2067 	pmcs_iport_t	*iport = NULL;
2068 
2069 	mutex_enter(&pwp->lock);
2070 	if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
2071 		mutex_exit(&pwp->lock);
2072 		return;
2073 	}
2074 	pwp->phymap_active++;
2075 	mutex_exit(&pwp->lock);
2076 
2077 	if (scsi_hba_iportmap_iport_add(pwp->hss_iportmap, ua, NULL) !=
2078 	    DDI_SUCCESS) {
2079 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: failed to "
2080 		    "add iport handle on unit address [%s]", __func__, ua);
2081 	} else {
2082 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: "
2083 		    "phymap_active count (%d), added iport handle on unit "
2084 		    "address [%s]", __func__, pwp->phymap_active, ua);
2085 	}
2086 
2087 	/* Set the HBA softstate as our private data for this unit address */
2088 	*privp = (void *)pwp;
2089 
2090 	/*
2091 	 * We are waiting on attach for this iport node, unless it is still
2092 	 * attached. This can happen if a consumer has an outstanding open
2093 	 * on our iport node, but the port is down.  If this is the case, we
2094 	 * need to configure our iport here for reuse.
2095 	 */
2096 	iport = pmcs_get_iport_by_ua(pwp, ua);
2097 	if (iport) {
2098 		mutex_enter(&iport->lock);
2099 		if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
2100 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: "
2101 			    "failed to configure phys on iport [0x%p] at "
2102 			    "unit address (%s)", __func__, (void *)iport, ua);
2103 		}
2104 		iport->ua_state = UA_ACTIVE;
2105 		pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
2106 		    &iport->nphy);
2107 		mutex_exit(&iport->lock);
2108 		pmcs_rele_iport(iport);
2109 	}
2110 
2111 }
2112 
2113 void
2114 pmcs_phymap_deactivate(void *arg, char *ua, void *privp)
2115 {
2116 	_NOTE(ARGUNUSED(privp));
2117 	pmcs_hw_t	*pwp = arg;
2118 	pmcs_iport_t	*iport;
2119 
2120 	mutex_enter(&pwp->lock);
2121 	pwp->phymap_active--;
2122 	mutex_exit(&pwp->lock);
2123 
2124 	if (scsi_hba_iportmap_iport_remove(pwp->hss_iportmap, ua) !=
2125 	    DDI_SUCCESS) {
2126 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: failed to "
2127 		    "remove iport handle on unit address [%s]", __func__, ua);
2128 	} else {
2129 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: "
2130 		    "phymap_active count (%d), removed iport handle on unit "
2131 		    "address [%s]", __func__, pwp->phymap_active, ua);
2132 	}
2133 
2134 	iport = pmcs_get_iport_by_ua(pwp, ua);
2135 
2136 	if (iport == NULL) {
2137 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: failed "
2138 		    "lookup of iport handle on unit addr (%s)", __func__, ua);
2139 		return;
2140 	}
2141 
2142 	mutex_enter(&iport->lock);
2143 	iport->ua_state = UA_INACTIVE;
2144 	iport->portid = PMCS_IPORT_INVALID_PORT_ID;
2145 	pmcs_remove_phy_from_iport(iport, NULL);
2146 	mutex_exit(&iport->lock);
2147 	pmcs_rele_iport(iport);
2148 }
2149 
2150 /*
2151  * Top-level discovery function
2152  */
2153 void
2154 pmcs_discover(pmcs_hw_t *pwp)
2155 {
2156 	pmcs_phy_t		*pptr;
2157 	pmcs_phy_t		*root_phy;
2158 	boolean_t		config_changed;
2159 
2160 	DTRACE_PROBE2(pmcs__discover__entry, ulong_t, pwp->work_flags,
2161 	    boolean_t, pwp->config_changed);
2162 
2163 	mutex_enter(&pwp->lock);
2164 
2165 	if (pwp->state != STATE_RUNNING) {
2166 		mutex_exit(&pwp->lock);
2167 		return;
2168 	}
2169 
2170 	/* Ensure we have at least one phymap active */
2171 	if (pwp->phymap_active == 0) {
2172 		mutex_exit(&pwp->lock);
2173 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2174 		    "%s: phymap inactive, exiting", __func__);
2175 		return;
2176 	}
2177 
2178 	mutex_exit(&pwp->lock);
2179 
2180 	/*
2181 	 * If no iports have attached, but we have PHYs that are up, we
2182 	 * are waiting for iport attach to complete.  Restart discovery.
2183 	 */
2184 	rw_enter(&pwp->iports_lock, RW_READER);
2185 	if (!pwp->iports_attached) {
2186 		rw_exit(&pwp->iports_lock);
2187 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2188 		    "%s: no iports attached, retry discovery", __func__);
2189 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2190 		return;
2191 	}
2192 	rw_exit(&pwp->iports_lock);
2193 
2194 	mutex_enter(&pwp->config_lock);
2195 	if (pwp->configuring) {
2196 		mutex_exit(&pwp->config_lock);
2197 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2198 		    "%s: configuration already in progress", __func__);
2199 		return;
2200 	}
2201 
2202 	if (pmcs_acquire_scratch(pwp, B_FALSE)) {
2203 		mutex_exit(&pwp->config_lock);
2204 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2205 		    "%s: cannot allocate scratch", __func__);
2206 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2207 		return;
2208 	}
2209 
2210 	pwp->configuring = 1;
2211 	pwp->config_changed = B_FALSE;
2212 	mutex_exit(&pwp->config_lock);
2213 
2214 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "Discovery begin");
2215 
2216 	/*
2217 	 * The order of the following traversals is important.
2218 	 *
2219 	 * The first one checks for changed expanders.
2220 	 *
2221 	 * The second one aborts commands for dead devices and deregisters them.
2222 	 *
2223 	 * The third one clears the contents of dead expanders from the tree
2224 	 *
2225 	 * The fourth one clears now dead devices in expanders that remain.
2226 	 */
2227 
2228 	/*
2229 	 * 1. Check expanders marked changed (but not dead) to see if they still
2230 	 * have the same number of phys and the same SAS address. Mark them,
2231 	 * their subsidiary phys (if wide) and their descendents dead if
2232 	 * anything has changed. Check the devices they contain to see if
2233 	 * *they* have changed. If they've changed from type NOTHING we leave
2234 	 * them marked changed to be configured later (picking up a new SAS
2235 	 * address and link rate if possible). Otherwise, any change in type,
2236 	 * SAS address or removal of target role will cause us to mark them
2237 	 * (and their descendents) as dead (and cause any pending commands
2238 	 * and associated devices to be removed).
2239 	 *
2240 	 * NOTE: We don't want to bail on discovery if the config has
2241 	 * changed until *after* we run pmcs_kill_devices.
2242 	 */
2243 	root_phy = pwp->root_phys;
2244 	config_changed = pmcs_check_expanders(pwp, root_phy);
2245 
2246 	/*
2247 	 * 2. Descend the tree looking for dead devices and kill them
2248 	 * by aborting all active commands and then deregistering them.
2249 	 */
2250 	if (pmcs_kill_devices(pwp, root_phy) || config_changed) {
2251 		goto out;
2252 	}
2253 
2254 	/*
2255 	 * 3. Check for dead expanders and remove their children from the tree.
2256 	 * By the time we get here, the devices and commands for them have
2257 	 * already been terminated and removed.
2258 	 *
2259 	 * We do this independent of the configuration count changing so we can
2260 	 * free any dead device PHYs that were discovered while checking
2261 	 * expanders. We ignore any subsidiary phys as pmcs_clear_expander
2262 	 * will take care of those.
2263 	 *
2264 	 * NOTE: pmcs_clear_expander requires softstate lock
2265 	 */
2266 	mutex_enter(&pwp->lock);
2267 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
2268 		/*
2269 		 * Call pmcs_clear_expander for every root PHY.  It will
2270 		 * recurse and determine which (if any) expanders actually
2271 		 * need to be cleared.
2272 		 */
2273 		pmcs_lock_phy(pptr);
2274 		pmcs_clear_expander(pwp, pptr, 0);
2275 		pmcs_unlock_phy(pptr);
2276 	}
2277 	mutex_exit(&pwp->lock);
2278 
2279 	/*
2280 	 * 4. Check for dead devices and nullify them. By the time we get here,
2281 	 * the devices and commands for them have already been terminated
2282 	 * and removed. This is different from step 2 in that this just nulls
2283 	 * phys that are part of expanders that are still here but used to
2284 	 * be something but are no longer something (e.g., after a pulled
2285 	 * disk drive). Note that dead expanders had their contained phys
2286 	 * removed from the tree- here, the expanders themselves are
2287 	 * nullified (unless they were removed by being contained in another
2288 	 * expander phy).
2289 	 */
2290 	pmcs_clear_phys(pwp, root_phy);
2291 
2292 	/*
2293 	 * 5. Now check for and configure new devices.
2294 	 */
2295 	if (pmcs_configure_new_devices(pwp, root_phy)) {
2296 		goto restart;
2297 	}
2298 
2299 out:
2300 	DTRACE_PROBE2(pmcs__discover__exit, ulong_t, pwp->work_flags,
2301 	    boolean_t, pwp->config_changed);
2302 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "Discovery end");
2303 
2304 	mutex_enter(&pwp->config_lock);
2305 
2306 	if (pwp->config_changed == B_FALSE) {
2307 		/*
2308 		 * Observation is stable, report what we currently see to
2309 		 * the tgtmaps for delta processing. Start by setting
2310 		 * BEGIN on all tgtmaps.
2311 		 */
2312 		mutex_exit(&pwp->config_lock);
2313 		if (pmcs_report_observations(pwp) == B_FALSE) {
2314 			goto restart;
2315 		}
2316 		mutex_enter(&pwp->config_lock);
2317 	} else {
2318 		/*
2319 		 * If config_changed is TRUE, we need to reschedule
2320 		 * discovery now.
2321 		 */
2322 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2323 		    "%s: Config has changed, will re-run discovery", __func__);
2324 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2325 	}
2326 
2327 	pmcs_release_scratch(pwp);
2328 	pwp->configuring = 0;
2329 	mutex_exit(&pwp->config_lock);
2330 
2331 #ifdef DEBUG
2332 	pptr = pmcs_find_phy_needing_work(pwp, pwp->root_phys);
2333 	if (pptr != NULL) {
2334 		if (!WORK_IS_SCHEDULED(pwp, PMCS_WORK_DISCOVER)) {
2335 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
2336 			    "PHY %s dead=%d changed=%d configured=%d "
2337 			    "but no work scheduled", pptr->path, pptr->dead,
2338 			    pptr->changed, pptr->configured);
2339 		}
2340 		pmcs_unlock_phy(pptr);
2341 	}
2342 #endif
2343 
2344 	return;
2345 
2346 restart:
2347 	/* Clean up and restart discovery */
2348 	pmcs_release_scratch(pwp);
2349 	mutex_enter(&pwp->config_lock);
2350 	pwp->configuring = 0;
2351 	RESTART_DISCOVERY_LOCKED(pwp);
2352 	mutex_exit(&pwp->config_lock);
2353 }
2354 
2355 /*
2356  * Return any PHY that needs to have scheduled work done.  The PHY is returned
2357  * locked.
2358  */
2359 static pmcs_phy_t *
2360 pmcs_find_phy_needing_work(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2361 {
2362 	pmcs_phy_t *cphyp, *pnext;
2363 
2364 	while (pptr) {
2365 		pmcs_lock_phy(pptr);
2366 
2367 		if (pptr->changed || (pptr->dead && pptr->valid_device_id)) {
2368 			return (pptr);
2369 		}
2370 
2371 		pnext = pptr->sibling;
2372 
2373 		if (pptr->children) {
2374 			cphyp = pptr->children;
2375 			pmcs_unlock_phy(pptr);
2376 			cphyp = pmcs_find_phy_needing_work(pwp, cphyp);
2377 			if (cphyp) {
2378 				return (cphyp);
2379 			}
2380 		} else {
2381 			pmcs_unlock_phy(pptr);
2382 		}
2383 
2384 		pptr = pnext;
2385 	}
2386 
2387 	return (NULL);
2388 }
2389 
2390 /*
2391  * Report current observations to SCSA.
2392  */
2393 static boolean_t
2394 pmcs_report_observations(pmcs_hw_t *pwp)
2395 {
2396 	pmcs_iport_t		*iport;
2397 	scsi_hba_tgtmap_t	*tgtmap;
2398 	char			*ap;
2399 	pmcs_phy_t		*pptr;
2400 	uint64_t		wwn;
2401 
2402 	/*
2403 	 * Observation is stable, report what we currently see to the tgtmaps
2404 	 * for delta processing. Start by setting BEGIN on all tgtmaps.
2405 	 */
2406 	rw_enter(&pwp->iports_lock, RW_READER);
2407 	for (iport = list_head(&pwp->iports); iport != NULL;
2408 	    iport = list_next(&pwp->iports, iport)) {
2409 		/*
2410 		 * Unless we have at least one phy up, skip this iport.
2411 		 * Note we don't need to lock the iport for report_skip
2412 		 * since it is only used here.  We are doing the skip so that
2413 		 * the phymap and iportmap stabilization times are honored -
2414 		 * giving us the ability to recover port operation within the
2415 		 * stabilization time without unconfiguring targets using the
2416 		 * port.
2417 		 */
2418 		if (!sas_phymap_uahasphys(pwp->hss_phymap, iport->ua)) {
2419 			iport->report_skip = 1;
2420 			continue;		/* skip set_begin */
2421 		}
2422 		iport->report_skip = 0;
2423 
2424 		tgtmap = iport->iss_tgtmap;
2425 		ASSERT(tgtmap);
2426 		if (scsi_hba_tgtmap_set_begin(tgtmap) != DDI_SUCCESS) {
2427 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2428 			    "%s: cannot set_begin tgtmap ", __func__);
2429 			rw_exit(&pwp->iports_lock);
2430 			return (B_FALSE);
2431 		}
2432 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2433 		    "%s: set begin on tgtmap [0x%p]", __func__, (void *)tgtmap);
2434 	}
2435 	rw_exit(&pwp->iports_lock);
2436 
2437 	/*
2438 	 * Now, cycle through all levels of all phys and report
2439 	 * observations into their respective tgtmaps.
2440 	 */
2441 	pptr = pwp->root_phys;
2442 
2443 	while (pptr) {
2444 		pmcs_lock_phy(pptr);
2445 
2446 		/*
2447 		 * Skip PHYs that have nothing attached or are dead.
2448 		 */
2449 		if ((pptr->dtype == NOTHING) || pptr->dead) {
2450 			pmcs_unlock_phy(pptr);
2451 			pptr = pptr->sibling;
2452 			continue;
2453 		}
2454 
2455 		if (pptr->changed) {
2456 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
2457 			    "%s: oops, PHY %s changed; restart discovery",
2458 			    __func__, pptr->path);
2459 			pmcs_unlock_phy(pptr);
2460 			return (B_FALSE);
2461 		}
2462 
2463 		/*
2464 		 * Get the iport for this root PHY, then call the helper
2465 		 * to report observations for this iport's targets
2466 		 */
2467 		iport = pmcs_get_iport_by_phy(pwp, pptr);
2468 		if (iport == NULL) {
2469 			/* No iport for this tgt */
2470 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2471 			    "%s: no iport for this target", __func__);
2472 			pmcs_unlock_phy(pptr);
2473 			pptr = pptr->sibling;
2474 			continue;
2475 		}
2476 
2477 		if (!iport->report_skip) {
2478 			if (pmcs_report_iport_observations(
2479 			    pwp, iport, pptr) == B_FALSE) {
2480 				pmcs_rele_iport(iport);
2481 				pmcs_unlock_phy(pptr);
2482 				return (B_FALSE);
2483 			}
2484 		}
2485 		pmcs_rele_iport(iport);
2486 		pmcs_unlock_phy(pptr);
2487 		pptr = pptr->sibling;
2488 	}
2489 
2490 	/*
2491 	 * The observation is complete, end sets. Note we will skip any
2492 	 * iports that are active, but have no PHYs in them (i.e. awaiting
2493 	 * unconfigure). Set to restart discovery if we find this.
2494 	 */
2495 	rw_enter(&pwp->iports_lock, RW_READER);
2496 	for (iport = list_head(&pwp->iports);
2497 	    iport != NULL;
2498 	    iport = list_next(&pwp->iports, iport)) {
2499 
2500 		if (iport->report_skip)
2501 			continue;		/* skip set_end */
2502 
2503 		tgtmap = iport->iss_tgtmap;
2504 		ASSERT(tgtmap);
2505 		if (scsi_hba_tgtmap_set_end(tgtmap, 0) != DDI_SUCCESS) {
2506 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2507 			    "%s: cannot set_end tgtmap ", __func__);
2508 			rw_exit(&pwp->iports_lock);
2509 			return (B_FALSE);
2510 		}
2511 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2512 		    "%s: set end on tgtmap [0x%p]", __func__, (void *)tgtmap);
2513 	}
2514 
2515 	/*
2516 	 * Now that discovery is complete, set up the necessary
2517 	 * DDI properties on each iport node.
2518 	 */
2519 	for (iport = list_head(&pwp->iports); iport != NULL;
2520 	    iport = list_next(&pwp->iports, iport)) {
2521 		/* Set up the DDI properties on each phy */
2522 		pmcs_smhba_set_phy_props(iport);
2523 
2524 		/* Set up the 'attached-port' property on the iport */
2525 		ap = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
2526 		mutex_enter(&iport->lock);
2527 		pptr = iport->pptr;
2528 		mutex_exit(&iport->lock);
2529 		if (pptr == NULL) {
2530 			/*
2531 			 * This iport is down, but has not been
2532 			 * removed from our list (unconfigured).
2533 			 * Set our value to '0'.
2534 			 */
2535 			(void) snprintf(ap, 1, "%s", "0");
2536 		} else {
2537 			/* Otherwise, set it to remote phy's wwn */
2538 			pmcs_lock_phy(pptr);
2539 			wwn = pmcs_barray2wwn(pptr->sas_address);
2540 			(void) scsi_wwn_to_wwnstr(wwn, 1, ap);
2541 			pmcs_unlock_phy(pptr);
2542 		}
2543 		if (ndi_prop_update_string(DDI_DEV_T_NONE, iport->dip,
2544 		    SCSI_ADDR_PROP_ATTACHED_PORT,  ap) != DDI_SUCCESS) {
2545 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed "
2546 			    "to set prop ("SCSI_ADDR_PROP_ATTACHED_PORT")",
2547 			    __func__);
2548 		}
2549 		kmem_free(ap, PMCS_MAX_UA_SIZE);
2550 	}
2551 	rw_exit(&pwp->iports_lock);
2552 
2553 	return (B_TRUE);
2554 }
2555 
2556 /*
2557  * Report observations into a particular iport's target map
2558  *
2559  * Called with phyp (and all descendents) locked
2560  */
2561 static boolean_t
2562 pmcs_report_iport_observations(pmcs_hw_t *pwp, pmcs_iport_t *iport,
2563     pmcs_phy_t *phyp)
2564 {
2565 	pmcs_phy_t		*lphyp;
2566 	scsi_hba_tgtmap_t	*tgtmap;
2567 	scsi_tgtmap_tgt_type_t	tgt_type;
2568 	char			*ua;
2569 	uint64_t		wwn;
2570 
2571 	tgtmap = iport->iss_tgtmap;
2572 	ASSERT(tgtmap);
2573 
2574 	lphyp = phyp;
2575 	while (lphyp) {
2576 		switch (lphyp->dtype) {
2577 		default:		/* Skip unknown PHYs. */
2578 			/* for non-root phys, skip to sibling */
2579 			goto next_phy;
2580 
2581 		case SATA:
2582 		case SAS:
2583 			tgt_type = SCSI_TGT_SCSI_DEVICE;
2584 			break;
2585 
2586 		case EXPANDER:
2587 			tgt_type = SCSI_TGT_SMP_DEVICE;
2588 			break;
2589 		}
2590 
2591 		if (lphyp->dead) {
2592 			goto next_phy;
2593 		}
2594 
2595 		wwn = pmcs_barray2wwn(lphyp->sas_address);
2596 		ua = scsi_wwn_to_wwnstr(wwn, 1, NULL);
2597 
2598 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, lphyp, NULL,
2599 		    "iport_observation: adding %s on tgtmap [0x%p] phy [0x%p]",
2600 		    ua, (void *)tgtmap, (void*)lphyp);
2601 
2602 		if (scsi_hba_tgtmap_set_add(tgtmap, tgt_type, ua, NULL) !=
2603 		    DDI_SUCCESS) {
2604 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,  NULL, NULL,
2605 			    "%s: failed to add address %s", __func__, ua);
2606 			scsi_free_wwnstr(ua);
2607 			return (B_FALSE);
2608 		}
2609 		scsi_free_wwnstr(ua);
2610 
2611 		if (lphyp->children) {
2612 			if (pmcs_report_iport_observations(pwp, iport,
2613 			    lphyp->children) == B_FALSE) {
2614 				return (B_FALSE);
2615 			}
2616 		}
2617 
2618 		/* for non-root phys, report siblings too */
2619 next_phy:
2620 		if (IS_ROOT_PHY(lphyp)) {
2621 			lphyp = NULL;
2622 		} else {
2623 			lphyp = lphyp->sibling;
2624 		}
2625 	}
2626 
2627 	return (B_TRUE);
2628 }
2629 
2630 /*
2631  * Check for and configure new devices.
2632  *
2633  * If the changed device is a SATA device, add a SATA device.
2634  *
2635  * If the changed device is a SAS device, add a SAS device.
2636  *
2637  * If the changed device is an EXPANDER device, do a REPORT
2638  * GENERAL SMP command to find out the number of contained phys.
2639  *
2640  * For each number of contained phys, allocate a phy, do a
2641  * DISCOVERY SMP command to find out what kind of device it
2642  * is and add it to the linked list of phys on the *next* level.
2643  *
2644  * NOTE: pptr passed in by the caller will be a root PHY
2645  */
2646 static int
2647 pmcs_configure_new_devices(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2648 {
2649 	int rval = 0;
2650 	pmcs_iport_t *iport;
2651 	pmcs_phy_t *pnext, *orig_pptr = pptr, *root_phy, *pchild;
2652 
2653 	/*
2654 	 * First, walk through each PHY at this level
2655 	 */
2656 	while (pptr) {
2657 		pmcs_lock_phy(pptr);
2658 		pnext = pptr->sibling;
2659 
2660 		/*
2661 		 * Set the new dtype if it has changed
2662 		 */
2663 		if ((pptr->pend_dtype != NEW) &&
2664 		    (pptr->pend_dtype != pptr->dtype)) {
2665 			pptr->dtype = pptr->pend_dtype;
2666 		}
2667 
2668 		if (pptr->changed == 0 || pptr->dead || pptr->configured) {
2669 			goto next_phy;
2670 		}
2671 
2672 		/*
2673 		 * Confirm that this target's iport is configured
2674 		 */
2675 		root_phy = pmcs_get_root_phy(pptr);
2676 		iport = pmcs_get_iport_by_phy(pwp, root_phy);
2677 		if (iport == NULL) {
2678 			/* No iport for this tgt, restart */
2679 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2680 			    "%s: iport not yet configured, "
2681 			    "retry discovery", __func__);
2682 			pnext = NULL;
2683 			rval = -1;
2684 			goto next_phy;
2685 		}
2686 
2687 		switch (pptr->dtype) {
2688 		case NOTHING:
2689 			pptr->changed = 0;
2690 			break;
2691 		case SATA:
2692 		case SAS:
2693 			pptr->iport = iport;
2694 			pmcs_new_tport(pwp, pptr);
2695 			break;
2696 		case EXPANDER:
2697 			pmcs_configure_expander(pwp, pptr, iport);
2698 			break;
2699 		}
2700 		pmcs_rele_iport(iport);
2701 
2702 		mutex_enter(&pwp->config_lock);
2703 		if (pwp->config_changed) {
2704 			mutex_exit(&pwp->config_lock);
2705 			pnext = NULL;
2706 			goto next_phy;
2707 		}
2708 		mutex_exit(&pwp->config_lock);
2709 
2710 next_phy:
2711 		pmcs_unlock_phy(pptr);
2712 		pptr = pnext;
2713 	}
2714 
2715 	if (rval != 0) {
2716 		return (rval);
2717 	}
2718 
2719 	/*
2720 	 * Now walk through each PHY again, recalling ourselves if they
2721 	 * have children
2722 	 */
2723 	pptr = orig_pptr;
2724 	while (pptr) {
2725 		pmcs_lock_phy(pptr);
2726 		pnext = pptr->sibling;
2727 		pchild = pptr->children;
2728 		pmcs_unlock_phy(pptr);
2729 
2730 		if (pchild) {
2731 			rval = pmcs_configure_new_devices(pwp, pchild);
2732 			if (rval != 0) {
2733 				break;
2734 			}
2735 		}
2736 
2737 		pptr = pnext;
2738 	}
2739 
2740 	return (rval);
2741 }
2742 
2743 /*
2744  * Set all phys and descendent phys as changed if changed == B_TRUE, otherwise
2745  * mark them all as not changed.
2746  *
2747  * Called with parent PHY locked.
2748  */
2749 void
2750 pmcs_set_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, boolean_t changed,
2751     int level)
2752 {
2753 	pmcs_phy_t *pptr;
2754 
2755 	if (level == 0) {
2756 		if (changed) {
2757 			PHY_CHANGED(pwp, parent);
2758 		} else {
2759 			parent->changed = 0;
2760 		}
2761 		if (parent->dtype == EXPANDER && parent->level) {
2762 			parent->width = 1;
2763 		}
2764 		if (parent->children) {
2765 			pmcs_set_changed(pwp, parent->children, changed,
2766 			    level + 1);
2767 		}
2768 	} else {
2769 		pptr = parent;
2770 		while (pptr) {
2771 			if (changed) {
2772 				PHY_CHANGED(pwp, pptr);
2773 			} else {
2774 				pptr->changed = 0;
2775 			}
2776 			if (pptr->dtype == EXPANDER && pptr->level) {
2777 				pptr->width = 1;
2778 			}
2779 			if (pptr->children) {
2780 				pmcs_set_changed(pwp, pptr->children, changed,
2781 				    level + 1);
2782 			}
2783 			pptr = pptr->sibling;
2784 		}
2785 	}
2786 }
2787 
2788 /*
2789  * Take the passed phy mark it and its descendants as dead.
2790  * Fire up reconfiguration to abort commands and bury it.
2791  *
2792  * Called with the parent PHY locked.
2793  */
2794 void
2795 pmcs_kill_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, int level)
2796 {
2797 	pmcs_phy_t *pptr = parent;
2798 
2799 	while (pptr) {
2800 		pptr->link_rate = 0;
2801 		pptr->abort_sent = 0;
2802 		pptr->abort_pending = 1;
2803 		SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
2804 		pptr->need_rl_ext = 0;
2805 
2806 		if (pptr->dead == 0) {
2807 			PHY_CHANGED(pwp, pptr);
2808 			RESTART_DISCOVERY(pwp);
2809 		}
2810 
2811 		pptr->dead = 1;
2812 
2813 		if (pptr->children) {
2814 			pmcs_kill_changed(pwp, pptr->children, level + 1);
2815 		}
2816 
2817 		/*
2818 		 * Only kill siblings at level > 0
2819 		 */
2820 		if (level == 0) {
2821 			return;
2822 		}
2823 
2824 		pptr = pptr->sibling;
2825 	}
2826 }
2827 
2828 /*
2829  * Go through every PHY and clear any that are dead (unless they're expanders)
2830  */
2831 static void
2832 pmcs_clear_phys(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2833 {
2834 	pmcs_phy_t *pnext, *phyp;
2835 
2836 	phyp = pptr;
2837 	while (phyp) {
2838 		if (IS_ROOT_PHY(phyp)) {
2839 			pmcs_lock_phy(phyp);
2840 		}
2841 
2842 		if ((phyp->dtype != EXPANDER) && phyp->dead) {
2843 			pmcs_clear_phy(pwp, phyp);
2844 		}
2845 
2846 		if (phyp->children) {
2847 			pmcs_clear_phys(pwp, phyp->children);
2848 		}
2849 
2850 		pnext = phyp->sibling;
2851 
2852 		if (IS_ROOT_PHY(phyp)) {
2853 			pmcs_unlock_phy(phyp);
2854 		}
2855 
2856 		phyp = pnext;
2857 	}
2858 }
2859 
2860 /*
2861  * Clear volatile parts of a phy.  Called with PHY locked.
2862  */
2863 void
2864 pmcs_clear_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2865 {
2866 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: %s",
2867 	    __func__, pptr->path);
2868 	ASSERT(mutex_owned(&pptr->phy_lock));
2869 	/* keep sibling */
2870 	/* keep children */
2871 	/* keep parent */
2872 	pptr->device_id = PMCS_INVALID_DEVICE_ID;
2873 	/* keep hw_event_ack */
2874 	pptr->ncphy = 0;
2875 	/* keep phynum */
2876 	pptr->width = 0;
2877 	pptr->ds_recovery_retries = 0;
2878 	pptr->ds_prev_good_recoveries = 0;
2879 	pptr->last_good_recovery = 0;
2880 	pptr->prev_recovery = 0;
2881 	/* keep dtype */
2882 	pptr->config_stop = 0;
2883 	pptr->spinup_hold = 0;
2884 	pptr->atdt = 0;
2885 	/* keep portid */
2886 	pptr->link_rate = 0;
2887 	pptr->valid_device_id = 0;
2888 	pptr->abort_sent = 0;
2889 	pptr->abort_pending = 0;
2890 	pptr->need_rl_ext = 0;
2891 	pptr->subsidiary = 0;
2892 	pptr->configured = 0;
2893 	/* Only mark dead if it's not a root PHY and its dtype isn't NOTHING */
2894 	/* XXX: What about directly attached disks? */
2895 	if (!IS_ROOT_PHY(pptr) && (pptr->dtype != NOTHING))
2896 		pptr->dead = 1;
2897 	pptr->changed = 0;
2898 	/* keep SAS address */
2899 	/* keep path */
2900 	/* keep ref_count */
2901 	/* Don't clear iport on root PHYs - they are handled in pmcs_intr.c */
2902 	if (!IS_ROOT_PHY(pptr)) {
2903 		pptr->iport = NULL;
2904 	}
2905 	/* keep target */
2906 }
2907 
2908 /*
2909  * Allocate softstate for this target if there isn't already one.  If there
2910  * is, just redo our internal configuration.  If it is actually "new", we'll
2911  * soon get a tran_tgt_init for it.
2912  *
2913  * Called with PHY locked.
2914  */
2915 static void
2916 pmcs_new_tport(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2917 {
2918 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: phy 0x%p @ %s",
2919 	    __func__, (void *)pptr, pptr->path);
2920 
2921 	if (pmcs_configure_phy(pwp, pptr) == B_FALSE) {
2922 		/*
2923 		 * If the config failed, mark the PHY as changed.
2924 		 */
2925 		PHY_CHANGED(pwp, pptr);
2926 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
2927 		    "%s: pmcs_configure_phy failed for phy 0x%p", __func__,
2928 		    (void *)pptr);
2929 		return;
2930 	}
2931 
2932 	/* Mark PHY as no longer changed */
2933 	pptr->changed = 0;
2934 
2935 	/*
2936 	 * If the PHY has no target pointer, see if there's a dead PHY that
2937 	 * matches.
2938 	 */
2939 	if (pptr->target == NULL) {
2940 		pmcs_reap_dead_phy(pptr);
2941 	}
2942 
2943 	/*
2944 	 * Only assign the device if there is a target for this PHY with a
2945 	 * matching SAS address.  If an iport is disconnected from one piece
2946 	 * of storage and connected to another within the iport stabilization
2947 	 * time, we can get the PHY/target mismatch situation.
2948 	 *
2949 	 * Otherwise, it'll get done in tran_tgt_init.
2950 	 */
2951 	if (pptr->target) {
2952 		mutex_enter(&pptr->target->statlock);
2953 		if (pmcs_phy_target_match(pptr) == B_FALSE) {
2954 			mutex_exit(&pptr->target->statlock);
2955 			if (!IS_ROOT_PHY(pptr)) {
2956 				pmcs_dec_phy_ref_count(pptr);
2957 			}
2958 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
2959 			    "%s: Not assigning existing tgt %p for PHY %p "
2960 			    "(WWN mismatch)", __func__, (void *)pptr->target,
2961 			    (void *)pptr);
2962 			pptr->target = NULL;
2963 			return;
2964 		}
2965 
2966 		if (!pmcs_assign_device(pwp, pptr->target)) {
2967 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
2968 			    "%s: pmcs_assign_device failed for target 0x%p",
2969 			    __func__, (void *)pptr->target);
2970 		}
2971 		mutex_exit(&pptr->target->statlock);
2972 	}
2973 }
2974 
2975 /*
2976  * Called with PHY lock held.
2977  */
2978 static boolean_t
2979 pmcs_configure_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2980 {
2981 	char *dtype;
2982 
2983 	ASSERT(mutex_owned(&pptr->phy_lock));
2984 
2985 	/*
2986 	 * Mark this device as no longer changed.
2987 	 */
2988 	pptr->changed = 0;
2989 
2990 	/*
2991 	 * If we don't have a device handle, get one.
2992 	 */
2993 	if (pmcs_get_device_handle(pwp, pptr)) {
2994 		return (B_FALSE);
2995 	}
2996 
2997 	pptr->configured = 1;
2998 
2999 	switch (pptr->dtype) {
3000 	case SAS:
3001 		dtype = "SAS";
3002 		break;
3003 	case SATA:
3004 		dtype = "SATA";
3005 		break;
3006 	case EXPANDER:
3007 		dtype = "SMP";
3008 		break;
3009 	default:
3010 		dtype = "???";
3011 	}
3012 
3013 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "config_dev: %s "
3014 	    "dev %s " SAS_ADDR_FMT " dev id 0x%x lr 0x%x", dtype, pptr->path,
3015 	    SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
3016 
3017 	return (B_TRUE);
3018 }
3019 
3020 /*
3021  * Called with PHY locked
3022  */
3023 static void
3024 pmcs_configure_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, pmcs_iport_t *iport)
3025 {
3026 	pmcs_phy_t *ctmp, *clist = NULL, *cnext;
3027 	int result, i, nphy = 0;
3028 	boolean_t root_phy = B_FALSE;
3029 
3030 	ASSERT(iport);
3031 
3032 	/*
3033 	 * Step 1- clear our "changed" bit. If we need to retry/restart due
3034 	 * to resource shortages, we'll set it again. While we're doing
3035 	 * configuration, other events may set it again as well.  If the PHY
3036 	 * is a root PHY and is currently marked as having changed, reset the
3037 	 * config_stop timer as well.
3038 	 */
3039 	if (IS_ROOT_PHY(pptr) && pptr->changed) {
3040 		pptr->config_stop = ddi_get_lbolt() +
3041 		    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3042 	}
3043 	pptr->changed = 0;
3044 
3045 	/*
3046 	 * Step 2- make sure we don't overflow
3047 	 */
3048 	if (pptr->level == PMCS_MAX_XPND-1) {
3049 		pmcs_prt(pwp, PMCS_PRT_WARN, pptr, NULL,
3050 		    "%s: SAS expansion tree too deep", __func__);
3051 		return;
3052 	}
3053 
3054 	/*
3055 	 * Step 3- Check if this expander is part of a wide phy that has
3056 	 * already been configured.
3057 	 *
3058 	 * This is known by checking this level for another EXPANDER device
3059 	 * with the same SAS address and isn't already marked as a subsidiary
3060 	 * phy and a parent whose SAS address is the same as our SAS address
3061 	 * (if there are parents).
3062 	 */
3063 	if (!IS_ROOT_PHY(pptr)) {
3064 		/*
3065 		 * No need to lock the parent here because we're in discovery
3066 		 * and the only time a PHY's children pointer can change is
3067 		 * in discovery; either in pmcs_clear_expander (which has
3068 		 * already been called) or here, down below.  Plus, trying to
3069 		 * grab the parent's lock here can cause deadlock.
3070 		 */
3071 		ctmp = pptr->parent->children;
3072 	} else {
3073 		ctmp = pwp->root_phys;
3074 		root_phy = B_TRUE;
3075 	}
3076 
3077 	while (ctmp) {
3078 		/*
3079 		 * If we've checked all PHYs up to pptr, we stop. Otherwise,
3080 		 * we'll be checking for a primary PHY with a higher PHY
3081 		 * number than pptr, which will never happen.  The primary
3082 		 * PHY on non-root expanders will ALWAYS be the lowest
3083 		 * numbered PHY.
3084 		 */
3085 		if (ctmp == pptr) {
3086 			break;
3087 		}
3088 
3089 		/*
3090 		 * If pptr and ctmp are root PHYs, just grab the mutex on
3091 		 * ctmp.  No need to lock the entire tree.  If they are not
3092 		 * root PHYs, there is no need to lock since a non-root PHY's
3093 		 * SAS address and other characteristics can only change in
3094 		 * discovery anyway.
3095 		 */
3096 		if (root_phy) {
3097 			mutex_enter(&ctmp->phy_lock);
3098 		}
3099 
3100 		if (ctmp->dtype == EXPANDER && ctmp->width &&
3101 		    memcmp(ctmp->sas_address, pptr->sas_address, 8) == 0) {
3102 			int widephy = 0;
3103 			/*
3104 			 * If these phys are not root PHYs, compare their SAS
3105 			 * addresses too.
3106 			 */
3107 			if (!root_phy) {
3108 				if (memcmp(ctmp->parent->sas_address,
3109 				    pptr->parent->sas_address, 8) == 0) {
3110 					widephy = 1;
3111 				}
3112 			} else {
3113 				widephy = 1;
3114 			}
3115 			if (widephy) {
3116 				ctmp->width++;
3117 				pptr->subsidiary = 1;
3118 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3119 				    "%s: PHY %s part of wide PHY %s "
3120 				    "(now %d wide)", __func__, pptr->path,
3121 				    ctmp->path, ctmp->width);
3122 				if (root_phy) {
3123 					mutex_exit(&ctmp->phy_lock);
3124 				}
3125 				return;
3126 			}
3127 		}
3128 
3129 		cnext = ctmp->sibling;
3130 		if (root_phy) {
3131 			mutex_exit(&ctmp->phy_lock);
3132 		}
3133 		ctmp = cnext;
3134 	}
3135 
3136 	/*
3137 	 * Step 4- If we don't have a device handle, get one.  Since this
3138 	 * is the primary PHY, make sure subsidiary is cleared.
3139 	 */
3140 	pptr->subsidiary = 0;
3141 	if (pmcs_get_device_handle(pwp, pptr)) {
3142 		goto out;
3143 	}
3144 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "Config expander %s "
3145 	    SAS_ADDR_FMT " dev id 0x%x lr 0x%x", pptr->path,
3146 	    SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
3147 
3148 	/*
3149 	 * Step 5- figure out how many phys are in this expander.
3150 	 */
3151 	nphy = pmcs_expander_get_nphy(pwp, pptr);
3152 	if (nphy <= 0) {
3153 		if (nphy == 0 && ddi_get_lbolt() < pptr->config_stop) {
3154 			PHY_CHANGED(pwp, pptr);
3155 			RESTART_DISCOVERY(pwp);
3156 		} else {
3157 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3158 			    "%s: Retries exhausted for %s, killing", __func__,
3159 			    pptr->path);
3160 			pptr->config_stop = 0;
3161 			pmcs_kill_changed(pwp, pptr, 0);
3162 		}
3163 		goto out;
3164 	}
3165 
3166 	/*
3167 	 * Step 6- Allocate a list of phys for this expander and figure out
3168 	 * what each one is.
3169 	 */
3170 	for (i = 0; i < nphy; i++) {
3171 		ctmp = kmem_cache_alloc(pwp->phy_cache, KM_SLEEP);
3172 		bzero(ctmp, sizeof (pmcs_phy_t));
3173 		ctmp->device_id = PMCS_INVALID_DEVICE_ID;
3174 		ctmp->sibling = clist;
3175 		ctmp->pend_dtype = NEW;	/* Init pending dtype */
3176 		ctmp->config_stop = ddi_get_lbolt() +
3177 		    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3178 		clist = ctmp;
3179 	}
3180 
3181 	mutex_enter(&pwp->config_lock);
3182 	if (pwp->config_changed) {
3183 		RESTART_DISCOVERY_LOCKED(pwp);
3184 		mutex_exit(&pwp->config_lock);
3185 		/*
3186 		 * Clean up the newly allocated PHYs and return
3187 		 */
3188 		while (clist) {
3189 			ctmp = clist->sibling;
3190 			kmem_cache_free(pwp->phy_cache, clist);
3191 			clist = ctmp;
3192 		}
3193 		return;
3194 	}
3195 	mutex_exit(&pwp->config_lock);
3196 
3197 	/*
3198 	 * Step 7- Now fill in the rest of the static portions of the phy.
3199 	 */
3200 	for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
3201 		ctmp->parent = pptr;
3202 		ctmp->pwp = pwp;
3203 		ctmp->level = pptr->level+1;
3204 		ctmp->portid = pptr->portid;
3205 		if (ctmp->tolerates_sas2) {
3206 			ASSERT(i < SAS2_PHYNUM_MAX);
3207 			ctmp->phynum = i & SAS2_PHYNUM_MASK;
3208 		} else {
3209 			ASSERT(i < SAS_PHYNUM_MAX);
3210 			ctmp->phynum = i & SAS_PHYNUM_MASK;
3211 		}
3212 		pmcs_phy_name(pwp, ctmp, ctmp->path, sizeof (ctmp->path));
3213 		pmcs_lock_phy(ctmp);
3214 	}
3215 
3216 	/*
3217 	 * Step 8- Discover things about each phy in the expander.
3218 	 */
3219 	for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
3220 		result = pmcs_expander_content_discover(pwp, pptr, ctmp);
3221 		if (result <= 0) {
3222 			if (ddi_get_lbolt() < pptr->config_stop) {
3223 				PHY_CHANGED(pwp, pptr);
3224 				RESTART_DISCOVERY(pwp);
3225 			} else {
3226 				pptr->config_stop = 0;
3227 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3228 				    "%s: Retries exhausted for %s, killing",
3229 				    __func__, pptr->path);
3230 				pmcs_kill_changed(pwp, pptr, 0);
3231 			}
3232 			goto out;
3233 		}
3234 
3235 		/* Set pend_dtype to dtype for 1st time initialization */
3236 		ctmp->pend_dtype = ctmp->dtype;
3237 	}
3238 
3239 	/*
3240 	 * Step 9- Install the new list on the next level. There should be
3241 	 * no children pointer on this PHY.  If there is, we'd need to know
3242 	 * how it happened (The expander suddenly got more PHYs?).
3243 	 */
3244 	ASSERT(pptr->children == NULL);
3245 	if (pptr->children != NULL) {
3246 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: Already child "
3247 		    "PHYs attached  to PHY %s: This should never happen",
3248 		    __func__, pptr->path);
3249 		goto out;
3250 	} else {
3251 		pptr->children = clist;
3252 	}
3253 
3254 	clist = NULL;
3255 	pptr->ncphy = nphy;
3256 	pptr->configured = 1;
3257 
3258 	/*
3259 	 * We only set width if we're greater than level 0.
3260 	 */
3261 	if (pptr->level) {
3262 		pptr->width = 1;
3263 	}
3264 
3265 	/*
3266 	 * Now tell the rest of the world about us, as an SMP node.
3267 	 */
3268 	pptr->iport = iport;
3269 	pmcs_new_tport(pwp, pptr);
3270 
3271 out:
3272 	while (clist) {
3273 		ctmp = clist->sibling;
3274 		pmcs_unlock_phy(clist);
3275 		kmem_cache_free(pwp->phy_cache, clist);
3276 		clist = ctmp;
3277 	}
3278 }
3279 
3280 /*
3281  * 2. Check expanders marked changed (but not dead) to see if they still have
3282  * the same number of phys and the same SAS address. Mark them, their subsidiary
3283  * phys (if wide) and their descendents dead if anything has changed. Check the
3284  * the devices they contain to see if *they* have changed. If they've changed
3285  * from type NOTHING we leave them marked changed to be configured later
3286  * (picking up a new SAS address and link rate if possible). Otherwise, any
3287  * change in type, SAS address or removal of target role will cause us to
3288  * mark them (and their descendents) as dead and cause any pending commands
3289  * and associated devices to be removed.
3290  *
3291  * Called with PHY (pptr) locked.
3292  */
3293 
3294 static void
3295 pmcs_check_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3296 {
3297 	int nphy, result;
3298 	pmcs_phy_t *ctmp, *local, *local_list = NULL, *local_tail = NULL;
3299 	boolean_t kill_changed, changed;
3300 
3301 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3302 	    "%s: check %s", __func__, pptr->path);
3303 
3304 	/*
3305 	 * Step 1: Mark phy as not changed. We will mark it changed if we need
3306 	 * to retry.
3307 	 */
3308 	pptr->changed = 0;
3309 
3310 	/*
3311 	 * Reset the config_stop time. Although we're not actually configuring
3312 	 * anything here, we do want some indication of when to give up trying
3313 	 * if we can't communicate with the expander.
3314 	 */
3315 	pptr->config_stop = ddi_get_lbolt() +
3316 	    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3317 
3318 	/*
3319 	 * Step 2: Figure out how many phys are in this expander. If
3320 	 * pmcs_expander_get_nphy returns 0 we ran out of resources,
3321 	 * so reschedule and try later. If it returns another error,
3322 	 * just return.
3323 	 */
3324 	nphy = pmcs_expander_get_nphy(pwp, pptr);
3325 	if (nphy <= 0) {
3326 		if ((nphy == 0) && (ddi_get_lbolt() < pptr->config_stop)) {
3327 			PHY_CHANGED(pwp, pptr);
3328 			RESTART_DISCOVERY(pwp);
3329 		} else {
3330 			pptr->config_stop = 0;
3331 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3332 			    "%s: Retries exhausted for %s, killing", __func__,
3333 			    pptr->path);
3334 			pmcs_kill_changed(pwp, pptr, 0);
3335 		}
3336 		return;
3337 	}
3338 
3339 	/*
3340 	 * Step 3: If the number of phys don't agree, kill the old sub-tree.
3341 	 */
3342 	if (nphy != pptr->ncphy) {
3343 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3344 		    "%s: number of contained phys for %s changed from %d to %d",
3345 		    __func__, pptr->path, pptr->ncphy, nphy);
3346 		/*
3347 		 * Force a rescan of this expander after dead contents
3348 		 * are cleared and removed.
3349 		 */
3350 		pmcs_kill_changed(pwp, pptr, 0);
3351 		return;
3352 	}
3353 
3354 	/*
3355 	 * Step 4: if we're at the bottom of the stack, we're done
3356 	 * (we can't have any levels below us)
3357 	 */
3358 	if (pptr->level == PMCS_MAX_XPND-1) {
3359 		return;
3360 	}
3361 
3362 	/*
3363 	 * Step 5: Discover things about each phy in this expander.  We do
3364 	 * this by walking the current list of contained phys and doing a
3365 	 * content discovery for it to a local phy.
3366 	 */
3367 	ctmp = pptr->children;
3368 	ASSERT(ctmp);
3369 	if (ctmp == NULL) {
3370 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3371 		    "%s: No children attached to expander @ %s?", __func__,
3372 		    pptr->path);
3373 		return;
3374 	}
3375 
3376 	while (ctmp) {
3377 		/*
3378 		 * Allocate a local PHY to contain the proposed new contents
3379 		 * and link it to the rest of the local PHYs so that they
3380 		 * can all be freed later.
3381 		 */
3382 		local = pmcs_clone_phy(ctmp);
3383 
3384 		if (local_list == NULL) {
3385 			local_list = local;
3386 			local_tail = local;
3387 		} else {
3388 			local_tail->sibling = local;
3389 			local_tail = local;
3390 		}
3391 
3392 		/*
3393 		 * Need to lock the local PHY since pmcs_expander_content_
3394 		 * discovery may call pmcs_clear_phy on it, which expects
3395 		 * the PHY to be locked.
3396 		 */
3397 		pmcs_lock_phy(local);
3398 		result = pmcs_expander_content_discover(pwp, pptr, local);
3399 		pmcs_unlock_phy(local);
3400 		if (result <= 0) {
3401 			if (ddi_get_lbolt() < pptr->config_stop) {
3402 				PHY_CHANGED(pwp, pptr);
3403 				RESTART_DISCOVERY(pwp);
3404 			} else {
3405 				pptr->config_stop = 0;
3406 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3407 				    "%s: Retries exhausted for %s, killing",
3408 				    __func__, pptr->path);
3409 				pmcs_kill_changed(pwp, pptr, 0);
3410 			}
3411 
3412 			/*
3413 			 * Release all the local PHYs that we allocated.
3414 			 */
3415 			pmcs_free_phys(pwp, local_list);
3416 			return;
3417 		}
3418 
3419 		ctmp = ctmp->sibling;
3420 	}
3421 
3422 	/*
3423 	 * Step 6: Compare the local PHY's contents to our current PHY.  If
3424 	 * there are changes, take the appropriate action.
3425 	 * This is done in two steps (step 5 above, and 6 here) so that if we
3426 	 * have to bail during this process (e.g. pmcs_expander_content_discover
3427 	 * fails), we haven't actually changed the state of any of the real
3428 	 * PHYs.  Next time we come through here, we'll be starting over from
3429 	 * scratch.  This keeps us from marking a changed PHY as no longer
3430 	 * changed, but then having to bail only to come back next time and
3431 	 * think that the PHY hadn't changed.  If this were to happen, we
3432 	 * would fail to properly configure the device behind this PHY.
3433 	 */
3434 	local = local_list;
3435 	ctmp = pptr->children;
3436 
3437 	while (ctmp) {
3438 		changed = B_FALSE;
3439 		kill_changed = B_FALSE;
3440 
3441 		/*
3442 		 * We set local to local_list prior to this loop so that we
3443 		 * can simply walk the local_list while we walk this list.  The
3444 		 * two lists should be completely in sync.
3445 		 *
3446 		 * Clear the changed flag here.
3447 		 */
3448 		ctmp->changed = 0;
3449 
3450 		if (ctmp->dtype != local->dtype) {
3451 			if (ctmp->dtype != NOTHING) {
3452 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3453 				    "%s: %s type changed from %s to %s "
3454 				    "(killing)", __func__, ctmp->path,
3455 				    PHY_TYPE(ctmp), PHY_TYPE(local));
3456 				/*
3457 				 * Force a rescan of this expander after dead
3458 				 * contents are cleared and removed.
3459 				 */
3460 				changed = B_TRUE;
3461 				kill_changed = B_TRUE;
3462 			} else {
3463 				changed = B_TRUE;
3464 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3465 				    "%s: %s type changed from NOTHING to %s",
3466 				    __func__, ctmp->path, PHY_TYPE(local));
3467 			}
3468 
3469 		} else if (ctmp->atdt != local->atdt) {
3470 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL, "%s: "
3471 			    "%s attached device type changed from %d to %d "
3472 			    "(killing)", __func__, ctmp->path, ctmp->atdt,
3473 			    local->atdt);
3474 			/*
3475 			 * Force a rescan of this expander after dead
3476 			 * contents are cleared and removed.
3477 			 */
3478 			changed = B_TRUE;
3479 
3480 			if (local->atdt == 0) {
3481 				kill_changed = B_TRUE;
3482 			}
3483 		} else if (ctmp->link_rate != local->link_rate) {
3484 			pmcs_prt(pwp, PMCS_PRT_INFO, ctmp, NULL, "%s: %s "
3485 			    "changed speed from %s to %s", __func__, ctmp->path,
3486 			    pmcs_get_rate(ctmp->link_rate),
3487 			    pmcs_get_rate(local->link_rate));
3488 			/* If the speed changed from invalid, force rescan */
3489 			if (!PMCS_VALID_LINK_RATE(ctmp->link_rate)) {
3490 				changed = B_TRUE;
3491 				RESTART_DISCOVERY(pwp);
3492 			} else {
3493 				/* Just update to the new link rate */
3494 				ctmp->link_rate = local->link_rate;
3495 			}
3496 
3497 			if (!PMCS_VALID_LINK_RATE(local->link_rate)) {
3498 				kill_changed = B_TRUE;
3499 			}
3500 		} else if (memcmp(ctmp->sas_address, local->sas_address,
3501 		    sizeof (ctmp->sas_address)) != 0) {
3502 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3503 			    "%s: SAS Addr for %s changed from " SAS_ADDR_FMT
3504 			    "to " SAS_ADDR_FMT " (kill old tree)", __func__,
3505 			    ctmp->path, SAS_ADDR_PRT(ctmp->sas_address),
3506 			    SAS_ADDR_PRT(local->sas_address));
3507 			/*
3508 			 * Force a rescan of this expander after dead
3509 			 * contents are cleared and removed.
3510 			 */
3511 			changed = B_TRUE;
3512 		} else {
3513 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3514 			    "%s: %s looks the same (type %s)",
3515 			    __func__, ctmp->path, PHY_TYPE(ctmp));
3516 			/*
3517 			 * If EXPANDER, still mark it changed so we
3518 			 * re-evaluate its contents.  If it's not an expander,
3519 			 * but it hasn't been configured, also mark it as
3520 			 * changed so that it will undergo configuration.
3521 			 */
3522 			if (ctmp->dtype == EXPANDER) {
3523 				changed = B_TRUE;
3524 			} else if ((ctmp->dtype != NOTHING) &&
3525 			    !ctmp->configured) {
3526 				ctmp->changed = 1;
3527 			} else {
3528 				/* It simply hasn't changed */
3529 				ctmp->changed = 0;
3530 			}
3531 		}
3532 
3533 		/*
3534 		 * If the PHY changed, call pmcs_kill_changed if indicated,
3535 		 * update its contents to reflect its current state and mark it
3536 		 * as changed.
3537 		 */
3538 		if (changed) {
3539 			/*
3540 			 * pmcs_kill_changed will mark the PHY as changed, so
3541 			 * only do PHY_CHANGED if we did not do kill_changed.
3542 			 */
3543 			if (kill_changed) {
3544 				pmcs_kill_changed(pwp, ctmp, 0);
3545 			} else {
3546 				/*
3547 				 * If we're not killing the device, it's not
3548 				 * dead.  Mark the PHY as changed.
3549 				 */
3550 				PHY_CHANGED(pwp, ctmp);
3551 
3552 				if (ctmp->dead) {
3553 					pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
3554 					    ctmp, NULL, "%s: Unmarking PHY %s "
3555 					    "dead, restarting discovery",
3556 					    __func__, ctmp->path);
3557 					ctmp->dead = 0;
3558 					RESTART_DISCOVERY(pwp);
3559 				}
3560 			}
3561 
3562 			/*
3563 			 * If the dtype of this PHY is now NOTHING, mark it as
3564 			 * unconfigured.  Set pend_dtype to what the new dtype
3565 			 * is.  It'll get updated at the end of the discovery
3566 			 * process.
3567 			 */
3568 			if (local->dtype == NOTHING) {
3569 				bzero(ctmp->sas_address,
3570 				    sizeof (local->sas_address));
3571 				ctmp->atdt = 0;
3572 				ctmp->link_rate = 0;
3573 				ctmp->pend_dtype = NOTHING;
3574 				ctmp->configured = 0;
3575 			} else {
3576 				(void) memcpy(ctmp->sas_address,
3577 				    local->sas_address,
3578 				    sizeof (local->sas_address));
3579 				ctmp->atdt = local->atdt;
3580 				ctmp->link_rate = local->link_rate;
3581 				ctmp->pend_dtype = local->dtype;
3582 			}
3583 		}
3584 
3585 		local = local->sibling;
3586 		ctmp = ctmp->sibling;
3587 	}
3588 
3589 	/*
3590 	 * If we got to here, that means we were able to see all the PHYs
3591 	 * and we can now update all of the real PHYs with the information
3592 	 * we got on the local PHYs.  Once that's done, free all the local
3593 	 * PHYs.
3594 	 */
3595 
3596 	pmcs_free_phys(pwp, local_list);
3597 }
3598 
3599 /*
3600  * Top level routine to check expanders.  We call pmcs_check_expander for
3601  * each expander.  Since we're not doing any configuration right now, it
3602  * doesn't matter if this is breadth-first.
3603  */
3604 static boolean_t
3605 pmcs_check_expanders(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3606 {
3607 	pmcs_phy_t *phyp, *pnext, *pchild;
3608 	boolean_t config_changed = B_FALSE;
3609 
3610 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3611 	    "%s: %s", __func__, pptr->path);
3612 
3613 	/*
3614 	 * Check each expander at this level
3615 	 */
3616 	phyp = pptr;
3617 	while (phyp && !config_changed) {
3618 		pmcs_lock_phy(phyp);
3619 
3620 		if ((phyp->dtype == EXPANDER) && phyp->changed &&
3621 		    !phyp->dead && !phyp->subsidiary &&
3622 		    phyp->configured) {
3623 			pmcs_check_expander(pwp, phyp);
3624 		}
3625 
3626 		pnext = phyp->sibling;
3627 		pmcs_unlock_phy(phyp);
3628 
3629 		mutex_enter(&pwp->config_lock);
3630 		config_changed = pwp->config_changed;
3631 		mutex_exit(&pwp->config_lock);
3632 
3633 		phyp = pnext;
3634 	}
3635 
3636 	if (config_changed) {
3637 		return (config_changed);
3638 	}
3639 
3640 	/*
3641 	 * Now check the children
3642 	 */
3643 	phyp = pptr;
3644 	while (phyp && !config_changed) {
3645 		pmcs_lock_phy(phyp);
3646 		pnext = phyp->sibling;
3647 		pchild = phyp->children;
3648 		pmcs_unlock_phy(phyp);
3649 
3650 		if (pchild) {
3651 			(void) pmcs_check_expanders(pwp, pchild);
3652 		}
3653 
3654 		mutex_enter(&pwp->config_lock);
3655 		config_changed = pwp->config_changed;
3656 		mutex_exit(&pwp->config_lock);
3657 
3658 		phyp = pnext;
3659 	}
3660 
3661 	/*
3662 	 * We're done
3663 	 */
3664 	return (config_changed);
3665 }
3666 
3667 /*
3668  * Called with softstate and PHY locked
3669  */
3670 static void
3671 pmcs_clear_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, int level)
3672 {
3673 	pmcs_phy_t *ctmp;
3674 
3675 	ASSERT(mutex_owned(&pwp->lock));
3676 	ASSERT(mutex_owned(&pptr->phy_lock));
3677 	ASSERT(pptr->level < PMCS_MAX_XPND - 1);
3678 
3679 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3680 	    "%s: checking %s", __func__, pptr->path);
3681 
3682 	ctmp = pptr->children;
3683 	while (ctmp) {
3684 		/*
3685 		 * If the expander is dead, mark its children dead
3686 		 */
3687 		if (pptr->dead) {
3688 			ctmp->dead = 1;
3689 		}
3690 		if (ctmp->dtype == EXPANDER) {
3691 			pmcs_clear_expander(pwp, ctmp, level + 1);
3692 		}
3693 		ctmp = ctmp->sibling;
3694 	}
3695 
3696 	/*
3697 	 * If this expander is not dead, we're done here.
3698 	 */
3699 	if (!pptr->dead) {
3700 		return;
3701 	}
3702 
3703 	/*
3704 	 * Now snip out the list of children below us and release them
3705 	 */
3706 	ctmp = pptr->children;
3707 	while (ctmp) {
3708 		pmcs_phy_t *nxt = ctmp->sibling;
3709 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3710 		    "%s: dead PHY 0x%p (%s) (ref_count %d)", __func__,
3711 		    (void *)ctmp, ctmp->path, ctmp->ref_count);
3712 		/*
3713 		 * Put this PHY on the dead PHY list for the watchdog to
3714 		 * clean up after any outstanding work has completed.
3715 		 */
3716 		mutex_enter(&pwp->dead_phylist_lock);
3717 		ctmp->dead_next = pwp->dead_phys;
3718 		pwp->dead_phys = ctmp;
3719 		mutex_exit(&pwp->dead_phylist_lock);
3720 		pmcs_unlock_phy(ctmp);
3721 		ctmp = nxt;
3722 	}
3723 
3724 	pptr->children = NULL;
3725 
3726 	/*
3727 	 * Clear subsidiary phys as well.  Getting the parent's PHY lock
3728 	 * is only necessary if level == 0 since otherwise the parent is
3729 	 * already locked.
3730 	 */
3731 	if (!IS_ROOT_PHY(pptr)) {
3732 		if (level == 0) {
3733 			mutex_enter(&pptr->parent->phy_lock);
3734 		}
3735 		ctmp = pptr->parent->children;
3736 		if (level == 0) {
3737 			mutex_exit(&pptr->parent->phy_lock);
3738 		}
3739 	} else {
3740 		ctmp = pwp->root_phys;
3741 	}
3742 
3743 	while (ctmp) {
3744 		if (ctmp == pptr) {
3745 			ctmp = ctmp->sibling;
3746 			continue;
3747 		}
3748 		/*
3749 		 * We only need to lock subsidiary PHYs on the level 0
3750 		 * expander.  Any children of that expander, subsidiaries or
3751 		 * not, will already be locked.
3752 		 */
3753 		if (level == 0) {
3754 			pmcs_lock_phy(ctmp);
3755 		}
3756 		if (ctmp->dtype != EXPANDER || ctmp->subsidiary == 0 ||
3757 		    memcmp(ctmp->sas_address, pptr->sas_address,
3758 		    sizeof (ctmp->sas_address)) != 0) {
3759 			if (level == 0) {
3760 				pmcs_unlock_phy(ctmp);
3761 			}
3762 			ctmp = ctmp->sibling;
3763 			continue;
3764 		}
3765 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3766 		    "%s: subsidiary %s", __func__, ctmp->path);
3767 		pmcs_clear_phy(pwp, ctmp);
3768 		if (level == 0) {
3769 			pmcs_unlock_phy(ctmp);
3770 		}
3771 		ctmp = ctmp->sibling;
3772 	}
3773 
3774 	pmcs_clear_phy(pwp, pptr);
3775 }
3776 
3777 /*
3778  * Called with PHY locked and with scratch acquired. We return 0 if
3779  * we fail to allocate resources or notice that the configuration
3780  * count changed while we were running the command. We return
3781  * less than zero if we had an I/O error or received an unsupported
3782  * configuration. Otherwise we return the number of phys in the
3783  * expander.
3784  */
3785 #define	DFM(m, y) if (m == NULL) m = y
3786 static int
3787 pmcs_expander_get_nphy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3788 {
3789 	struct pmcwork *pwrk;
3790 	char buf[64];
3791 	const uint_t rdoff = 0x100;	/* returned data offset */
3792 	smp_response_frame_t *srf;
3793 	smp_report_general_resp_t *srgr;
3794 	uint32_t msg[PMCS_MSG_SIZE], *ptr, htag, status, ival;
3795 	int result;
3796 
3797 	ival = 0x40001100;
3798 again:
3799 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
3800 	if (pwrk == NULL) {
3801 		result = 0;
3802 		goto out;
3803 	}
3804 	(void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
3805 	pwrk->arg = pwp->scratch;
3806 	pwrk->dtype = pptr->dtype;
3807 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
3808 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
3809 	if (ptr == NULL) {
3810 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
3811 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, NULL,
3812 		    "%s: GET_IQ_ENTRY failed", __func__);
3813 		pmcs_pwork(pwp, pwrk);
3814 		result = 0;
3815 		goto out;
3816 	}
3817 
3818 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
3819 	msg[1] = LE_32(pwrk->htag);
3820 	msg[2] = LE_32(pptr->device_id);
3821 	msg[3] = LE_32((4 << SMP_REQUEST_LENGTH_SHIFT) | SMP_INDIRECT_RESPONSE);
3822 	/*
3823 	 * Send SMP REPORT GENERAL (of either SAS1.1 or SAS2 flavors).
3824 	 */
3825 	msg[4] = BE_32(ival);
3826 	msg[5] = 0;
3827 	msg[6] = 0;
3828 	msg[7] = 0;
3829 	msg[8] = 0;
3830 	msg[9] = 0;
3831 	msg[10] = 0;
3832 	msg[11] = 0;
3833 	msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
3834 	msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
3835 	msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
3836 	msg[15] = 0;
3837 
3838 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
3839 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
3840 	htag = pwrk->htag;
3841 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
3842 
3843 	pmcs_unlock_phy(pptr);
3844 	WAIT_FOR(pwrk, 1000, result);
3845 	pmcs_lock_phy(pptr);
3846 	pmcs_pwork(pwp, pwrk);
3847 
3848 	mutex_enter(&pwp->config_lock);
3849 	if (pwp->config_changed) {
3850 		RESTART_DISCOVERY_LOCKED(pwp);
3851 		mutex_exit(&pwp->config_lock);
3852 		result = 0;
3853 		goto out;
3854 	}
3855 	mutex_exit(&pwp->config_lock);
3856 
3857 	if (result) {
3858 		pmcs_timed_out(pwp, htag, __func__);
3859 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3860 		    "%s: Issuing SMP ABORT for htag 0x%08x", __func__, htag);
3861 		if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
3862 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3863 			    "%s: Unable to issue SMP ABORT for htag 0x%08x",
3864 			    __func__, htag);
3865 		} else {
3866 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3867 			    "%s: Issuing SMP ABORT for htag 0x%08x",
3868 			    __func__, htag);
3869 		}
3870 		result = 0;
3871 		goto out;
3872 	}
3873 	ptr = (void *)pwp->scratch;
3874 	status = LE_32(ptr[2]);
3875 	if (status == PMCOUT_STATUS_UNDERFLOW ||
3876 	    status == PMCOUT_STATUS_OVERFLOW) {
3877 		pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW, pptr, NULL,
3878 		    "%s: over/underflow", __func__);
3879 		status = PMCOUT_STATUS_OK;
3880 	}
3881 	srf = (smp_response_frame_t *)&((uint32_t *)pwp->scratch)[rdoff >> 2];
3882 	srgr = (smp_report_general_resp_t *)
3883 	    &((uint32_t *)pwp->scratch)[(rdoff >> 2)+1];
3884 
3885 	if (status != PMCOUT_STATUS_OK) {
3886 		char *nag = NULL;
3887 		(void) snprintf(buf, sizeof (buf),
3888 		    "%s: SMP op failed (0x%x)", __func__, status);
3889 		switch (status) {
3890 		case PMCOUT_STATUS_IO_PORT_IN_RESET:
3891 			DFM(nag, "I/O Port In Reset");
3892 			/* FALLTHROUGH */
3893 		case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
3894 			DFM(nag, "Hardware Timeout");
3895 			/* FALLTHROUGH */
3896 		case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
3897 			DFM(nag, "Internal SMP Resource Failure");
3898 			/* FALLTHROUGH */
3899 		case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
3900 			DFM(nag, "PHY Not Ready");
3901 			/* FALLTHROUGH */
3902 		case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
3903 			DFM(nag, "Connection Rate Not Supported");
3904 			/* FALLTHROUGH */
3905 		case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
3906 			DFM(nag, "Open Retry Timeout");
3907 			/* FALLTHROUGH */
3908 		case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
3909 			DFM(nag, "Response Connection Error");
3910 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3911 			    "%s: expander %s SMP operation failed (%s)",
3912 			    __func__, pptr->path, nag);
3913 			break;
3914 
3915 		/*
3916 		 * For the IO_DS_NON_OPERATIONAL case, we need to kick off
3917 		 * device state recovery and return 0 so that the caller
3918 		 * doesn't assume this expander is dead for good.
3919 		 */
3920 		case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL: {
3921 			pmcs_xscsi_t *xp = pptr->target;
3922 
3923 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, xp,
3924 			    "%s: expander %s device state non-operational",
3925 			    __func__, pptr->path);
3926 
3927 			if (xp == NULL) {
3928 				pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr,
3929 				    xp, "%s: No target to do DS recovery for "
3930 				    "PHY %p (%s), attempting PHY hard reset",
3931 				    __func__, (void *)pptr, pptr->path);
3932 				(void) pmcs_reset_phy(pwp, pptr,
3933 				    PMCS_PHYOP_HARD_RESET);
3934 				break;
3935 			}
3936 
3937 			mutex_enter(&xp->statlock);
3938 			pmcs_start_dev_state_recovery(xp, pptr);
3939 			mutex_exit(&xp->statlock);
3940 			break;
3941 		}
3942 
3943 		default:
3944 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
3945 			result = -EIO;
3946 			break;
3947 		}
3948 	} else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
3949 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3950 		    "%s: bad response frame type 0x%x",
3951 		    __func__, srf->srf_frame_type);
3952 		result = -EINVAL;
3953 	} else if (srf->srf_function != SMP_FUNC_REPORT_GENERAL) {
3954 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3955 		    "%s: bad response function 0x%x",
3956 		    __func__, srf->srf_function);
3957 		result = -EINVAL;
3958 	} else if (srf->srf_result != 0) {
3959 		/*
3960 		 * Check to see if we have a value of 3 for failure and
3961 		 * whether we were using a SAS2.0 allocation length value
3962 		 * and retry without it.
3963 		 */
3964 		if (srf->srf_result == 3 && (ival & 0xff00)) {
3965 			ival &= ~0xff00;
3966 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3967 			    "%s: err 0x%x with SAS2 request- retry with SAS1",
3968 			    __func__, srf->srf_result);
3969 			goto again;
3970 		}
3971 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3972 		    "%s: bad response 0x%x", __func__, srf->srf_result);
3973 		result = -EINVAL;
3974 	} else if (srgr->srgr_configuring) {
3975 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3976 		    "%s: expander at phy %s is still configuring",
3977 		    __func__, pptr->path);
3978 		result = 0;
3979 	} else {
3980 		result = srgr->srgr_number_of_phys;
3981 		if (ival & 0xff00) {
3982 			pptr->tolerates_sas2 = 1;
3983 		}
3984 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3985 		    "%s has %d phys and %s SAS2", pptr->path, result,
3986 		    pptr->tolerates_sas2? "tolerates" : "does not tolerate");
3987 	}
3988 out:
3989 	return (result);
3990 }
3991 
3992 /*
3993  * Called with expander locked (and thus, pptr) as well as all PHYs up to
3994  * the root, and scratch acquired. Return 0 if we fail to allocate resources
3995  * or notice that the configuration changed while we were running the command.
3996  *
3997  * We return less than zero if we had an I/O error or received an
3998  * unsupported configuration.
3999  */
4000 static int
4001 pmcs_expander_content_discover(pmcs_hw_t *pwp, pmcs_phy_t *expander,
4002     pmcs_phy_t *pptr)
4003 {
4004 	struct pmcwork *pwrk;
4005 	char buf[64];
4006 	uint8_t sas_address[8];
4007 	uint8_t att_sas_address[8];
4008 	smp_response_frame_t *srf;
4009 	smp_discover_resp_t *sdr;
4010 	const uint_t rdoff = 0x100;	/* returned data offset */
4011 	uint8_t *roff;
4012 	uint32_t status, *ptr, msg[PMCS_MSG_SIZE], htag;
4013 	int result;
4014 	uint8_t	ini_support;
4015 	uint8_t	tgt_support;
4016 
4017 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, expander);
4018 	if (pwrk == NULL) {
4019 		result = 0;
4020 		goto out;
4021 	}
4022 	(void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
4023 	pwrk->arg = pwp->scratch;
4024 	pwrk->dtype = expander->dtype;
4025 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4026 	msg[1] = LE_32(pwrk->htag);
4027 	msg[2] = LE_32(expander->device_id);
4028 	msg[3] = LE_32((12 << SMP_REQUEST_LENGTH_SHIFT) |
4029 	    SMP_INDIRECT_RESPONSE);
4030 	/*
4031 	 * Send SMP DISCOVER (of either SAS1.1 or SAS2 flavors).
4032 	 */
4033 	if (expander->tolerates_sas2) {
4034 		msg[4] = BE_32(0x40101B00);
4035 	} else {
4036 		msg[4] = BE_32(0x40100000);
4037 	}
4038 	msg[5] = 0;
4039 	msg[6] = BE_32((pptr->phynum << 16));
4040 	msg[7] = 0;
4041 	msg[8] = 0;
4042 	msg[9] = 0;
4043 	msg[10] = 0;
4044 	msg[11] = 0;
4045 	msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
4046 	msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
4047 	msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
4048 	msg[15] = 0;
4049 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4050 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4051 	if (ptr == NULL) {
4052 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4053 		result = 0;
4054 		goto out;
4055 	}
4056 
4057 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4058 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4059 	htag = pwrk->htag;
4060 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4061 
4062 	/*
4063 	 * Drop PHY lock while waiting so other completions aren't potentially
4064 	 * blocked.
4065 	 */
4066 	pmcs_unlock_phy(expander);
4067 	WAIT_FOR(pwrk, 1000, result);
4068 	pmcs_lock_phy(expander);
4069 	pmcs_pwork(pwp, pwrk);
4070 
4071 	mutex_enter(&pwp->config_lock);
4072 	if (pwp->config_changed) {
4073 		RESTART_DISCOVERY_LOCKED(pwp);
4074 		mutex_exit(&pwp->config_lock);
4075 		result = 0;
4076 		goto out;
4077 	}
4078 	mutex_exit(&pwp->config_lock);
4079 
4080 	if (result) {
4081 		pmcs_prt(pwp, PMCS_PRT_WARN, pptr, NULL, pmcs_timeo, __func__);
4082 		if (pmcs_abort(pwp, expander, htag, 0, 0)) {
4083 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4084 			    "%s: Unable to issue SMP ABORT for htag 0x%08x",
4085 			    __func__, htag);
4086 		} else {
4087 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4088 			    "%s: Issuing SMP ABORT for htag 0x%08x",
4089 			    __func__, htag);
4090 		}
4091 		result = -ETIMEDOUT;
4092 		goto out;
4093 	}
4094 	ptr = (void *)pwp->scratch;
4095 	/*
4096 	 * Point roff to the DMA offset for returned data
4097 	 */
4098 	roff = pwp->scratch;
4099 	roff += rdoff;
4100 	srf = (smp_response_frame_t *)roff;
4101 	sdr = (smp_discover_resp_t *)(roff+4);
4102 	status = LE_32(ptr[2]);
4103 	if (status == PMCOUT_STATUS_UNDERFLOW ||
4104 	    status == PMCOUT_STATUS_OVERFLOW) {
4105 		pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW, pptr, NULL,
4106 		    "%s: over/underflow", __func__);
4107 		status = PMCOUT_STATUS_OK;
4108 	}
4109 	if (status != PMCOUT_STATUS_OK) {
4110 		char *nag = NULL;
4111 		(void) snprintf(buf, sizeof (buf),
4112 		    "%s: SMP op failed (0x%x)", __func__, status);
4113 		switch (status) {
4114 		case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4115 			DFM(nag, "Hardware Timeout");
4116 			/* FALLTHROUGH */
4117 		case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4118 			DFM(nag, "Internal SMP Resource Failure");
4119 			/* FALLTHROUGH */
4120 		case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4121 			DFM(nag, "PHY Not Ready");
4122 			/* FALLTHROUGH */
4123 		case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4124 			DFM(nag, "Connection Rate Not Supported");
4125 			/* FALLTHROUGH */
4126 		case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4127 			DFM(nag, "Open Retry Timeout");
4128 			/* FALLTHROUGH */
4129 		case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4130 			DFM(nag, "Response Connection Error");
4131 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4132 			    "%s: expander %s SMP operation failed (%s)",
4133 			    __func__, pptr->path, nag);
4134 			break;
4135 		default:
4136 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
4137 			result = -EIO;
4138 			break;
4139 		}
4140 		goto out;
4141 	} else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
4142 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4143 		    "%s: bad response frame type 0x%x",
4144 		    __func__, srf->srf_frame_type);
4145 		result = -EINVAL;
4146 		goto out;
4147 	} else if (srf->srf_function != SMP_FUNC_DISCOVER) {
4148 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4149 		    "%s: bad response function 0x%x",
4150 		    __func__, srf->srf_function);
4151 		result = -EINVAL;
4152 		goto out;
4153 	} else if (srf->srf_result != SMP_RES_FUNCTION_ACCEPTED) {
4154 		result = pmcs_smp_function_result(pwp, srf);
4155 		/* Need not fail if PHY is Vacant */
4156 		if (result != SMP_RES_PHY_VACANT) {
4157 			result = -EINVAL;
4158 			goto out;
4159 		}
4160 	}
4161 
4162 	ini_support = (sdr->sdr_attached_sata_host |
4163 	    (sdr->sdr_attached_smp_initiator << 1) |
4164 	    (sdr->sdr_attached_stp_initiator << 2) |
4165 	    (sdr->sdr_attached_ssp_initiator << 3));
4166 
4167 	tgt_support = (sdr->sdr_attached_sata_device |
4168 	    (sdr->sdr_attached_smp_target << 1) |
4169 	    (sdr->sdr_attached_stp_target << 2) |
4170 	    (sdr->sdr_attached_ssp_target << 3));
4171 
4172 	pmcs_wwn2barray(BE_64(sdr->sdr_sas_addr), sas_address);
4173 	pmcs_wwn2barray(BE_64(sdr->sdr_attached_sas_addr), att_sas_address);
4174 
4175 	switch (sdr->sdr_attached_device_type) {
4176 	case SAS_IF_DTYPE_ENDPOINT:
4177 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4178 		    "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4179 		    SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4180 		    pptr->path,
4181 		    sdr->sdr_attached_device_type,
4182 		    sdr->sdr_negotiated_logical_link_rate,
4183 		    ini_support,
4184 		    tgt_support,
4185 		    SAS_ADDR_PRT(sas_address),
4186 		    SAS_ADDR_PRT(att_sas_address),
4187 		    sdr->sdr_attached_phy_identifier);
4188 
4189 		if (sdr->sdr_attached_sata_device ||
4190 		    sdr->sdr_attached_stp_target) {
4191 			pptr->dtype = SATA;
4192 		} else if (sdr->sdr_attached_ssp_target) {
4193 			pptr->dtype = SAS;
4194 		} else if (tgt_support || ini_support) {
4195 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4196 			    "%s: %s has tgt support=%x init support=(%x)",
4197 			    __func__, pptr->path, tgt_support, ini_support);
4198 		}
4199 		break;
4200 	case SAS_IF_DTYPE_EDGE:
4201 	case SAS_IF_DTYPE_FANOUT:
4202 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4203 		    "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4204 		    SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4205 		    pptr->path,
4206 		    sdr->sdr_attached_device_type,
4207 		    sdr->sdr_negotiated_logical_link_rate,
4208 		    ini_support,
4209 		    tgt_support,
4210 		    SAS_ADDR_PRT(sas_address),
4211 		    SAS_ADDR_PRT(att_sas_address),
4212 		    sdr->sdr_attached_phy_identifier);
4213 		if (sdr->sdr_attached_smp_target) {
4214 			/*
4215 			 * Avoid configuring phys that just point back
4216 			 * at a parent phy
4217 			 */
4218 			if (expander->parent &&
4219 			    memcmp(expander->parent->sas_address,
4220 			    att_sas_address,
4221 			    sizeof (expander->parent->sas_address)) == 0) {
4222 				pmcs_prt(pwp, PMCS_PRT_DEBUG3, pptr, NULL,
4223 				    "%s: skipping port back to parent "
4224 				    "expander (%s)", __func__, pptr->path);
4225 				pptr->dtype = NOTHING;
4226 				break;
4227 			}
4228 			pptr->dtype = EXPANDER;
4229 
4230 		} else if (tgt_support || ini_support) {
4231 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4232 			    "%s has tgt support=%x init support=(%x)",
4233 			    pptr->path, tgt_support, ini_support);
4234 			pptr->dtype = EXPANDER;
4235 		}
4236 		break;
4237 	default:
4238 		pptr->dtype = NOTHING;
4239 		break;
4240 	}
4241 	if (pptr->dtype != NOTHING) {
4242 		pmcs_phy_t *ctmp;
4243 
4244 		/*
4245 		 * If the attached device is a SATA device and the expander
4246 		 * is (possibly) a SAS2 compliant expander, check for whether
4247 		 * there is a NAA=5 WWN field starting at this offset and
4248 		 * use that for the SAS Address for this device.
4249 		 */
4250 		if (expander->tolerates_sas2 && pptr->dtype == SATA &&
4251 		    (roff[SAS_ATTACHED_NAME_OFFSET] >> 8) == 0x5) {
4252 			(void) memcpy(pptr->sas_address,
4253 			    &roff[SAS_ATTACHED_NAME_OFFSET], 8);
4254 		} else {
4255 			(void) memcpy(pptr->sas_address, att_sas_address, 8);
4256 		}
4257 		pptr->atdt = (sdr->sdr_attached_device_type);
4258 		/*
4259 		 * Now run up from the expander's parent up to the top to
4260 		 * make sure we only use the least common link_rate.
4261 		 */
4262 		for (ctmp = expander->parent; ctmp; ctmp = ctmp->parent) {
4263 			if (ctmp->link_rate <
4264 			    sdr->sdr_negotiated_logical_link_rate) {
4265 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4266 				    "%s: derating link rate from %x to %x due "
4267 				    "to %s being slower", pptr->path,
4268 				    sdr->sdr_negotiated_logical_link_rate,
4269 				    ctmp->link_rate,
4270 				    ctmp->path);
4271 				sdr->sdr_negotiated_logical_link_rate =
4272 				    ctmp->link_rate;
4273 			}
4274 		}
4275 		pptr->link_rate = sdr->sdr_negotiated_logical_link_rate;
4276 		pptr->state.prog_min_rate = sdr->sdr_prog_min_phys_link_rate;
4277 		pptr->state.hw_min_rate = sdr->sdr_hw_min_phys_link_rate;
4278 		pptr->state.prog_max_rate = sdr->sdr_prog_max_phys_link_rate;
4279 		pptr->state.hw_max_rate = sdr->sdr_hw_max_phys_link_rate;
4280 		PHY_CHANGED(pwp, pptr);
4281 	} else {
4282 		pmcs_clear_phy(pwp, pptr);
4283 	}
4284 	result = 1;
4285 out:
4286 	return (result);
4287 }
4288 
4289 /*
4290  * Get a work structure and assign it a tag with type and serial number
4291  * If a structure is returned, it is returned locked.
4292  */
4293 pmcwork_t *
4294 pmcs_gwork(pmcs_hw_t *pwp, uint32_t tag_type, pmcs_phy_t *phyp)
4295 {
4296 	pmcwork_t *p;
4297 	uint16_t snum;
4298 	uint32_t off;
4299 
4300 	mutex_enter(&pwp->wfree_lock);
4301 	p = STAILQ_FIRST(&pwp->wf);
4302 	if (p == NULL) {
4303 		/*
4304 		 * If we couldn't get a work structure, it's time to bite
4305 		 * the bullet, grab the pfree_lock and copy over all the
4306 		 * work structures from the pending free list to the actual
4307 		 * free list.  This shouldn't happen all that often.
4308 		 */
4309 		mutex_enter(&pwp->pfree_lock);
4310 		pwp->wf.stqh_first = pwp->pf.stqh_first;
4311 		pwp->wf.stqh_last = pwp->pf.stqh_last;
4312 		STAILQ_INIT(&pwp->pf);
4313 		mutex_exit(&pwp->pfree_lock);
4314 
4315 		p = STAILQ_FIRST(&pwp->wf);
4316 		if (p == NULL) {
4317 			mutex_exit(&pwp->wfree_lock);
4318 			return (NULL);
4319 		}
4320 	}
4321 	STAILQ_REMOVE(&pwp->wf, p, pmcwork, next);
4322 	snum = pwp->wserno++;
4323 	mutex_exit(&pwp->wfree_lock);
4324 
4325 	off = p - pwp->work;
4326 
4327 	mutex_enter(&p->lock);
4328 	ASSERT(p->state == PMCS_WORK_STATE_NIL);
4329 	ASSERT(p->htag == PMCS_TAG_FREE);
4330 	p->htag = (tag_type << PMCS_TAG_TYPE_SHIFT) & PMCS_TAG_TYPE_MASK;
4331 	p->htag |= ((snum << PMCS_TAG_SERNO_SHIFT) & PMCS_TAG_SERNO_MASK);
4332 	p->htag |= ((off << PMCS_TAG_INDEX_SHIFT) & PMCS_TAG_INDEX_MASK);
4333 	p->start = gethrtime();
4334 	p->state = PMCS_WORK_STATE_READY;
4335 	p->ssp_event = 0;
4336 	p->dead = 0;
4337 
4338 	if (phyp) {
4339 		p->phy = phyp;
4340 		pmcs_inc_phy_ref_count(phyp);
4341 	}
4342 
4343 	return (p);
4344 }
4345 
4346 /*
4347  * Called with pwrk lock held.  Returned with lock released.
4348  */
4349 void
4350 pmcs_pwork(pmcs_hw_t *pwp, pmcwork_t *p)
4351 {
4352 	ASSERT(p != NULL);
4353 	ASSERT(mutex_owned(&p->lock));
4354 
4355 	p->last_ptr = p->ptr;
4356 	p->last_arg = p->arg;
4357 	p->last_phy = p->phy;
4358 	p->last_xp = p->xp;
4359 	p->last_htag = p->htag;
4360 	p->last_state = p->state;
4361 	p->finish = gethrtime();
4362 
4363 	if (p->phy) {
4364 		pmcs_dec_phy_ref_count(p->phy);
4365 	}
4366 
4367 	p->state = PMCS_WORK_STATE_NIL;
4368 	p->htag = PMCS_TAG_FREE;
4369 	p->xp = NULL;
4370 	p->ptr = NULL;
4371 	p->arg = NULL;
4372 	p->phy = NULL;
4373 	p->abt_htag = 0;
4374 	p->timer = 0;
4375 	mutex_exit(&p->lock);
4376 
4377 	if (mutex_tryenter(&pwp->wfree_lock) == 0) {
4378 		mutex_enter(&pwp->pfree_lock);
4379 		STAILQ_INSERT_TAIL(&pwp->pf, p, next);
4380 		mutex_exit(&pwp->pfree_lock);
4381 	} else {
4382 		STAILQ_INSERT_TAIL(&pwp->wf, p, next);
4383 		mutex_exit(&pwp->wfree_lock);
4384 	}
4385 }
4386 
4387 /*
4388  * Find a work structure based upon a tag and make sure that the tag
4389  * serial number matches the work structure we've found.
4390  * If a structure is found, its lock is held upon return.
4391  */
4392 pmcwork_t *
4393 pmcs_tag2wp(pmcs_hw_t *pwp, uint32_t htag)
4394 {
4395 	pmcwork_t *p;
4396 	uint32_t idx = PMCS_TAG_INDEX(htag);
4397 
4398 	p = &pwp->work[idx];
4399 
4400 	mutex_enter(&p->lock);
4401 	if (p->htag == htag) {
4402 		return (p);
4403 	}
4404 	mutex_exit(&p->lock);
4405 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
4406 	    "INDEX 0x%x HTAG 0x%x got p->htag 0x%x", idx, htag, p->htag);
4407 	return (NULL);
4408 }
4409 
4410 /*
4411  * Issue an abort for a command or for all commands.
4412  *
4413  * Since this can be called from interrupt context,
4414  * we don't wait for completion if wait is not set.
4415  *
4416  * Called with PHY lock held.
4417  */
4418 int
4419 pmcs_abort(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint32_t tag, int all_cmds,
4420     int wait)
4421 {
4422 	pmcwork_t *pwrk;
4423 	pmcs_xscsi_t *tgt;
4424 	uint32_t msg[PMCS_MSG_SIZE], *ptr;
4425 	int result, abt_type;
4426 	uint32_t abt_htag, status;
4427 
4428 	if (pptr->abort_all_start) {
4429 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: ABORT_ALL for "
4430 		    "(%s) already in progress.", __func__, pptr->path);
4431 		return (EBUSY);
4432 	}
4433 
4434 	switch (pptr->dtype) {
4435 	case SAS:
4436 		abt_type = PMCIN_SSP_ABORT;
4437 		break;
4438 	case SATA:
4439 		abt_type = PMCIN_SATA_ABORT;
4440 		break;
4441 	case EXPANDER:
4442 		abt_type = PMCIN_SMP_ABORT;
4443 		break;
4444 	default:
4445 		return (0);
4446 	}
4447 
4448 	pwrk = pmcs_gwork(pwp, wait ? PMCS_TAG_TYPE_WAIT : PMCS_TAG_TYPE_NONE,
4449 	    pptr);
4450 
4451 	if (pwrk == NULL) {
4452 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
4453 		return (ENOMEM);
4454 	}
4455 
4456 	pwrk->dtype = pptr->dtype;
4457 	if (wait) {
4458 		pwrk->arg = msg;
4459 	}
4460 	if (pptr->valid_device_id == 0) {
4461 		pmcs_pwork(pwp, pwrk);
4462 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4463 		    "%s: Invalid DeviceID", __func__);
4464 		return (ENODEV);
4465 	}
4466 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, abt_type));
4467 	msg[1] = LE_32(pwrk->htag);
4468 	msg[2] = LE_32(pptr->device_id);
4469 	if (all_cmds) {
4470 		msg[3] = 0;
4471 		msg[4] = LE_32(1);
4472 		pwrk->ptr = NULL;
4473 		pptr->abort_all_start = gethrtime();
4474 	} else {
4475 		msg[3] = LE_32(tag);
4476 		msg[4] = 0;
4477 		pwrk->abt_htag = tag;
4478 	}
4479 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4480 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4481 	if (ptr == NULL) {
4482 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4483 		pmcs_pwork(pwp, pwrk);
4484 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
4485 		return (ENOMEM);
4486 	}
4487 
4488 	COPY_MESSAGE(ptr, msg, 5);
4489 	if (all_cmds) {
4490 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4491 		    "%s: aborting all commands for %s device %s. (htag=0x%x)",
4492 		    __func__, pmcs_get_typename(pptr->dtype), pptr->path,
4493 		    msg[1]);
4494 	} else {
4495 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4496 		    "%s: aborting tag 0x%x for %s device %s. (htag=0x%x)",
4497 		    __func__, tag, pmcs_get_typename(pptr->dtype), pptr->path,
4498 		    msg[1]);
4499 	}
4500 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4501 
4502 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4503 	if (!wait) {
4504 		mutex_exit(&pwrk->lock);
4505 		return (0);
4506 	}
4507 
4508 	abt_htag = pwrk->htag;
4509 	pmcs_unlock_phy(pwrk->phy);
4510 	WAIT_FOR(pwrk, 1000, result);
4511 	pmcs_lock_phy(pwrk->phy);
4512 
4513 	tgt = pwrk->xp;
4514 	pmcs_pwork(pwp, pwrk);
4515 
4516 	if (tgt != NULL) {
4517 		mutex_enter(&tgt->aqlock);
4518 		if (!STAILQ_EMPTY(&tgt->aq)) {
4519 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4520 			    "%s: Abort complete (result=0x%x), but "
4521 			    "aq not empty (tgt 0x%p), waiting",
4522 			    __func__, result, (void *)tgt);
4523 			cv_wait(&tgt->abort_cv, &tgt->aqlock);
4524 		}
4525 		mutex_exit(&tgt->aqlock);
4526 	}
4527 
4528 	if (all_cmds) {
4529 		pptr->abort_all_start = 0;
4530 		cv_signal(&pptr->abort_all_cv);
4531 	}
4532 
4533 	if (result) {
4534 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4535 		    "%s: Abort (htag 0x%08x) request timed out",
4536 		    __func__, abt_htag);
4537 		if (tgt != NULL) {
4538 			mutex_enter(&tgt->statlock);
4539 			if ((tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) &&
4540 			    (tgt->dev_state !=
4541 			    PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
4542 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4543 				    "%s: Trying DS error recovery for tgt 0x%p",
4544 				    __func__, (void *)tgt);
4545 				(void) pmcs_send_err_recovery_cmd(pwp,
4546 				    PMCS_DEVICE_STATE_IN_RECOVERY, tgt);
4547 			}
4548 			mutex_exit(&tgt->statlock);
4549 		}
4550 		return (ETIMEDOUT);
4551 	}
4552 
4553 	status = LE_32(msg[2]);
4554 	if (status != PMCOUT_STATUS_OK) {
4555 		/*
4556 		 * The only non-success status are IO_NOT_VALID &
4557 		 * IO_ABORT_IN_PROGRESS.
4558 		 * In case of IO_ABORT_IN_PROGRESS, the other ABORT cmd's
4559 		 * status is of concern and this duplicate cmd status can
4560 		 * be ignored.
4561 		 * If IO_NOT_VALID, that's not an error per-se.
4562 		 * For abort of single I/O complete the command anyway.
4563 		 * If, however, we were aborting all, that is a problem
4564 		 * as IO_NOT_VALID really means that the IO or device is
4565 		 * not there. So, discovery process will take of the cleanup.
4566 		 */
4567 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4568 		    "%s: abort result 0x%x", __func__, LE_32(msg[2]));
4569 		if (all_cmds) {
4570 			PHY_CHANGED(pwp, pptr);
4571 			RESTART_DISCOVERY(pwp);
4572 		} else {
4573 			return (EINVAL);
4574 		}
4575 
4576 		return (0);
4577 	}
4578 
4579 	if (tgt != NULL) {
4580 		mutex_enter(&tgt->statlock);
4581 		if (tgt->dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
4582 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4583 			    "%s: Restoring OPERATIONAL dev_state for tgt 0x%p",
4584 			    __func__, (void *)tgt);
4585 			(void) pmcs_send_err_recovery_cmd(pwp,
4586 			    PMCS_DEVICE_STATE_OPERATIONAL, tgt);
4587 		}
4588 		mutex_exit(&tgt->statlock);
4589 	}
4590 
4591 	return (0);
4592 }
4593 
4594 /*
4595  * Issue a task management function to an SSP device.
4596  *
4597  * Called with PHY lock held.
4598  * statlock CANNOT be held upon entry.
4599  */
4600 int
4601 pmcs_ssp_tmf(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t tmf, uint32_t tag,
4602     uint64_t lun, uint32_t *response)
4603 {
4604 	int result, ds;
4605 	uint8_t local[PMCS_QENTRY_SIZE << 1], *xd;
4606 	sas_ssp_rsp_iu_t *rptr = (void *)local;
4607 	static const uint8_t ssp_rsp_evec[] = {
4608 		0x58, 0x61, 0x56, 0x72, 0x00
4609 	};
4610 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
4611 	struct pmcwork *pwrk;
4612 	pmcs_xscsi_t *xp;
4613 
4614 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4615 	if (pwrk == NULL) {
4616 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
4617 		return (ENOMEM);
4618 	}
4619 	/*
4620 	 * NB: We use the PMCS_OQ_GENERAL outbound queue
4621 	 * NB: so as to not get entangled in normal I/O
4622 	 * NB: processing.
4623 	 */
4624 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4625 	    PMCIN_SSP_INI_TM_START));
4626 	msg[1] = LE_32(pwrk->htag);
4627 	msg[2] = LE_32(pptr->device_id);
4628 	if (tmf == SAS_ABORT_TASK || tmf == SAS_QUERY_TASK) {
4629 		msg[3] = LE_32(tag);
4630 	} else {
4631 		msg[3] = 0;
4632 	}
4633 	msg[4] = LE_32(tmf);
4634 	msg[5] = BE_32((uint32_t)lun);
4635 	msg[6] = BE_32((uint32_t)(lun >> 32));
4636 	msg[7] = LE_32(PMCIN_MESSAGE_REPORT);
4637 
4638 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4639 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4640 	if (ptr == NULL) {
4641 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4642 		pmcs_pwork(pwp, pwrk);
4643 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
4644 		return (ENOMEM);
4645 	}
4646 	COPY_MESSAGE(ptr, msg, 7);
4647 	pwrk->arg = msg;
4648 	pwrk->dtype = pptr->dtype;
4649 
4650 	xp = pptr->target;
4651 	if (xp != NULL) {
4652 		mutex_enter(&xp->statlock);
4653 		if (xp->dev_state == PMCS_DEVICE_STATE_NON_OPERATIONAL) {
4654 			mutex_exit(&xp->statlock);
4655 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4656 			pmcs_pwork(pwp, pwrk);
4657 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: Not "
4658 			    "sending '%s' because DS is '%s'", __func__,
4659 			    pmcs_tmf2str(tmf), pmcs_status_str
4660 			    (PMCOUT_STATUS_IO_DS_NON_OPERATIONAL));
4661 			return (EIO);
4662 		}
4663 		mutex_exit(&xp->statlock);
4664 	}
4665 
4666 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4667 	    "%s: sending '%s' to %s (lun %llu) tag 0x%x", __func__,
4668 	    pmcs_tmf2str(tmf), pptr->path, (unsigned long long) lun, tag);
4669 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4670 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4671 
4672 	pmcs_unlock_phy(pptr);
4673 	/*
4674 	 * This is a command sent to the target device, so it can take
4675 	 * significant amount of time to complete when path & device is busy.
4676 	 * Set a timeout to 20 seconds
4677 	 */
4678 	WAIT_FOR(pwrk, 20000, result);
4679 	pmcs_lock_phy(pptr);
4680 	pmcs_pwork(pwp, pwrk);
4681 
4682 	if (result) {
4683 		if (xp == NULL) {
4684 			return (ETIMEDOUT);
4685 		}
4686 
4687 		mutex_enter(&xp->statlock);
4688 		pmcs_start_dev_state_recovery(xp, pptr);
4689 		mutex_exit(&xp->statlock);
4690 		return (ETIMEDOUT);
4691 	}
4692 
4693 	status = LE_32(msg[2]);
4694 	if (status != PMCOUT_STATUS_OK) {
4695 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4696 		    "%s: status %s for TMF %s action to %s, lun %llu",
4697 		    __func__, pmcs_status_str(status),  pmcs_tmf2str(tmf),
4698 		    pptr->path, (unsigned long long) lun);
4699 		if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
4700 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
4701 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
4702 			ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
4703 		} else if (status == PMCOUT_STATUS_IO_DS_IN_RECOVERY) {
4704 			/*
4705 			 * If the status is IN_RECOVERY, it's an indication
4706 			 * that it's now time for us to request to have the
4707 			 * device state set to OPERATIONAL since we're the ones
4708 			 * that requested recovery to begin with.
4709 			 */
4710 			ds = PMCS_DEVICE_STATE_OPERATIONAL;
4711 		} else {
4712 			ds = PMCS_DEVICE_STATE_IN_RECOVERY;
4713 		}
4714 		if (xp != NULL) {
4715 			mutex_enter(&xp->statlock);
4716 			if (xp->dev_state != ds) {
4717 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4718 				    "%s: Sending err recovery cmd"
4719 				    " for tgt 0x%p (status = %s)",
4720 				    __func__, (void *)xp,
4721 				    pmcs_status_str(status));
4722 				(void) pmcs_send_err_recovery_cmd(pwp, ds, xp);
4723 			}
4724 			mutex_exit(&xp->statlock);
4725 		}
4726 		return (EIO);
4727 	} else {
4728 		ds = PMCS_DEVICE_STATE_OPERATIONAL;
4729 		if (xp != NULL) {
4730 			mutex_enter(&xp->statlock);
4731 			if (xp->dev_state != ds) {
4732 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4733 				    "%s: Sending err recovery cmd"
4734 				    " for tgt 0x%p (status = %s)",
4735 				    __func__, (void *)xp,
4736 				    pmcs_status_str(status));
4737 				(void) pmcs_send_err_recovery_cmd(pwp, ds, xp);
4738 			}
4739 			mutex_exit(&xp->statlock);
4740 		}
4741 	}
4742 	if (LE_32(msg[3]) == 0) {
4743 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4744 		    "TMF completed with no response");
4745 		return (EIO);
4746 	}
4747 	pmcs_endian_transform(pwp, local, &msg[5], ssp_rsp_evec);
4748 	xd = (uint8_t *)(&msg[5]);
4749 	xd += SAS_RSP_HDR_SIZE;
4750 	if (rptr->datapres != SAS_RSP_DATAPRES_RESPONSE_DATA) {
4751 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4752 		    "%s: TMF response not RESPONSE DATA (0x%x)",
4753 		    __func__, rptr->datapres);
4754 		return (EIO);
4755 	}
4756 	if (rptr->response_data_length != 4) {
4757 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4758 		    "Bad SAS RESPONSE DATA LENGTH", msg);
4759 		return (EIO);
4760 	}
4761 	(void) memcpy(&status, xd, sizeof (uint32_t));
4762 	status = BE_32(status);
4763 	if (response != NULL)
4764 		*response = status;
4765 	/*
4766 	 * The status is actually in the low-order byte.  The upper three
4767 	 * bytes contain additional information for the TMFs that support them.
4768 	 * However, at this time we do not issue any of those.  In the other
4769 	 * cases, the upper three bytes are supposed to be 0, but it appears
4770 	 * they aren't always.  Just mask them off.
4771 	 */
4772 	switch (status & 0xff) {
4773 	case SAS_RSP_TMF_COMPLETE:
4774 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4775 		    "%s: TMF complete", __func__);
4776 		result = 0;
4777 		break;
4778 	case SAS_RSP_TMF_SUCCEEDED:
4779 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4780 		    "%s: TMF succeeded", __func__);
4781 		result = 0;
4782 		break;
4783 	case SAS_RSP_INVALID_FRAME:
4784 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4785 		    "%s: TMF returned INVALID FRAME", __func__);
4786 		result = EIO;
4787 		break;
4788 	case SAS_RSP_TMF_NOT_SUPPORTED:
4789 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4790 		    "%s: TMF returned TMF NOT SUPPORTED", __func__);
4791 		result = EIO;
4792 		break;
4793 	case SAS_RSP_TMF_FAILED:
4794 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4795 		    "%s: TMF returned TMF FAILED", __func__);
4796 		result = EIO;
4797 		break;
4798 	case SAS_RSP_TMF_INCORRECT_LUN:
4799 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4800 		    "%s: TMF returned INCORRECT LUN", __func__);
4801 		result = EIO;
4802 		break;
4803 	case SAS_RSP_OVERLAPPED_OIPTTA:
4804 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4805 		    "%s: TMF returned OVERLAPPED INITIATOR PORT TRANSFER TAG "
4806 		    "ATTEMPTED", __func__);
4807 		result = EIO;
4808 		break;
4809 	default:
4810 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4811 		    "%s: TMF returned unknown code 0x%x", __func__, status);
4812 		result = EIO;
4813 		break;
4814 	}
4815 	return (result);
4816 }
4817 
4818 /*
4819  * Called with PHY lock held and scratch acquired
4820  */
4821 int
4822 pmcs_sata_abort_ncq(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4823 {
4824 	const char *utag_fail_fmt = "%s: untagged NCQ command failure";
4825 	const char *tag_fail_fmt = "%s: NCQ command failure (tag 0x%x)";
4826 	uint32_t msg[PMCS_QENTRY_SIZE], *ptr, result, status;
4827 	uint8_t *fp = pwp->scratch, ds;
4828 	fis_t fis;
4829 	pmcwork_t *pwrk;
4830 	pmcs_xscsi_t *tgt;
4831 
4832 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4833 	if (pwrk == NULL) {
4834 		return (ENOMEM);
4835 	}
4836 	msg[0] = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE,
4837 	    PMCIN_SATA_HOST_IO_START));
4838 	msg[1] = LE_32(pwrk->htag);
4839 	msg[2] = LE_32(pptr->device_id);
4840 	msg[3] = LE_32(512);
4841 	msg[4] = LE_32(SATA_PROTOCOL_PIO | PMCIN_DATADIR_2_INI);
4842 	msg[5] = LE_32((READ_LOG_EXT << 16) | (C_BIT << 8) | FIS_REG_H2DEV);
4843 	msg[6] = LE_32(0x10);
4844 	msg[8] = LE_32(1);
4845 	msg[9] = 0;
4846 	msg[10] = 0;
4847 	msg[11] = 0;
4848 	msg[12] = LE_32(DWORD0(pwp->scratch_dma));
4849 	msg[13] = LE_32(DWORD1(pwp->scratch_dma));
4850 	msg[14] = LE_32(512);
4851 	msg[15] = 0;
4852 
4853 	pwrk->arg = msg;
4854 	pwrk->dtype = pptr->dtype;
4855 
4856 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4857 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4858 	if (ptr == NULL) {
4859 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4860 		pmcs_pwork(pwp, pwrk);
4861 		return (ENOMEM);
4862 	}
4863 	COPY_MESSAGE(ptr, msg, PMCS_QENTRY_SIZE);
4864 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4865 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4866 
4867 	pmcs_unlock_phy(pptr);
4868 	WAIT_FOR(pwrk, 250, result);
4869 	pmcs_lock_phy(pptr);
4870 	pmcs_pwork(pwp, pwrk);
4871 
4872 	tgt = pptr->target;
4873 	if (result) {
4874 		pmcs_prt(pwp, PMCS_PRT_INFO, pptr, tgt, pmcs_timeo, __func__);
4875 		return (EIO);
4876 	}
4877 	status = LE_32(msg[2]);
4878 	if (status != PMCOUT_STATUS_OK || LE_32(msg[3])) {
4879 		if (tgt == NULL) {
4880 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4881 			    "%s: cannot find target for phy 0x%p for "
4882 			    "dev state recovery", __func__, (void *)pptr);
4883 			return (EIO);
4884 		}
4885 
4886 		mutex_enter(&tgt->statlock);
4887 
4888 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG, "READ LOG EXT", msg);
4889 		if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
4890 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
4891 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
4892 			ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
4893 		} else {
4894 			ds = PMCS_DEVICE_STATE_IN_RECOVERY;
4895 		}
4896 		if (tgt->dev_state != ds) {
4897 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt, "%s: Trying "
4898 			    "SATA DS Recovery for tgt(0x%p) for status(%s)",
4899 			    __func__, (void *)tgt, pmcs_status_str(status));
4900 			(void) pmcs_send_err_recovery_cmd(pwp, ds, tgt);
4901 		}
4902 
4903 		mutex_exit(&tgt->statlock);
4904 		return (EIO);
4905 	}
4906 	fis[0] = (fp[4] << 24) | (fp[3] << 16) | (fp[2] << 8) | FIS_REG_D2H;
4907 	fis[1] = (fp[8] << 24) | (fp[7] << 16) | (fp[6] << 8) | fp[5];
4908 	fis[2] = (fp[12] << 24) | (fp[11] << 16) | (fp[10] << 8) | fp[9];
4909 	fis[3] = (fp[16] << 24) | (fp[15] << 16) | (fp[14] << 8) | fp[13];
4910 	fis[4] = 0;
4911 	if (fp[0] & 0x80) {
4912 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4913 		    utag_fail_fmt, __func__);
4914 	} else {
4915 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4916 		    tag_fail_fmt, __func__, fp[0] & 0x1f);
4917 	}
4918 	pmcs_fis_dump(pwp, fis);
4919 	pptr->need_rl_ext = 0;
4920 	return (0);
4921 }
4922 
4923 /*
4924  * Transform a structure from CPU to Device endian format, or
4925  * vice versa, based upon a transformation vector.
4926  *
4927  * A transformation vector is an array of bytes, each byte
4928  * of which is defined thusly:
4929  *
4930  *  bit 7: from CPU to desired endian, otherwise from desired endian
4931  *	   to CPU format
4932  *  bit 6: Big Endian, else Little Endian
4933  *  bits 5-4:
4934  *       00 Undefined
4935  *       01 One Byte quantities
4936  *       02 Two Byte quantities
4937  *       03 Four Byte quantities
4938  *
4939  *  bits 3-0:
4940  *       00 Undefined
4941  *       Number of quantities to transform
4942  *
4943  * The vector is terminated by a 0 value.
4944  */
4945 
4946 void
4947 pmcs_endian_transform(pmcs_hw_t *pwp, void *orig_out, void *orig_in,
4948     const uint8_t *xfvec)
4949 {
4950 	uint8_t c, *out = orig_out, *in = orig_in;
4951 
4952 	if (xfvec == NULL) {
4953 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4954 		    "%s: null xfvec", __func__);
4955 		return;
4956 	}
4957 	if (out == NULL) {
4958 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4959 		    "%s: null out", __func__);
4960 		return;
4961 	}
4962 	if (in == NULL) {
4963 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4964 		    "%s: null in", __func__);
4965 		return;
4966 	}
4967 	while ((c = *xfvec++) != 0) {
4968 		int nbyt = (c & 0xf);
4969 		int size = (c >> 4) & 0x3;
4970 		int bige = (c >> 4) & 0x4;
4971 
4972 		switch (size) {
4973 		case 1:
4974 		{
4975 			while (nbyt-- > 0) {
4976 				*out++ = *in++;
4977 			}
4978 			break;
4979 		}
4980 		case 2:
4981 		{
4982 			uint16_t tmp;
4983 			while (nbyt-- > 0) {
4984 				(void) memcpy(&tmp, in, sizeof (uint16_t));
4985 				if (bige) {
4986 					tmp = BE_16(tmp);
4987 				} else {
4988 					tmp = LE_16(tmp);
4989 				}
4990 				(void) memcpy(out, &tmp, sizeof (uint16_t));
4991 				out += sizeof (uint16_t);
4992 				in += sizeof (uint16_t);
4993 			}
4994 			break;
4995 		}
4996 		case 3:
4997 		{
4998 			uint32_t tmp;
4999 			while (nbyt-- > 0) {
5000 				(void) memcpy(&tmp, in, sizeof (uint32_t));
5001 				if (bige) {
5002 					tmp = BE_32(tmp);
5003 				} else {
5004 					tmp = LE_32(tmp);
5005 				}
5006 				(void) memcpy(out, &tmp, sizeof (uint32_t));
5007 				out += sizeof (uint32_t);
5008 				in += sizeof (uint32_t);
5009 			}
5010 			break;
5011 		}
5012 		default:
5013 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
5014 			    "%s: bad size", __func__);
5015 			return;
5016 		}
5017 	}
5018 }
5019 
5020 const char *
5021 pmcs_get_rate(unsigned int linkrt)
5022 {
5023 	const char *rate;
5024 	switch (linkrt) {
5025 	case SAS_LINK_RATE_1_5GBIT:
5026 		rate = "1.5";
5027 		break;
5028 	case SAS_LINK_RATE_3GBIT:
5029 		rate = "3.0";
5030 		break;
5031 	case SAS_LINK_RATE_6GBIT:
5032 		rate = "6.0";
5033 		break;
5034 	default:
5035 		rate = "???";
5036 		break;
5037 	}
5038 	return (rate);
5039 }
5040 
5041 const char *
5042 pmcs_get_typename(pmcs_dtype_t type)
5043 {
5044 	switch (type) {
5045 	case NOTHING:
5046 		return ("NIL");
5047 	case SATA:
5048 		return ("SATA");
5049 	case SAS:
5050 		return ("SSP");
5051 	case EXPANDER:
5052 		return ("EXPANDER");
5053 	}
5054 	return ("????");
5055 }
5056 
5057 const char *
5058 pmcs_tmf2str(int tmf)
5059 {
5060 	switch (tmf) {
5061 	case SAS_ABORT_TASK:
5062 		return ("Abort Task");
5063 	case SAS_ABORT_TASK_SET:
5064 		return ("Abort Task Set");
5065 	case SAS_CLEAR_TASK_SET:
5066 		return ("Clear Task Set");
5067 	case SAS_LOGICAL_UNIT_RESET:
5068 		return ("Logical Unit Reset");
5069 	case SAS_I_T_NEXUS_RESET:
5070 		return ("I_T Nexus Reset");
5071 	case SAS_CLEAR_ACA:
5072 		return ("Clear ACA");
5073 	case SAS_QUERY_TASK:
5074 		return ("Query Task");
5075 	case SAS_QUERY_TASK_SET:
5076 		return ("Query Task Set");
5077 	case SAS_QUERY_UNIT_ATTENTION:
5078 		return ("Query Unit Attention");
5079 	default:
5080 		return ("Unknown");
5081 	}
5082 }
5083 
5084 const char *
5085 pmcs_status_str(uint32_t status)
5086 {
5087 	switch (status) {
5088 	case PMCOUT_STATUS_OK:
5089 		return ("OK");
5090 	case PMCOUT_STATUS_ABORTED:
5091 		return ("ABORTED");
5092 	case PMCOUT_STATUS_OVERFLOW:
5093 		return ("OVERFLOW");
5094 	case PMCOUT_STATUS_UNDERFLOW:
5095 		return ("UNDERFLOW");
5096 	case PMCOUT_STATUS_FAILED:
5097 		return ("FAILED");
5098 	case PMCOUT_STATUS_ABORT_RESET:
5099 		return ("ABORT_RESET");
5100 	case PMCOUT_STATUS_IO_NOT_VALID:
5101 		return ("IO_NOT_VALID");
5102 	case PMCOUT_STATUS_NO_DEVICE:
5103 		return ("NO_DEVICE");
5104 	case PMCOUT_STATUS_ILLEGAL_PARAMETER:
5105 		return ("ILLEGAL_PARAMETER");
5106 	case PMCOUT_STATUS_LINK_FAILURE:
5107 		return ("LINK_FAILURE");
5108 	case PMCOUT_STATUS_PROG_ERROR:
5109 		return ("PROG_ERROR");
5110 	case PMCOUT_STATUS_EDC_IN_ERROR:
5111 		return ("EDC_IN_ERROR");
5112 	case PMCOUT_STATUS_EDC_OUT_ERROR:
5113 		return ("EDC_OUT_ERROR");
5114 	case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
5115 		return ("ERROR_HW_TIMEOUT");
5116 	case PMCOUT_STATUS_XFER_ERR_BREAK:
5117 		return ("XFER_ERR_BREAK");
5118 	case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
5119 		return ("XFER_ERR_PHY_NOT_READY");
5120 	case PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED:
5121 		return ("OPEN_CNX_PROTOCOL_NOT_SUPPORTED");
5122 	case PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION:
5123 		return ("OPEN_CNX_ERROR_ZONE_VIOLATION");
5124 	case PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK:
5125 		return ("OPEN_CNX_ERROR_BREAK");
5126 	case PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
5127 		return ("OPEN_CNX_ERROR_IT_NEXUS_LOSS");
5128 	case PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION:
5129 		return ("OPENCNX_ERROR_BAD_DESTINATION");
5130 	case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
5131 		return ("OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED");
5132 	case PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
5133 		return ("OPEN_CNX_ERROR_STP_RESOURCES_BUSY");
5134 	case PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION:
5135 		return ("OPEN_CNX_ERROR_WRONG_DESTINATION");
5136 	case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_EROOR:
5137 		return ("OPEN_CNX_ERROR_UNKNOWN_EROOR");
5138 	case PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED:
5139 		return ("IO_XFER_ERROR_NAK_RECEIVED");
5140 	case PMCOUT_STATUS_XFER_ERROR_ACK_NAK_TIMEOUT:
5141 		return ("XFER_ERROR_ACK_NAK_TIMEOUT");
5142 	case PMCOUT_STATUS_XFER_ERROR_PEER_ABORTED:
5143 		return ("XFER_ERROR_PEER_ABORTED");
5144 	case PMCOUT_STATUS_XFER_ERROR_RX_FRAME:
5145 		return ("XFER_ERROR_RX_FRAME");
5146 	case PMCOUT_STATUS_IO_XFER_ERROR_DMA:
5147 		return ("IO_XFER_ERROR_DMA");
5148 	case PMCOUT_STATUS_XFER_ERROR_CREDIT_TIMEOUT:
5149 		return ("XFER_ERROR_CREDIT_TIMEOUT");
5150 	case PMCOUT_STATUS_XFER_ERROR_SATA_LINK_TIMEOUT:
5151 		return ("XFER_ERROR_SATA_LINK_TIMEOUT");
5152 	case PMCOUT_STATUS_XFER_ERROR_SATA:
5153 		return ("XFER_ERROR_SATA");
5154 	case PMCOUT_STATUS_XFER_ERROR_REJECTED_NCQ_MODE:
5155 		return ("XFER_ERROR_REJECTED_NCQ_MODE");
5156 	case PMCOUT_STATUS_XFER_ERROR_ABORTED_DUE_TO_SRST:
5157 		return ("XFER_ERROR_ABORTED_DUE_TO_SRST");
5158 	case PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE:
5159 		return ("XFER_ERROR_ABORTED_NCQ_MODE");
5160 	case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
5161 		return ("IO_XFER_OPEN_RETRY_TIMEOUT");
5162 	case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
5163 		return ("SMP_RESP_CONNECTION_ERROR");
5164 	case PMCOUT_STATUS_XFER_ERROR_UNEXPECTED_PHASE:
5165 		return ("XFER_ERROR_UNEXPECTED_PHASE");
5166 	case PMCOUT_STATUS_XFER_ERROR_RDY_OVERRUN:
5167 		return ("XFER_ERROR_RDY_OVERRUN");
5168 	case PMCOUT_STATUS_XFER_ERROR_RDY_NOT_EXPECTED:
5169 		return ("XFER_ERROR_RDY_NOT_EXPECTED");
5170 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
5171 		return ("XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT");
5172 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK:
5173 		return ("XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK");
5174 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK:
5175 		return ("XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK");
5176 	case PMCOUT_STATUS_XFER_ERROR_OFFSET_MISMATCH:
5177 		return ("XFER_ERROR_OFFSET_MISMATCH");
5178 	case PMCOUT_STATUS_XFER_ERROR_ZERO_DATA_LEN:
5179 		return ("XFER_ERROR_ZERO_DATA_LEN");
5180 	case PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED:
5181 		return ("XFER_CMD_FRAME_ISSUED");
5182 	case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
5183 		return ("ERROR_INTERNAL_SMP_RESOURCE");
5184 	case PMCOUT_STATUS_IO_PORT_IN_RESET:
5185 		return ("IO_PORT_IN_RESET");
5186 	case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL:
5187 		return ("DEVICE STATE NON-OPERATIONAL");
5188 	case PMCOUT_STATUS_IO_DS_IN_RECOVERY:
5189 		return ("DEVICE STATE IN RECOVERY");
5190 	default:
5191 		return (NULL);
5192 	}
5193 }
5194 
5195 uint64_t
5196 pmcs_barray2wwn(uint8_t ba[8])
5197 {
5198 	uint64_t result = 0;
5199 	int i;
5200 
5201 	for (i = 0; i < 8; i++) {
5202 		result <<= 8;
5203 		result |= ba[i];
5204 	}
5205 	return (result);
5206 }
5207 
5208 void
5209 pmcs_wwn2barray(uint64_t wwn, uint8_t ba[8])
5210 {
5211 	int i;
5212 	for (i = 0; i < 8; i++) {
5213 		ba[7 - i] = wwn & 0xff;
5214 		wwn >>= 8;
5215 	}
5216 }
5217 
5218 void
5219 pmcs_report_fwversion(pmcs_hw_t *pwp)
5220 {
5221 	const char *fwsupport;
5222 	switch (PMCS_FW_TYPE(pwp)) {
5223 	case PMCS_FW_TYPE_RELEASED:
5224 		fwsupport = "Released";
5225 		break;
5226 	case PMCS_FW_TYPE_DEVELOPMENT:
5227 		fwsupport = "Development";
5228 		break;
5229 	case PMCS_FW_TYPE_ALPHA:
5230 		fwsupport = "Alpha";
5231 		break;
5232 	case PMCS_FW_TYPE_BETA:
5233 		fwsupport = "Beta";
5234 		break;
5235 	default:
5236 		fwsupport = "Special";
5237 		break;
5238 	}
5239 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5240 	    "Chip Revision: %c; F/W Revision %x.%x.%x %s", 'A' + pwp->chiprev,
5241 	    PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp), PMCS_FW_MICRO(pwp),
5242 	    fwsupport);
5243 }
5244 
5245 void
5246 pmcs_phy_name(pmcs_hw_t *pwp, pmcs_phy_t *pptr, char *obuf, size_t olen)
5247 {
5248 	if (pptr->parent) {
5249 		pmcs_phy_name(pwp, pptr->parent, obuf, olen);
5250 		(void) snprintf(obuf, olen, "%s.%02x", obuf, pptr->phynum);
5251 	} else {
5252 		(void) snprintf(obuf, olen, "pp%02x", pptr->phynum);
5253 	}
5254 }
5255 
5256 /*
5257  * Implementation for pmcs_find_phy_by_devid.
5258  * If the PHY is found, it is returned locked.
5259  */
5260 static pmcs_phy_t *
5261 pmcs_find_phy_by_devid_impl(pmcs_phy_t *phyp, uint32_t device_id)
5262 {
5263 	pmcs_phy_t *match, *cphyp, *nphyp;
5264 
5265 	ASSERT(!mutex_owned(&phyp->phy_lock));
5266 
5267 	while (phyp) {
5268 		pmcs_lock_phy(phyp);
5269 
5270 		if ((phyp->valid_device_id) && (phyp->device_id == device_id)) {
5271 			return (phyp);
5272 		}
5273 		if (phyp->children) {
5274 			cphyp = phyp->children;
5275 			pmcs_unlock_phy(phyp);
5276 			match = pmcs_find_phy_by_devid_impl(cphyp, device_id);
5277 			if (match) {
5278 				ASSERT(mutex_owned(&match->phy_lock));
5279 				return (match);
5280 			}
5281 			pmcs_lock_phy(phyp);
5282 		}
5283 
5284 		if (IS_ROOT_PHY(phyp)) {
5285 			pmcs_unlock_phy(phyp);
5286 			phyp = NULL;
5287 		} else {
5288 			nphyp = phyp->sibling;
5289 			pmcs_unlock_phy(phyp);
5290 			phyp = nphyp;
5291 		}
5292 	}
5293 
5294 	return (NULL);
5295 }
5296 
5297 /*
5298  * If the PHY is found, it is returned locked
5299  */
5300 pmcs_phy_t *
5301 pmcs_find_phy_by_devid(pmcs_hw_t *pwp, uint32_t device_id)
5302 {
5303 	pmcs_phy_t *phyp, *match = NULL;
5304 
5305 	phyp = pwp->root_phys;
5306 
5307 	while (phyp) {
5308 		match = pmcs_find_phy_by_devid_impl(phyp, device_id);
5309 		if (match) {
5310 			ASSERT(mutex_owned(&match->phy_lock));
5311 			return (match);
5312 		}
5313 		phyp = phyp->sibling;
5314 	}
5315 
5316 	return (NULL);
5317 }
5318 
5319 /*
5320  * This function is called as a sanity check to ensure that a newly registered
5321  * PHY doesn't have a device_id that exists with another registered PHY.
5322  */
5323 static boolean_t
5324 pmcs_validate_devid(pmcs_phy_t *parent, pmcs_phy_t *phyp, uint32_t device_id)
5325 {
5326 	pmcs_phy_t *pptr;
5327 	boolean_t rval;
5328 
5329 	pptr = parent;
5330 
5331 	while (pptr) {
5332 		if (pptr->valid_device_id && (pptr != phyp) &&
5333 		    (pptr->device_id == device_id)) {
5334 			pmcs_prt(pptr->pwp, PMCS_PRT_DEBUG, pptr, NULL,
5335 			    "%s: phy %s already exists as %s with "
5336 			    "device id 0x%x", __func__, phyp->path,
5337 			    pptr->path, device_id);
5338 			return (B_FALSE);
5339 		}
5340 
5341 		if (pptr->children) {
5342 			rval = pmcs_validate_devid(pptr->children, phyp,
5343 			    device_id);
5344 			if (rval == B_FALSE) {
5345 				return (rval);
5346 			}
5347 		}
5348 
5349 		pptr = pptr->sibling;
5350 	}
5351 
5352 	/* This PHY and device_id are valid */
5353 	return (B_TRUE);
5354 }
5355 
5356 /*
5357  * If the PHY is found, it is returned locked
5358  */
5359 static pmcs_phy_t *
5360 pmcs_find_phy_by_wwn_impl(pmcs_phy_t *phyp, uint8_t *wwn)
5361 {
5362 	pmcs_phy_t *matched_phy, *cphyp, *nphyp;
5363 
5364 	ASSERT(!mutex_owned(&phyp->phy_lock));
5365 
5366 	while (phyp) {
5367 		pmcs_lock_phy(phyp);
5368 
5369 		if (phyp->valid_device_id) {
5370 			if (memcmp(phyp->sas_address, wwn, 8) == 0) {
5371 				return (phyp);
5372 			}
5373 		}
5374 
5375 		if (phyp->children) {
5376 			cphyp = phyp->children;
5377 			pmcs_unlock_phy(phyp);
5378 			matched_phy = pmcs_find_phy_by_wwn_impl(cphyp, wwn);
5379 			if (matched_phy) {
5380 				ASSERT(mutex_owned(&matched_phy->phy_lock));
5381 				return (matched_phy);
5382 			}
5383 			pmcs_lock_phy(phyp);
5384 		}
5385 
5386 		/*
5387 		 * Only iterate through non-root PHYs
5388 		 */
5389 		if (IS_ROOT_PHY(phyp)) {
5390 			pmcs_unlock_phy(phyp);
5391 			phyp = NULL;
5392 		} else {
5393 			nphyp = phyp->sibling;
5394 			pmcs_unlock_phy(phyp);
5395 			phyp = nphyp;
5396 		}
5397 	}
5398 
5399 	return (NULL);
5400 }
5401 
5402 pmcs_phy_t *
5403 pmcs_find_phy_by_wwn(pmcs_hw_t *pwp, uint64_t wwn)
5404 {
5405 	uint8_t ebstr[8];
5406 	pmcs_phy_t *pptr, *matched_phy;
5407 
5408 	pmcs_wwn2barray(wwn, ebstr);
5409 
5410 	pptr = pwp->root_phys;
5411 	while (pptr) {
5412 		matched_phy = pmcs_find_phy_by_wwn_impl(pptr, ebstr);
5413 		if (matched_phy) {
5414 			ASSERT(mutex_owned(&matched_phy->phy_lock));
5415 			return (matched_phy);
5416 		}
5417 
5418 		pptr = pptr->sibling;
5419 	}
5420 
5421 	return (NULL);
5422 }
5423 
5424 
5425 /*
5426  * pmcs_find_phy_by_sas_address
5427  *
5428  * Find a PHY that both matches "sas_addr" and is on "iport".
5429  * If a matching PHY is found, it is returned locked.
5430  */
5431 pmcs_phy_t *
5432 pmcs_find_phy_by_sas_address(pmcs_hw_t *pwp, pmcs_iport_t *iport,
5433     pmcs_phy_t *root, char *sas_addr)
5434 {
5435 	int ua_form = 1;
5436 	uint64_t wwn;
5437 	char addr[PMCS_MAX_UA_SIZE];
5438 	pmcs_phy_t *pptr, *pnext, *pchild;
5439 
5440 	if (root == NULL) {
5441 		pptr = pwp->root_phys;
5442 	} else {
5443 		pptr = root;
5444 	}
5445 
5446 	while (pptr) {
5447 		pmcs_lock_phy(pptr);
5448 		/*
5449 		 * If the PHY is dead or does not have a valid device ID,
5450 		 * skip it.
5451 		 */
5452 		if ((pptr->dead) || (!pptr->valid_device_id)) {
5453 			goto next_phy;
5454 		}
5455 
5456 		if (pptr->iport != iport) {
5457 			goto next_phy;
5458 		}
5459 
5460 		wwn = pmcs_barray2wwn(pptr->sas_address);
5461 		(void *) scsi_wwn_to_wwnstr(wwn, ua_form, addr);
5462 		if (strncmp(addr, sas_addr, strlen(addr)) == 0) {
5463 			return (pptr);
5464 		}
5465 
5466 		if (pptr->children) {
5467 			pchild = pptr->children;
5468 			pmcs_unlock_phy(pptr);
5469 			pnext = pmcs_find_phy_by_sas_address(pwp, iport, pchild,
5470 			    sas_addr);
5471 			if (pnext) {
5472 				return (pnext);
5473 			}
5474 			pmcs_lock_phy(pptr);
5475 		}
5476 
5477 next_phy:
5478 		pnext = pptr->sibling;
5479 		pmcs_unlock_phy(pptr);
5480 		pptr = pnext;
5481 	}
5482 
5483 	return (NULL);
5484 }
5485 
5486 void
5487 pmcs_fis_dump(pmcs_hw_t *pwp, fis_t fis)
5488 {
5489 	switch (fis[0] & 0xff) {
5490 	case FIS_REG_H2DEV:
5491 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5492 		    "FIS REGISTER HOST TO DEVICE: "
5493 		    "OP=0x%02x Feature=0x%04x Count=0x%04x Device=0x%02x "
5494 		    "LBA=%llu", BYTE2(fis[0]), BYTE3(fis[2]) << 8 |
5495 		    BYTE3(fis[0]), WORD0(fis[3]), BYTE3(fis[1]),
5496 		    (unsigned long long)
5497 		    (((uint64_t)fis[2] & 0x00ffffff) << 24 |
5498 		    ((uint64_t)fis[1] & 0x00ffffff)));
5499 		break;
5500 	case FIS_REG_D2H:
5501 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5502 		    "FIS REGISTER DEVICE TO HOST: Status=0x%02x "
5503 		    "Error=0x%02x Dev=0x%02x Count=0x%04x LBA=%llu",
5504 		    BYTE2(fis[0]), BYTE3(fis[0]), BYTE3(fis[1]), WORD0(fis[3]),
5505 		    (unsigned long long)(((uint64_t)fis[2] & 0x00ffffff) << 24 |
5506 		    ((uint64_t)fis[1] & 0x00ffffff)));
5507 		break;
5508 	default:
5509 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5510 		    "FIS: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
5511 		    fis[0], fis[1], fis[2], fis[3], fis[4], fis[5], fis[6]);
5512 		break;
5513 	}
5514 }
5515 
5516 void
5517 pmcs_print_entry(pmcs_hw_t *pwp, int level, char *msg, void *arg)
5518 {
5519 	uint32_t *mb = arg;
5520 	size_t i;
5521 
5522 	pmcs_prt(pwp, level, NULL, NULL, msg);
5523 	for (i = 0; i < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); i += 4) {
5524 		pmcs_prt(pwp, level, NULL, NULL,
5525 		    "Offset %2lu: 0x%08x 0x%08x 0x%08x 0x%08x",
5526 		    i * sizeof (uint32_t), LE_32(mb[i]),
5527 		    LE_32(mb[i+1]), LE_32(mb[i+2]), LE_32(mb[i+3]));
5528 	}
5529 }
5530 
5531 /*
5532  * If phyp == NULL we're being called from the worker thread, in which
5533  * case we need to check all the PHYs.  In this case, the softstate lock
5534  * will be held.
5535  * If phyp is non-NULL, just issue the spinup release for the specified PHY
5536  * (which will already be locked).
5537  */
5538 void
5539 pmcs_spinup_release(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
5540 {
5541 	uint32_t *msg;
5542 	struct pmcwork *pwrk;
5543 	pmcs_phy_t *tphyp;
5544 
5545 	if (phyp != NULL) {
5546 		ASSERT(mutex_owned(&phyp->phy_lock));
5547 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, NULL,
5548 		    "%s: Issuing spinup release only for PHY %s", __func__,
5549 		    phyp->path);
5550 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5551 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5552 		if (msg == NULL || (pwrk =
5553 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
5554 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5555 			SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
5556 			return;
5557 		}
5558 
5559 		phyp->spinup_hold = 0;
5560 		bzero(msg, PMCS_QENTRY_SIZE);
5561 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5562 		    PMCIN_LOCAL_PHY_CONTROL));
5563 		msg[1] = LE_32(pwrk->htag);
5564 		msg[2] = LE_32((0x10 << 8) | phyp->phynum);
5565 
5566 		pwrk->dtype = phyp->dtype;
5567 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
5568 		mutex_exit(&pwrk->lock);
5569 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5570 		return;
5571 	}
5572 
5573 	ASSERT(mutex_owned(&pwp->lock));
5574 
5575 	tphyp = pwp->root_phys;
5576 	while (tphyp) {
5577 		pmcs_lock_phy(tphyp);
5578 		if (tphyp->spinup_hold == 0) {
5579 			pmcs_unlock_phy(tphyp);
5580 			tphyp = tphyp->sibling;
5581 			continue;
5582 		}
5583 
5584 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, NULL,
5585 		    "%s: Issuing spinup release for PHY %s", __func__,
5586 		    phyp->path);
5587 
5588 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5589 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5590 		if (msg == NULL || (pwrk =
5591 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
5592 			pmcs_unlock_phy(tphyp);
5593 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5594 			SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
5595 			break;
5596 		}
5597 
5598 		tphyp->spinup_hold = 0;
5599 		bzero(msg, PMCS_QENTRY_SIZE);
5600 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5601 		    PMCIN_LOCAL_PHY_CONTROL));
5602 		msg[1] = LE_32(pwrk->htag);
5603 		msg[2] = LE_32((0x10 << 8) | tphyp->phynum);
5604 
5605 		pwrk->dtype = phyp->dtype;
5606 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
5607 		mutex_exit(&pwrk->lock);
5608 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5609 		pmcs_unlock_phy(tphyp);
5610 
5611 		tphyp = tphyp->sibling;
5612 	}
5613 }
5614 
5615 /*
5616  * Abort commands on dead PHYs and deregister them as well as removing
5617  * the associated targets.
5618  */
5619 static int
5620 pmcs_kill_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
5621 {
5622 	pmcs_phy_t *pnext, *pchild;
5623 	boolean_t remove_device;
5624 	int rval = 0;
5625 
5626 	while (phyp) {
5627 		pmcs_lock_phy(phyp);
5628 		pchild = phyp->children;
5629 		pnext = phyp->sibling;
5630 		pmcs_unlock_phy(phyp);
5631 
5632 		if (pchild) {
5633 			rval = pmcs_kill_devices(pwp, pchild);
5634 			if (rval) {
5635 				return (rval);
5636 			}
5637 		}
5638 
5639 		/*
5640 		 * pmcs_remove_device requires the softstate lock.
5641 		 */
5642 		mutex_enter(&pwp->lock);
5643 		pmcs_lock_phy(phyp);
5644 		if (phyp->dead && phyp->valid_device_id) {
5645 			remove_device = B_TRUE;
5646 		} else {
5647 			remove_device = B_FALSE;
5648 		}
5649 
5650 		if (remove_device) {
5651 			pmcs_remove_device(pwp, phyp);
5652 			mutex_exit(&pwp->lock);
5653 
5654 			rval = pmcs_kill_device(pwp, phyp);
5655 
5656 			if (rval) {
5657 				pmcs_unlock_phy(phyp);
5658 				return (rval);
5659 			}
5660 		} else {
5661 			mutex_exit(&pwp->lock);
5662 		}
5663 
5664 		pmcs_unlock_phy(phyp);
5665 		phyp = pnext;
5666 	}
5667 
5668 	return (rval);
5669 }
5670 
5671 /*
5672  * Called with PHY locked
5673  */
5674 int
5675 pmcs_kill_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
5676 {
5677 	int r, result;
5678 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
5679 	struct pmcwork *pwrk;
5680 
5681 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "kill %s device @ %s",
5682 	    pmcs_get_typename(pptr->dtype), pptr->path);
5683 
5684 	/*
5685 	 * There may be an outstanding ABORT_ALL running, which we wouldn't
5686 	 * know just by checking abort_pending.  We can, however, check
5687 	 * abort_all_start.  If it's non-zero, there is one, and we'll just
5688 	 * sit here and wait for it to complete.  If we don't, we'll remove
5689 	 * the device while there are still commands pending.
5690 	 */
5691 	if (pptr->abort_all_start) {
5692 		while (pptr->abort_all_start) {
5693 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
5694 			    "%s: Waiting for outstanding ABORT_ALL on PHY 0x%p",
5695 			    __func__, (void *)pptr);
5696 			cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
5697 		}
5698 	} else if (pptr->abort_pending) {
5699 		r = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
5700 
5701 		if (r) {
5702 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
5703 			    "%s: ABORT_ALL returned non-zero status (%d) for "
5704 			    "PHY 0x%p", __func__, r, (void *)pptr);
5705 			return (r);
5706 		}
5707 		pptr->abort_pending = 0;
5708 	}
5709 
5710 	if (pptr->valid_device_id == 0) {
5711 		return (0);
5712 	}
5713 
5714 	if ((pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
5715 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
5716 		return (ENOMEM);
5717 	}
5718 	pwrk->arg = msg;
5719 	pwrk->dtype = pptr->dtype;
5720 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5721 	    PMCIN_DEREGISTER_DEVICE_HANDLE));
5722 	msg[1] = LE_32(pwrk->htag);
5723 	msg[2] = LE_32(pptr->device_id);
5724 
5725 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5726 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5727 	if (ptr == NULL) {
5728 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5729 		mutex_exit(&pwrk->lock);
5730 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
5731 		return (ENOMEM);
5732 	}
5733 
5734 	COPY_MESSAGE(ptr, msg, 3);
5735 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
5736 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5737 
5738 	pmcs_unlock_phy(pptr);
5739 	WAIT_FOR(pwrk, 250, result);
5740 	pmcs_lock_phy(pptr);
5741 	pmcs_pwork(pwp, pwrk);
5742 
5743 	if (result) {
5744 		return (ETIMEDOUT);
5745 	}
5746 	status = LE_32(msg[2]);
5747 	if (status != PMCOUT_STATUS_OK) {
5748 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
5749 		    "%s: status 0x%x when trying to deregister device %s",
5750 		    __func__, status, pptr->path);
5751 	}
5752 
5753 	pptr->device_id = PMCS_INVALID_DEVICE_ID;
5754 	PHY_CHANGED(pwp, pptr);
5755 	RESTART_DISCOVERY(pwp);
5756 	pptr->valid_device_id = 0;
5757 	return (0);
5758 }
5759 
5760 /*
5761  * Acknowledge the SAS h/w events that need acknowledgement.
5762  * This is only needed for first level PHYs.
5763  */
5764 void
5765 pmcs_ack_events(pmcs_hw_t *pwp)
5766 {
5767 	uint32_t msg[PMCS_MSG_SIZE], *ptr;
5768 	struct pmcwork *pwrk;
5769 	pmcs_phy_t *pptr;
5770 
5771 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
5772 		pmcs_lock_phy(pptr);
5773 		if (pptr->hw_event_ack == 0) {
5774 			pmcs_unlock_phy(pptr);
5775 			continue;
5776 		}
5777 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5778 		ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5779 
5780 		if ((ptr == NULL) || (pwrk =
5781 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
5782 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5783 			pmcs_unlock_phy(pptr);
5784 			SCHEDULE_WORK(pwp, PMCS_WORK_SAS_HW_ACK);
5785 			break;
5786 		}
5787 
5788 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5789 		    PMCIN_SAW_HW_EVENT_ACK));
5790 		msg[1] = LE_32(pwrk->htag);
5791 		msg[2] = LE_32(pptr->hw_event_ack);
5792 
5793 		mutex_exit(&pwrk->lock);
5794 		pwrk->dtype = pptr->dtype;
5795 		pptr->hw_event_ack = 0;
5796 		COPY_MESSAGE(ptr, msg, 3);
5797 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5798 		pmcs_unlock_phy(pptr);
5799 	}
5800 }
5801 
5802 /*
5803  * Load DMA
5804  */
5805 int
5806 pmcs_dma_load(pmcs_hw_t *pwp, pmcs_cmd_t *sp, uint32_t *msg)
5807 {
5808 	ddi_dma_cookie_t *sg;
5809 	pmcs_dmachunk_t *tc;
5810 	pmcs_dmasgl_t *sgl, *prior;
5811 	int seg, tsc;
5812 	uint64_t sgl_addr;
5813 
5814 	/*
5815 	 * If we have no data segments, we're done.
5816 	 */
5817 	if (CMD2PKT(sp)->pkt_numcookies == 0) {
5818 		return (0);
5819 	}
5820 
5821 	/*
5822 	 * Get the S/G list pointer.
5823 	 */
5824 	sg = CMD2PKT(sp)->pkt_cookies;
5825 
5826 	/*
5827 	 * If we only have one dma segment, we can directly address that
5828 	 * data within the Inbound message itself.
5829 	 */
5830 	if (CMD2PKT(sp)->pkt_numcookies == 1) {
5831 		msg[12] = LE_32(DWORD0(sg->dmac_laddress));
5832 		msg[13] = LE_32(DWORD1(sg->dmac_laddress));
5833 		msg[14] = LE_32(sg->dmac_size);
5834 		msg[15] = 0;
5835 		return (0);
5836 	}
5837 
5838 	/*
5839 	 * Otherwise, we'll need one or more external S/G list chunks.
5840 	 * Get the first one and its dma address into the Inbound message.
5841 	 */
5842 	mutex_enter(&pwp->dma_lock);
5843 	tc = pwp->dma_freelist;
5844 	if (tc == NULL) {
5845 		SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
5846 		mutex_exit(&pwp->dma_lock);
5847 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
5848 		    "%s: out of SG lists", __func__);
5849 		return (-1);
5850 	}
5851 	pwp->dma_freelist = tc->nxt;
5852 	mutex_exit(&pwp->dma_lock);
5853 
5854 	tc->nxt = NULL;
5855 	sp->cmd_clist = tc;
5856 	sgl = tc->chunks;
5857 	(void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
5858 	sgl_addr = tc->addr;
5859 	msg[12] = LE_32(DWORD0(sgl_addr));
5860 	msg[13] = LE_32(DWORD1(sgl_addr));
5861 	msg[14] = 0;
5862 	msg[15] = LE_32(PMCS_DMASGL_EXTENSION);
5863 
5864 	prior = sgl;
5865 	tsc = 0;
5866 
5867 	for (seg = 0; seg < CMD2PKT(sp)->pkt_numcookies; seg++) {
5868 		/*
5869 		 * If the current segment count for this chunk is one less than
5870 		 * the number s/g lists per chunk and we have more than one seg
5871 		 * to go, we need another chunk. Get it, and make sure that the
5872 		 * tail end of the the previous chunk points the new chunk
5873 		 * (if remembering an offset can be called 'pointing to').
5874 		 *
5875 		 * Note that we can store the offset into our command area that
5876 		 * represents the new chunk in the length field of the part
5877 		 * that points the PMC chip at the next chunk- the PMC chip
5878 		 * ignores this field when the EXTENSION bit is set.
5879 		 *
5880 		 * This is required for dma unloads later.
5881 		 */
5882 		if (tsc == (PMCS_SGL_NCHUNKS - 1) &&
5883 		    seg < (CMD2PKT(sp)->pkt_numcookies - 1)) {
5884 			mutex_enter(&pwp->dma_lock);
5885 			tc = pwp->dma_freelist;
5886 			if (tc == NULL) {
5887 				SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
5888 				mutex_exit(&pwp->dma_lock);
5889 				pmcs_dma_unload(pwp, sp);
5890 				pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
5891 				    "%s: out of SG lists", __func__);
5892 				return (-1);
5893 			}
5894 			pwp->dma_freelist = tc->nxt;
5895 			tc->nxt = sp->cmd_clist;
5896 			mutex_exit(&pwp->dma_lock);
5897 
5898 			sp->cmd_clist = tc;
5899 			(void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
5900 			sgl = tc->chunks;
5901 			sgl_addr = tc->addr;
5902 			prior[PMCS_SGL_NCHUNKS-1].sglal =
5903 			    LE_32(DWORD0(sgl_addr));
5904 			prior[PMCS_SGL_NCHUNKS-1].sglah =
5905 			    LE_32(DWORD1(sgl_addr));
5906 			prior[PMCS_SGL_NCHUNKS-1].sglen = 0;
5907 			prior[PMCS_SGL_NCHUNKS-1].flags =
5908 			    LE_32(PMCS_DMASGL_EXTENSION);
5909 			prior = sgl;
5910 			tsc = 0;
5911 		}
5912 		sgl[tsc].sglal = LE_32(DWORD0(sg->dmac_laddress));
5913 		sgl[tsc].sglah = LE_32(DWORD1(sg->dmac_laddress));
5914 		sgl[tsc].sglen = LE_32(sg->dmac_size);
5915 		sgl[tsc++].flags = 0;
5916 		sg++;
5917 	}
5918 	return (0);
5919 }
5920 
5921 /*
5922  * Unload DMA
5923  */
5924 void
5925 pmcs_dma_unload(pmcs_hw_t *pwp, pmcs_cmd_t *sp)
5926 {
5927 	pmcs_dmachunk_t *cp;
5928 
5929 	mutex_enter(&pwp->dma_lock);
5930 	while ((cp = sp->cmd_clist) != NULL) {
5931 		sp->cmd_clist = cp->nxt;
5932 		cp->nxt = pwp->dma_freelist;
5933 		pwp->dma_freelist = cp;
5934 	}
5935 	mutex_exit(&pwp->dma_lock);
5936 }
5937 
5938 /*
5939  * Take a chunk of consistent memory that has just been allocated and inserted
5940  * into the cip indices and prepare it for DMA chunk usage and add it to the
5941  * freelist.
5942  *
5943  * Called with dma_lock locked (except during attach when it's unnecessary)
5944  */
5945 void
5946 pmcs_idma_chunks(pmcs_hw_t *pwp, pmcs_dmachunk_t *dcp,
5947     pmcs_chunk_t *pchunk, unsigned long lim)
5948 {
5949 	unsigned long off, n;
5950 	pmcs_dmachunk_t *np = dcp;
5951 	pmcs_chunk_t *tmp_chunk;
5952 
5953 	if (pwp->dma_chunklist == NULL) {
5954 		pwp->dma_chunklist = pchunk;
5955 	} else {
5956 		tmp_chunk = pwp->dma_chunklist;
5957 		while (tmp_chunk->next) {
5958 			tmp_chunk = tmp_chunk->next;
5959 		}
5960 		tmp_chunk->next = pchunk;
5961 	}
5962 
5963 	/*
5964 	 * Install offsets into chunk lists.
5965 	 */
5966 	for (n = 0, off = 0; off < lim; off += PMCS_SGL_CHUNKSZ, n++) {
5967 		np->chunks = (void *)&pchunk->addrp[off];
5968 		np->addr = pchunk->dma_addr + off;
5969 		np->acc_handle = pchunk->acc_handle;
5970 		np->dma_handle = pchunk->dma_handle;
5971 		if ((off + PMCS_SGL_CHUNKSZ) < lim) {
5972 			np = np->nxt;
5973 		}
5974 	}
5975 	np->nxt = pwp->dma_freelist;
5976 	pwp->dma_freelist = dcp;
5977 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
5978 	    "added %lu DMA chunks ", n);
5979 }
5980 
5981 /*
5982  * Change the value of the interrupt coalescing timer.  This is done currently
5983  * only for I/O completions.  If we're using the "auto clear" feature, it can
5984  * be turned back on when interrupt coalescing is turned off and must be
5985  * turned off when the coalescing timer is on.
5986  * NOTE: PMCS_MSIX_GENERAL and PMCS_OQ_IODONE are the same value.  As long
5987  * as that's true, we don't need to distinguish between them.
5988  */
5989 
5990 void
5991 pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj)
5992 {
5993 	if (adj == DECREASE_TIMER) {
5994 		/* If the timer is already off, nothing to do. */
5995 		if (pwp->io_intr_coal.timer_on == B_FALSE) {
5996 			return;
5997 		}
5998 
5999 		pwp->io_intr_coal.intr_coal_timer -= PMCS_COAL_TIMER_GRAN;
6000 
6001 		if (pwp->io_intr_coal.intr_coal_timer == 0) {
6002 			/* Disable the timer */
6003 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0);
6004 
6005 			if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
6006 				pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
6007 				    pwp->odb_auto_clear);
6008 			}
6009 
6010 			pwp->io_intr_coal.timer_on = B_FALSE;
6011 			pwp->io_intr_coal.max_io_completions = B_FALSE;
6012 			pwp->io_intr_coal.num_intrs = 0;
6013 			pwp->io_intr_coal.int_cleared = B_FALSE;
6014 			pwp->io_intr_coal.num_io_completions = 0;
6015 
6016 			DTRACE_PROBE1(pmcs__intr__coalesce__timer__off,
6017 			    pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
6018 		} else {
6019 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
6020 			    pwp->io_intr_coal.intr_coal_timer);
6021 		}
6022 	} else {
6023 		/*
6024 		 * If the timer isn't on yet, do the setup for it now.
6025 		 */
6026 		if (pwp->io_intr_coal.timer_on == B_FALSE) {
6027 			/* If auto clear is being used, turn it off. */
6028 			if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
6029 				pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
6030 				    (pwp->odb_auto_clear &
6031 				    ~(1 << PMCS_MSIX_IODONE)));
6032 			}
6033 
6034 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL,
6035 			    (1 << PMCS_MSIX_IODONE));
6036 			pwp->io_intr_coal.timer_on = B_TRUE;
6037 			pwp->io_intr_coal.intr_coal_timer =
6038 			    PMCS_COAL_TIMER_GRAN;
6039 
6040 			DTRACE_PROBE1(pmcs__intr__coalesce__timer__on,
6041 			    pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
6042 		} else {
6043 			pwp->io_intr_coal.intr_coal_timer +=
6044 			    PMCS_COAL_TIMER_GRAN;
6045 		}
6046 
6047 		if (pwp->io_intr_coal.intr_coal_timer > PMCS_MAX_COAL_TIMER) {
6048 			pwp->io_intr_coal.intr_coal_timer = PMCS_MAX_COAL_TIMER;
6049 		}
6050 
6051 		pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
6052 		    pwp->io_intr_coal.intr_coal_timer);
6053 	}
6054 
6055 	/*
6056 	 * Adjust the interrupt threshold based on the current timer value
6057 	 */
6058 	pwp->io_intr_coal.intr_threshold =
6059 	    PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
6060 	    (pwp->io_intr_coal.intr_latency +
6061 	    (pwp->io_intr_coal.intr_coal_timer * 1000)));
6062 }
6063 
6064 /*
6065  * Register Access functions
6066  */
6067 uint32_t
6068 pmcs_rd_iqci(pmcs_hw_t *pwp, uint32_t qnum)
6069 {
6070 	uint32_t iqci;
6071 
6072 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
6073 	    DDI_SUCCESS) {
6074 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6075 		    "%s: ddi_dma_sync failed?", __func__);
6076 	}
6077 
6078 	iqci = LE_32(
6079 	    ((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2]);
6080 
6081 	return (iqci);
6082 }
6083 
6084 uint32_t
6085 pmcs_rd_oqpi(pmcs_hw_t *pwp, uint32_t qnum)
6086 {
6087 	uint32_t oqpi;
6088 
6089 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
6090 	    DDI_SUCCESS) {
6091 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6092 		    "%s: ddi_dma_sync failed?", __func__);
6093 	}
6094 
6095 	oqpi = LE_32(
6096 	    ((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2]);
6097 
6098 	return (oqpi);
6099 }
6100 
6101 uint32_t
6102 pmcs_rd_gsm_reg(pmcs_hw_t *pwp, uint32_t off)
6103 {
6104 	uint32_t rv, newaxil, oldaxil;
6105 
6106 	newaxil = off & ~GSM_BASE_MASK;
6107 	off &= GSM_BASE_MASK;
6108 	mutex_enter(&pwp->axil_lock);
6109 	oldaxil = ddi_get32(pwp->top_acc_handle,
6110 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
6111 	ddi_put32(pwp->top_acc_handle,
6112 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
6113 	drv_usecwait(10);
6114 	if (ddi_get32(pwp->top_acc_handle,
6115 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
6116 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6117 		    "AXIL register update failed");
6118 	}
6119 	rv = ddi_get32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2]);
6120 	ddi_put32(pwp->top_acc_handle,
6121 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
6122 	drv_usecwait(10);
6123 	if (ddi_get32(pwp->top_acc_handle,
6124 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
6125 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6126 		    "AXIL register restore failed");
6127 	}
6128 	mutex_exit(&pwp->axil_lock);
6129 	return (rv);
6130 }
6131 
6132 void
6133 pmcs_wr_gsm_reg(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6134 {
6135 	uint32_t newaxil, oldaxil;
6136 
6137 	newaxil = off & ~GSM_BASE_MASK;
6138 	off &= GSM_BASE_MASK;
6139 	mutex_enter(&pwp->axil_lock);
6140 	oldaxil = ddi_get32(pwp->top_acc_handle,
6141 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
6142 	ddi_put32(pwp->top_acc_handle,
6143 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
6144 	drv_usecwait(10);
6145 	if (ddi_get32(pwp->top_acc_handle,
6146 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
6147 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6148 		    "AXIL register update failed");
6149 	}
6150 	ddi_put32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2], val);
6151 	ddi_put32(pwp->top_acc_handle,
6152 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
6153 	drv_usecwait(10);
6154 	if (ddi_get32(pwp->top_acc_handle,
6155 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
6156 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6157 		    "AXIL register restore failed");
6158 	}
6159 	mutex_exit(&pwp->axil_lock);
6160 }
6161 
6162 uint32_t
6163 pmcs_rd_topunit(pmcs_hw_t *pwp, uint32_t off)
6164 {
6165 	switch (off) {
6166 	case PMCS_SPC_RESET:
6167 	case PMCS_SPC_BOOT_STRAP:
6168 	case PMCS_SPC_DEVICE_ID:
6169 	case PMCS_DEVICE_REVISION:
6170 		off = pmcs_rd_gsm_reg(pwp, off);
6171 		break;
6172 	default:
6173 		off = ddi_get32(pwp->top_acc_handle,
6174 		    &pwp->top_regs[off >> 2]);
6175 		break;
6176 	}
6177 	return (off);
6178 }
6179 
6180 void
6181 pmcs_wr_topunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6182 {
6183 	switch (off) {
6184 	case PMCS_SPC_RESET:
6185 	case PMCS_DEVICE_REVISION:
6186 		pmcs_wr_gsm_reg(pwp, off, val);
6187 		break;
6188 	default:
6189 		ddi_put32(pwp->top_acc_handle, &pwp->top_regs[off >> 2], val);
6190 		break;
6191 	}
6192 }
6193 
6194 uint32_t
6195 pmcs_rd_msgunit(pmcs_hw_t *pwp, uint32_t off)
6196 {
6197 	return (ddi_get32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2]));
6198 }
6199 
6200 uint32_t
6201 pmcs_rd_mpi_tbl(pmcs_hw_t *pwp, uint32_t off)
6202 {
6203 	return (ddi_get32(pwp->mpi_acc_handle,
6204 	    &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2]));
6205 }
6206 
6207 uint32_t
6208 pmcs_rd_gst_tbl(pmcs_hw_t *pwp, uint32_t off)
6209 {
6210 	return (ddi_get32(pwp->mpi_acc_handle,
6211 	    &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2]));
6212 }
6213 
6214 uint32_t
6215 pmcs_rd_iqc_tbl(pmcs_hw_t *pwp, uint32_t off)
6216 {
6217 	return (ddi_get32(pwp->mpi_acc_handle,
6218 	    &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2]));
6219 }
6220 
6221 uint32_t
6222 pmcs_rd_oqc_tbl(pmcs_hw_t *pwp, uint32_t off)
6223 {
6224 	return (ddi_get32(pwp->mpi_acc_handle,
6225 	    &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2]));
6226 }
6227 
6228 uint32_t
6229 pmcs_rd_iqpi(pmcs_hw_t *pwp, uint32_t qnum)
6230 {
6231 	return (ddi_get32(pwp->mpi_acc_handle,
6232 	    &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2]));
6233 }
6234 
6235 uint32_t
6236 pmcs_rd_oqci(pmcs_hw_t *pwp, uint32_t qnum)
6237 {
6238 	return (ddi_get32(pwp->mpi_acc_handle,
6239 	    &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2]));
6240 }
6241 
6242 void
6243 pmcs_wr_msgunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6244 {
6245 	ddi_put32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2], val);
6246 }
6247 
6248 void
6249 pmcs_wr_mpi_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6250 {
6251 	ddi_put32(pwp->mpi_acc_handle,
6252 	    &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2], (val));
6253 }
6254 
6255 void
6256 pmcs_wr_gst_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6257 {
6258 	ddi_put32(pwp->mpi_acc_handle,
6259 	    &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2], val);
6260 }
6261 
6262 void
6263 pmcs_wr_iqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6264 {
6265 	ddi_put32(pwp->mpi_acc_handle,
6266 	    &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2], val);
6267 }
6268 
6269 void
6270 pmcs_wr_oqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6271 {
6272 	ddi_put32(pwp->mpi_acc_handle,
6273 	    &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2], val);
6274 }
6275 
6276 void
6277 pmcs_wr_iqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6278 {
6279 	((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2] = val;
6280 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
6281 	    DDI_SUCCESS) {
6282 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6283 		    "%s: ddi_dma_sync failed?", __func__);
6284 	}
6285 }
6286 
6287 void
6288 pmcs_wr_iqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6289 {
6290 	ddi_put32(pwp->mpi_acc_handle,
6291 	    &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2], val);
6292 }
6293 
6294 void
6295 pmcs_wr_oqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6296 {
6297 	ddi_put32(pwp->mpi_acc_handle,
6298 	    &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2], val);
6299 }
6300 
6301 void
6302 pmcs_wr_oqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6303 {
6304 	((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2] = val;
6305 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
6306 	    DDI_SUCCESS) {
6307 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6308 		    "%s: ddi_dma_sync failed?", __func__);
6309 	}
6310 }
6311 
6312 /*
6313  * Check the status value of an outbound IOMB and report anything bad
6314  */
6315 
6316 void
6317 pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb)
6318 {
6319 	uint16_t 	opcode;
6320 	int		offset;
6321 
6322 	if (iomb == NULL) {
6323 		return;
6324 	}
6325 
6326 	opcode = LE_32(iomb[0]) & 0xfff;
6327 
6328 	switch (opcode) {
6329 		/*
6330 		 * The following have no status field, so ignore them
6331 		 */
6332 	case PMCOUT_ECHO:
6333 	case PMCOUT_SAS_HW_EVENT:
6334 	case PMCOUT_GET_DEVICE_HANDLE:
6335 	case PMCOUT_SATA_EVENT:
6336 	case PMCOUT_SSP_EVENT:
6337 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
6338 	case PMCOUT_SMP_REQUEST_RECEIVED:
6339 	case PMCOUT_GPIO:
6340 	case PMCOUT_GPIO_EVENT:
6341 	case PMCOUT_GET_TIME_STAMP:
6342 	case PMCOUT_SKIP_ENTRIES:
6343 	case PMCOUT_GET_NVMD_DATA:	/* Actually lower 16 bits of word 3 */
6344 	case PMCOUT_SET_NVMD_DATA:	/* but ignore - we don't use these */
6345 	case PMCOUT_DEVICE_HANDLE_REMOVED:
6346 	case PMCOUT_SSP_REQUEST_RECEIVED:
6347 		return;
6348 
6349 	case PMCOUT_GENERAL_EVENT:
6350 		offset = 1;
6351 		break;
6352 
6353 	case PMCOUT_SSP_COMPLETION:
6354 	case PMCOUT_SMP_COMPLETION:
6355 	case PMCOUT_DEVICE_REGISTRATION:
6356 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
6357 	case PMCOUT_SATA_COMPLETION:
6358 	case PMCOUT_DEVICE_INFO:
6359 	case PMCOUT_FW_FLASH_UPDATE:
6360 	case PMCOUT_SSP_ABORT:
6361 	case PMCOUT_SATA_ABORT:
6362 	case PMCOUT_SAS_DIAG_MODE_START_END:
6363 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
6364 	case PMCOUT_SMP_ABORT:
6365 	case PMCOUT_SET_DEVICE_STATE:
6366 	case PMCOUT_GET_DEVICE_STATE:
6367 	case PMCOUT_SET_DEVICE_INFO:
6368 		offset = 2;
6369 		break;
6370 
6371 	case PMCOUT_LOCAL_PHY_CONTROL:
6372 	case PMCOUT_SAS_DIAG_EXECUTE:
6373 	case PMCOUT_PORT_CONTROL:
6374 		offset = 3;
6375 		break;
6376 
6377 	case PMCOUT_GET_INFO:
6378 	case PMCOUT_GET_VPD:
6379 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
6380 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
6381 	case PMCOUT_SET_VPD:
6382 	case PMCOUT_TWI:
6383 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6384 		    "Got response for deprecated opcode", iomb);
6385 		return;
6386 
6387 	default:
6388 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6389 		    "Got response for unknown opcode", iomb);
6390 		return;
6391 	}
6392 
6393 	if (LE_32(iomb[offset]) != PMCOUT_STATUS_OK) {
6394 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6395 		    "bad status on TAG_TYPE_NONE command", iomb);
6396 	}
6397 }
6398 
6399 /*
6400  * Called with statlock held
6401  */
6402 void
6403 pmcs_clear_xp(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
6404 {
6405 	_NOTE(ARGUNUSED(pwp));
6406 
6407 	ASSERT(mutex_owned(&xp->statlock));
6408 
6409 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp, "%s: Device 0x%p is gone.",
6410 	    __func__, (void *)xp);
6411 
6412 	/*
6413 	 * Clear the dip now.  This keeps pmcs_remove_device from attempting
6414 	 * to call us on the same device while we're still flushing queues.
6415 	 * The only side effect is we can no longer update SM-HBA properties,
6416 	 * but this device is going away anyway, so no matter.
6417 	 */
6418 	xp->dip = NULL;
6419 
6420 	xp->special_running = 0;
6421 	xp->recovering = 0;
6422 	xp->recover_wait = 0;
6423 	xp->draining = 0;
6424 	xp->new = 0;
6425 	xp->assigned = 0;
6426 	xp->dev_state = 0;
6427 	xp->tagmap = 0;
6428 	xp->dev_gone = 1;
6429 	xp->event_recovery = 0;
6430 	xp->dtype = NOTHING;
6431 	xp->wq_recovery_tail = NULL;
6432 	/* Don't clear xp->phy */
6433 	/* Don't clear xp->actv_cnt */
6434 
6435 	/*
6436 	 * Flush all target queues
6437 	 */
6438 	pmcs_flush_target_queues(pwp, xp, PMCS_TGT_ALL_QUEUES);
6439 }
6440 
6441 static int
6442 pmcs_smp_function_result(pmcs_hw_t *pwp, smp_response_frame_t *srf)
6443 {
6444 	int result = srf->srf_result;
6445 
6446 	switch (result) {
6447 	case SMP_RES_UNKNOWN_FUNCTION:
6448 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6449 		    "%s: SMP DISCOVER Response "
6450 		    "Function Result: Unknown SMP Function(0x%x)",
6451 		    __func__, result);
6452 		break;
6453 	case SMP_RES_FUNCTION_FAILED:
6454 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6455 		    "%s: SMP DISCOVER Response "
6456 		    "Function Result: SMP Function Failed(0x%x)",
6457 		    __func__, result);
6458 		break;
6459 	case SMP_RES_INVALID_REQUEST_FRAME_LENGTH:
6460 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6461 		    "%s: SMP DISCOVER Response "
6462 		    "Function Result: Invalid Request Frame Length(0x%x)",
6463 		    __func__, result);
6464 		break;
6465 	case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST:
6466 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6467 		    "%s: SMP DISCOVER Response "
6468 		    "Function Result: Incomplete Descriptor List(0x%x)",
6469 		    __func__, result);
6470 		break;
6471 	case SMP_RES_PHY_DOES_NOT_EXIST:
6472 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6473 		    "%s: SMP DISCOVER Response "
6474 		    "Function Result: PHY does not exist(0x%x)",
6475 		    __func__, result);
6476 		break;
6477 	case SMP_RES_PHY_VACANT:
6478 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6479 		    "%s: SMP DISCOVER Response "
6480 		    "Function Result: PHY Vacant(0x%x)",
6481 		    __func__, result);
6482 		break;
6483 	default:
6484 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6485 		    "%s: SMP DISCOVER Response "
6486 		    "Function Result: (0x%x)",
6487 		    __func__, result);
6488 		break;
6489 	}
6490 
6491 	return (result);
6492 }
6493 
6494 /*
6495  * Do all the repetitive stuff necessary to setup for DMA
6496  *
6497  * pwp: Used for dip
6498  * dma_attr: ddi_dma_attr_t to use for the mapping
6499  * acch: ddi_acc_handle_t to use for the mapping
6500  * dmah: ddi_dma_handle_t to use
6501  * length: Amount of memory for mapping
6502  * kvp: Pointer filled in with kernel virtual address on successful return
6503  * dma_addr: Pointer filled in with DMA address on successful return
6504  */
6505 boolean_t
6506 pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr, ddi_acc_handle_t *acch,
6507     ddi_dma_handle_t *dmah, size_t length, caddr_t *kvp, uint64_t *dma_addr)
6508 {
6509 	dev_info_t		*dip = pwp->dip;
6510 	ddi_dma_cookie_t	cookie;
6511 	size_t			real_length;
6512 	uint_t			ddma_flag = DDI_DMA_CONSISTENT;
6513 	uint_t			ddabh_flag = DDI_DMA_CONSISTENT | DDI_DMA_RDWR;
6514 	uint_t			cookie_cnt;
6515 	ddi_device_acc_attr_t	mattr = {
6516 		DDI_DEVICE_ATTR_V0,
6517 		DDI_NEVERSWAP_ACC,
6518 		DDI_STRICTORDER_ACC,
6519 		DDI_DEFAULT_ACC
6520 	};
6521 
6522 	*acch = NULL;
6523 	*dmah = NULL;
6524 
6525 	if (ddi_dma_alloc_handle(dip, dma_attr, DDI_DMA_SLEEP, NULL, dmah) !=
6526 	    DDI_SUCCESS) {
6527 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6528 		    "Failed to allocate DMA handle");
6529 		return (B_FALSE);
6530 	}
6531 
6532 	if (ddi_dma_mem_alloc(*dmah, length, &mattr, ddma_flag, DDI_DMA_SLEEP,
6533 	    NULL, kvp, &real_length, acch) != DDI_SUCCESS) {
6534 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6535 		    "Failed to allocate DMA mem");
6536 		ddi_dma_free_handle(dmah);
6537 		*dmah = NULL;
6538 		return (B_FALSE);
6539 	}
6540 
6541 	if (ddi_dma_addr_bind_handle(*dmah, NULL, *kvp, real_length,
6542 	    ddabh_flag, DDI_DMA_SLEEP, NULL, &cookie, &cookie_cnt)
6543 	    != DDI_DMA_MAPPED) {
6544 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Failed to bind DMA");
6545 		ddi_dma_free_handle(dmah);
6546 		ddi_dma_mem_free(acch);
6547 		*dmah = NULL;
6548 		*acch = NULL;
6549 		return (B_FALSE);
6550 	}
6551 
6552 	if (cookie_cnt != 1) {
6553 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Multiple cookies");
6554 		if (ddi_dma_unbind_handle(*dmah) != DDI_SUCCESS) {
6555 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Condition "
6556 			    "failed at %s():%d", __func__, __LINE__);
6557 		}
6558 		ddi_dma_free_handle(dmah);
6559 		ddi_dma_mem_free(acch);
6560 		*dmah = NULL;
6561 		*acch = NULL;
6562 		return (B_FALSE);
6563 	}
6564 
6565 	*dma_addr = cookie.dmac_laddress;
6566 
6567 	return (B_TRUE);
6568 }
6569 
6570 /*
6571  * Flush requested queues for a particular target.  Called with statlock held
6572  */
6573 void
6574 pmcs_flush_target_queues(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt, uint8_t queues)
6575 {
6576 	pmcs_cmd_t	*sp;
6577 	pmcwork_t	*pwrk;
6578 
6579 	ASSERT(pwp != NULL);
6580 	ASSERT(tgt != NULL);
6581 
6582 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, tgt,
6583 	    "%s: Flushing queues (%d) for target 0x%p", __func__,
6584 	    queues, (void *)tgt);
6585 
6586 	/*
6587 	 * Commands on the wait queue (or the special queue below) don't have
6588 	 * work structures associated with them.
6589 	 */
6590 	if (queues & PMCS_TGT_WAIT_QUEUE) {
6591 		mutex_enter(&tgt->wqlock);
6592 		while ((sp = STAILQ_FIRST(&tgt->wq)) != NULL) {
6593 			STAILQ_REMOVE(&tgt->wq, sp, pmcs_cmd, cmd_next);
6594 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, tgt,
6595 			    "%s: Removing cmd 0x%p from wq for target 0x%p",
6596 			    __func__, (void *)sp, (void *)tgt);
6597 			CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
6598 			CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
6599 			mutex_exit(&tgt->wqlock);
6600 			pmcs_dma_unload(pwp, sp);
6601 			mutex_enter(&pwp->cq_lock);
6602 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
6603 			mutex_exit(&pwp->cq_lock);
6604 			mutex_enter(&tgt->wqlock);
6605 		}
6606 		mutex_exit(&tgt->wqlock);
6607 	}
6608 
6609 	/*
6610 	 * Commands on the active queue will have work structures associated
6611 	 * with them.
6612 	 */
6613 	if (queues & PMCS_TGT_ACTIVE_QUEUE) {
6614 		mutex_enter(&tgt->aqlock);
6615 		while ((sp = STAILQ_FIRST(&tgt->aq)) != NULL) {
6616 			STAILQ_REMOVE(&tgt->aq, sp, pmcs_cmd, cmd_next);
6617 			pwrk = pmcs_tag2wp(pwp, sp->cmd_tag);
6618 			mutex_exit(&tgt->aqlock);
6619 			mutex_exit(&tgt->statlock);
6620 			/*
6621 			 * If we found a work structure, mark it as dead
6622 			 * and complete it
6623 			 */
6624 			if (pwrk != NULL) {
6625 				pwrk->dead = 1;
6626 				CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
6627 				CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
6628 				pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
6629 			}
6630 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, tgt,
6631 			    "%s: Removing cmd 0x%p from aq for target 0x%p",
6632 			    __func__, (void *)sp, (void *)tgt);
6633 			pmcs_dma_unload(pwp, sp);
6634 			mutex_enter(&pwp->cq_lock);
6635 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
6636 			mutex_exit(&pwp->cq_lock);
6637 			mutex_enter(&tgt->aqlock);
6638 			mutex_enter(&tgt->statlock);
6639 		}
6640 		mutex_exit(&tgt->aqlock);
6641 	}
6642 
6643 	if (queues & PMCS_TGT_SPECIAL_QUEUE) {
6644 		while ((sp = STAILQ_FIRST(&tgt->sq)) != NULL) {
6645 			STAILQ_REMOVE(&tgt->sq, sp, pmcs_cmd, cmd_next);
6646 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, tgt,
6647 			    "%s: Removing cmd 0x%p from sq for target 0x%p",
6648 			    __func__, (void *)sp, (void *)tgt);
6649 			CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
6650 			CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
6651 			pmcs_dma_unload(pwp, sp);
6652 			mutex_enter(&pwp->cq_lock);
6653 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
6654 			mutex_exit(&pwp->cq_lock);
6655 		}
6656 	}
6657 }
6658 
6659 void
6660 pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
6661     size_t amt)
6662 {
6663 	switch (PMCS_TAG_TYPE(pwrk->htag)) {
6664 	case PMCS_TAG_TYPE_CBACK:
6665 	{
6666 		pmcs_cb_t callback = (pmcs_cb_t)pwrk->ptr;
6667 		(*callback)(pwp, pwrk, iomb);
6668 		break;
6669 	}
6670 	case PMCS_TAG_TYPE_WAIT:
6671 		if (pwrk->arg && iomb && amt) {
6672 			(void) memcpy(pwrk->arg, iomb, amt);
6673 		}
6674 		cv_signal(&pwrk->sleep_cv);
6675 		mutex_exit(&pwrk->lock);
6676 		break;
6677 	case PMCS_TAG_TYPE_NONE:
6678 #ifdef DEBUG
6679 		pmcs_check_iomb_status(pwp, iomb);
6680 #endif
6681 		pmcs_pwork(pwp, pwrk);
6682 		break;
6683 	default:
6684 		/*
6685 		 * We will leak a structure here if we don't know
6686 		 * what happened
6687 		 */
6688 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6689 		    "%s: Unknown PMCS_TAG_TYPE (%x)",
6690 		    __func__, PMCS_TAG_TYPE(pwrk->htag));
6691 		break;
6692 	}
6693 }
6694 
6695 /*
6696  * Determine if iport still has targets. During detach(9E), if SCSA is
6697  * successfull in its guarantee of tran_tgt_free(9E) before detach(9E),
6698  * this should always return B_FALSE.
6699  */
6700 boolean_t
6701 pmcs_iport_has_targets(pmcs_hw_t *pwp, pmcs_iport_t *iport)
6702 {
6703 	pmcs_xscsi_t *xp;
6704 	int i;
6705 
6706 	mutex_enter(&pwp->lock);
6707 
6708 	if (!pwp->targets || !pwp->max_dev) {
6709 		mutex_exit(&pwp->lock);
6710 		return (B_FALSE);
6711 	}
6712 
6713 	for (i = 0; i < pwp->max_dev; i++) {
6714 		xp = pwp->targets[i];
6715 		if ((xp == NULL) || (xp->phy == NULL) ||
6716 		    (xp->phy->iport != iport)) {
6717 			continue;
6718 		}
6719 
6720 		mutex_exit(&pwp->lock);
6721 		return (B_TRUE);
6722 	}
6723 
6724 	mutex_exit(&pwp->lock);
6725 	return (B_FALSE);
6726 }
6727 
6728 /*
6729  * Called with softstate lock held
6730  */
6731 void
6732 pmcs_destroy_target(pmcs_xscsi_t *target)
6733 {
6734 	pmcs_hw_t *pwp = target->pwp;
6735 	pmcs_iport_t *iport;
6736 
6737 	ASSERT(pwp);
6738 	ASSERT(mutex_owned(&pwp->lock));
6739 
6740 	if (!target->ua) {
6741 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, target,
6742 		    "%s: target %p iport address is null",
6743 		    __func__, (void *)target);
6744 	}
6745 
6746 	iport = pmcs_get_iport_by_ua(pwp, target->ua);
6747 	if (iport == NULL) {
6748 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, target,
6749 		    "%s: no iport associated with tgt(0x%p)",
6750 		    __func__, (void *)target);
6751 		return;
6752 	}
6753 
6754 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, target,
6755 	    "%s: free target %p", __func__, (void *)target);
6756 	if (target->ua) {
6757 		strfree(target->ua);
6758 	}
6759 
6760 	mutex_destroy(&target->wqlock);
6761 	mutex_destroy(&target->aqlock);
6762 	mutex_destroy(&target->statlock);
6763 	cv_destroy(&target->reset_cv);
6764 	cv_destroy(&target->abort_cv);
6765 	ddi_soft_state_bystr_fini(&target->lun_sstate);
6766 	ddi_soft_state_bystr_free(iport->tgt_sstate, target->unit_address);
6767 	pmcs_rele_iport(iport);
6768 }
6769 
6770 /*
6771  * Get device state.  Called with statlock and PHY lock held.
6772  */
6773 int
6774 pmcs_get_dev_state(pmcs_hw_t *pwp, pmcs_xscsi_t *xp, uint8_t *ds)
6775 {
6776 	uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
6777 	int result;
6778 	struct pmcwork *pwrk;
6779 	pmcs_phy_t *phyp;
6780 
6781 	pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, xp, "%s: tgt(0x%p)", __func__,
6782 	    (void *)xp);
6783 	if (xp == NULL) {
6784 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
6785 		    "%s: Target is NULL", __func__);
6786 		return (-1);
6787 	}
6788 
6789 	ASSERT(mutex_owned(&xp->statlock));
6790 	phyp = xp->phy;
6791 	ASSERT(mutex_owned(&phyp->phy_lock));
6792 
6793 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
6794 	if (pwrk == NULL) {
6795 		pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nowrk, __func__);
6796 		return (-1);
6797 	}
6798 	pwrk->arg = msg;
6799 	pwrk->dtype = phyp->dtype;
6800 
6801 	if (phyp->valid_device_id == 0) {
6802 		pmcs_pwork(pwp, pwrk);
6803 		pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, xp,
6804 		    "%s: Invalid DeviceID", __func__);
6805 		return (-1);
6806 	}
6807 	htag = pwrk->htag;
6808 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
6809 	    PMCIN_GET_DEVICE_STATE));
6810 	msg[1] = LE_32(pwrk->htag);
6811 	msg[2] = LE_32(phyp->device_id);
6812 
6813 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6814 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6815 	if (ptr == NULL) {
6816 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6817 		pmcs_pwork(pwp, pwrk);
6818 		pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nomsg, __func__);
6819 		return (-1);
6820 	}
6821 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
6822 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
6823 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6824 	mutex_exit(&xp->statlock);
6825 	pmcs_unlock_phy(phyp);
6826 	WAIT_FOR(pwrk, 1000, result);
6827 	pmcs_lock_phy(phyp);
6828 	pmcs_pwork(pwp, pwrk);
6829 	mutex_enter(&xp->statlock);
6830 
6831 	if (result) {
6832 		pmcs_timed_out(pwp, htag, __func__);
6833 		pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, xp,
6834 		    "%s: cmd timed out, returning ", __func__);
6835 		return (-1);
6836 	}
6837 	if (LE_32(msg[2]) == 0) {
6838 		*ds = (uint8_t)(LE_32(msg[4]));
6839 		if (*ds !=  xp->dev_state) {
6840 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6841 			    "%s: retrieved_ds=0x%x, target_ds=0x%x", __func__,
6842 			    *ds, xp->dev_state);
6843 		}
6844 		return (0);
6845 	} else {
6846 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6847 		    "%s: cmd failed Status(0x%x), returning ", __func__,
6848 		    LE_32(msg[2]));
6849 		return (-1);
6850 	}
6851 }
6852 
6853 /*
6854  * Set device state.  Called with target's statlock and PHY lock held.
6855  */
6856 int
6857 pmcs_set_dev_state(pmcs_hw_t *pwp, pmcs_xscsi_t *xp, uint8_t ds)
6858 {
6859 	uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
6860 	int result;
6861 	uint8_t pds, nds;
6862 	struct pmcwork *pwrk;
6863 	pmcs_phy_t *phyp;
6864 
6865 	pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, NULL, xp,
6866 	    "%s: ds(0x%x), tgt(0x%p)", __func__, ds, (void *)xp);
6867 	if (xp == NULL) {
6868 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
6869 		    "%s: Target is Null", __func__);
6870 		return (-1);
6871 	}
6872 
6873 	phyp = xp->phy;
6874 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
6875 	if (pwrk == NULL) {
6876 		pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nowrk, __func__);
6877 		return (-1);
6878 	}
6879 	if (phyp == NULL) {
6880 		pmcs_pwork(pwp, pwrk);
6881 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6882 		    "%s: PHY is Null", __func__);
6883 		return (-1);
6884 	}
6885 	if (phyp->valid_device_id == 0) {
6886 		pmcs_pwork(pwp, pwrk);
6887 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6888 		    "%s: Invalid DeviceID", __func__);
6889 		return (-1);
6890 	}
6891 	pwrk->arg = msg;
6892 	pwrk->dtype = phyp->dtype;
6893 	htag = pwrk->htag;
6894 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
6895 	    PMCIN_SET_DEVICE_STATE));
6896 	msg[1] = LE_32(pwrk->htag);
6897 	msg[2] = LE_32(phyp->device_id);
6898 	msg[3] = LE_32(ds);
6899 
6900 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6901 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6902 	if (ptr == NULL) {
6903 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6904 		pmcs_pwork(pwp, pwrk);
6905 		pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nomsg, __func__);
6906 		return (-1);
6907 	}
6908 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
6909 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
6910 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6911 
6912 	mutex_exit(&xp->statlock);
6913 	pmcs_unlock_phy(phyp);
6914 	WAIT_FOR(pwrk, 1000, result);
6915 	pmcs_lock_phy(phyp);
6916 	pmcs_pwork(pwp, pwrk);
6917 	mutex_enter(&xp->statlock);
6918 
6919 	if (result) {
6920 		pmcs_timed_out(pwp, htag, __func__);
6921 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6922 		    "%s: cmd timed out, returning", __func__);
6923 		return (-1);
6924 	}
6925 	if (LE_32(msg[2]) == 0) {
6926 		pds = (uint8_t)(LE_32(msg[4]) >> 4);
6927 		nds = (uint8_t)(LE_32(msg[4]) & 0x0000000f);
6928 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6929 		    "%s: previous_ds=0x%x, new_ds=0x%x", __func__, pds, nds);
6930 		xp->dev_state = nds;
6931 		return (0);
6932 	} else {
6933 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
6934 		    "%s: cmd failed Status(0x%x), returning ", __func__,
6935 		    LE_32(msg[2]));
6936 		return (-1);
6937 	}
6938 }
6939 
6940 void
6941 pmcs_dev_state_recovery(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
6942 {
6943 	uint8_t	ds;
6944 	int rc;
6945 	pmcs_xscsi_t *tgt;
6946 	pmcs_phy_t *pptr, *pnext, *pchild;
6947 
6948 	/*
6949 	 * First time, check to see if we're already performing recovery
6950 	 */
6951 	if (phyp == NULL) {
6952 		mutex_enter(&pwp->lock);
6953 		if (pwp->ds_err_recovering) {
6954 			mutex_exit(&pwp->lock);
6955 			SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
6956 			return;
6957 		}
6958 
6959 		pwp->ds_err_recovering = 1;
6960 		pptr = pwp->root_phys;
6961 		mutex_exit(&pwp->lock);
6962 	} else {
6963 		pptr = phyp;
6964 	}
6965 
6966 	while (pptr) {
6967 		/*
6968 		 * Since ds_err_recovering is set, we can be assured these
6969 		 * PHYs won't disappear on us while we do this.
6970 		 */
6971 		pmcs_lock_phy(pptr);
6972 		pchild = pptr->children;
6973 		pnext = pptr->sibling;
6974 		pmcs_unlock_phy(pptr);
6975 
6976 		if (pchild) {
6977 			pmcs_dev_state_recovery(pwp, pchild);
6978 		}
6979 
6980 		tgt = NULL;
6981 		pmcs_lock_phy(pptr);
6982 
6983 		if (pptr->dead) {
6984 			goto next_phy;
6985 		}
6986 
6987 		tgt = pptr->target;
6988 
6989 		if (tgt != NULL) {
6990 			mutex_enter(&tgt->statlock);
6991 			if (tgt->recover_wait == 0) {
6992 				goto next_phy;
6993 			}
6994 		}
6995 
6996 		if (pptr->prev_recovery) {
6997 			if (ddi_get_lbolt() - pptr->prev_recovery <
6998 			    drv_usectohz(PMCS_DS_RECOVERY_INTERVAL)) {
6999 				pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, tgt,
7000 				    "%s: DS recovery on PHY %s "
7001 				    "re-invoked too soon. Skipping...",
7002 				    __func__, pptr->path);
7003 				goto next_phy;
7004 			}
7005 		}
7006 		pptr->prev_recovery = ddi_get_lbolt();
7007 
7008 		/*
7009 		 * Step 1: Put the device into the IN_RECOVERY state
7010 		 */
7011 		rc = pmcs_get_dev_state(pwp, tgt, &ds);
7012 		if (rc != 0) {
7013 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7014 			    "%s: pmcs_get_dev_state on PHY %s "
7015 			    "failed (rc=%d)",
7016 			    __func__, pptr->path, rc);
7017 
7018 			pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
7019 			    __func__, __LINE__, "pmcs_get_dev_state");
7020 
7021 			goto next_phy;
7022 		}
7023 
7024 		if ((tgt->dev_state == ds) &&
7025 		    (ds == PMCS_DEVICE_STATE_IN_RECOVERY)) {
7026 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7027 			    "%s: Target 0x%p already IN_RECOVERY", __func__,
7028 			    (void *)tgt);
7029 		} else {
7030 			tgt->dev_state = ds;
7031 			ds = PMCS_DEVICE_STATE_IN_RECOVERY;
7032 			rc = pmcs_send_err_recovery_cmd(pwp, ds, tgt);
7033 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7034 			    "%s: pmcs_send_err_recovery_cmd "
7035 			    "result(%d) tgt(0x%p) ds(0x%x) tgt->ds(0x%x)",
7036 			    __func__, rc, (void *)tgt, ds, tgt->dev_state);
7037 
7038 			if (rc) {
7039 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7040 				    "%s: pmcs_send_err_recovery_cmd to PHY %s "
7041 				    "failed (rc=%d)",
7042 				    __func__, pptr->path, rc);
7043 
7044 				pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
7045 				    __func__, __LINE__,
7046 				    "pmcs_send_err_recovery_cmd");
7047 
7048 				goto next_phy;
7049 			}
7050 		}
7051 
7052 		/*
7053 		 * Step 2: Perform a hard reset on the PHY
7054 		 */
7055 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7056 		    "%s: Issue HARD_RESET to PHY %s", __func__, pptr->path);
7057 		/*
7058 		 * Must release statlock here because pmcs_reset_phy will
7059 		 * drop and reacquire the PHY lock.
7060 		 */
7061 		mutex_exit(&tgt->statlock);
7062 		rc = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_HARD_RESET);
7063 		mutex_enter(&tgt->statlock);
7064 		if (rc) {
7065 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7066 			    "%s: HARD_RESET to PHY %s failed (rc=%d)",
7067 			    __func__, pptr->path, rc);
7068 
7069 			pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
7070 			    __func__, __LINE__, "HARD_RESET");
7071 
7072 			goto next_phy;
7073 		}
7074 
7075 		/*
7076 		 * Step 3: Abort all I/Os to the device
7077 		 */
7078 		if (pptr->abort_all_start) {
7079 			while (pptr->abort_all_start) {
7080 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7081 				    "%s: Waiting for outstanding ABORT_ALL on "
7082 				    "PHY 0x%p", __func__, (void *)pptr);
7083 				cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
7084 			}
7085 		} else {
7086 			mutex_exit(&tgt->statlock);
7087 			rc = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
7088 			mutex_enter(&tgt->statlock);
7089 			if (rc != 0) {
7090 				pptr->abort_pending = 1;
7091 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7092 				    "%s: pmcs_abort to PHY %s failed (rc=%d)",
7093 				    __func__, pptr->path, rc);
7094 
7095 				pmcs_handle_ds_recovery_error(pptr, tgt,
7096 				    pwp, __func__, __LINE__, "pmcs_abort");
7097 
7098 				goto next_phy;
7099 			}
7100 		}
7101 
7102 		/*
7103 		 * Step 4: Set the device back to OPERATIONAL state
7104 		 */
7105 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7106 		    "%s: Set PHY/tgt 0x%p/0x%p to OPERATIONAL state",
7107 		    __func__, (void *)pptr, (void *)tgt);
7108 		rc = pmcs_set_dev_state(pwp, tgt,
7109 		    PMCS_DEVICE_STATE_OPERATIONAL);
7110 		if (rc == 0) {
7111 			tgt->recover_wait = 0;
7112 
7113 			pptr->ds_recovery_retries = 0;
7114 			if ((pptr->ds_prev_good_recoveries == 0) ||
7115 			    (ddi_get_lbolt() - pptr->last_good_recovery >
7116 			    drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME))) {
7117 				pptr->last_good_recovery = ddi_get_lbolt();
7118 				pptr->ds_prev_good_recoveries = 1;
7119 			} else if (ddi_get_lbolt() < pptr->last_good_recovery +
7120 			    drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME)) {
7121 				pptr->ds_prev_good_recoveries++;
7122 			} else {
7123 				pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
7124 				    __func__, __LINE__, "Max recovery"
7125 				    "attempts reached. Declaring PHY dead");
7126 			}
7127 
7128 			/*
7129 			 * Don't bother to run the work queues if the PHY
7130 			 * is dead.
7131 			 */
7132 			if (tgt->phy && !tgt->phy->dead) {
7133 				SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
7134 				(void) ddi_taskq_dispatch(pwp->tq, pmcs_worker,
7135 				    pwp, DDI_NOSLEEP);
7136 			}
7137 		} else {
7138 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7139 			    "%s: Failed to SET tgt 0x%p to OPERATIONAL state",
7140 			    __func__, (void *)tgt);
7141 
7142 			pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
7143 			    __func__, __LINE__, "SET tgt to OPERATIONAL state");
7144 
7145 			goto next_phy;
7146 		}
7147 
7148 next_phy:
7149 		if (tgt) {
7150 			mutex_exit(&tgt->statlock);
7151 		}
7152 		pmcs_unlock_phy(pptr);
7153 		pptr = pnext;
7154 	}
7155 
7156 	/*
7157 	 * Only clear ds_err_recovering if we're exiting for good and not
7158 	 * just unwinding from recursion
7159 	 */
7160 	if (phyp == NULL) {
7161 		mutex_enter(&pwp->lock);
7162 		pwp->ds_err_recovering = 0;
7163 		mutex_exit(&pwp->lock);
7164 	}
7165 }
7166 
7167 /*
7168  * Called with target's statlock and PHY lock held.
7169  */
7170 int
7171 pmcs_send_err_recovery_cmd(pmcs_hw_t *pwp, uint8_t dev_state, pmcs_xscsi_t *tgt)
7172 {
7173 	pmcs_phy_t *pptr;
7174 	int rc = -1;
7175 
7176 	ASSERT(tgt != NULL);
7177 	ASSERT(mutex_owned(&tgt->statlock));
7178 
7179 	if (tgt->recovering) {
7180 		return (0);
7181 	}
7182 
7183 	tgt->recovering = 1;
7184 	pptr = tgt->phy;
7185 
7186 	if (pptr == NULL) {
7187 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7188 		    "%s: PHY is Null", __func__);
7189 		return (-1);
7190 	}
7191 
7192 	ASSERT(mutex_owned(&pptr->phy_lock));
7193 
7194 	pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7195 	    "%s: ds: 0x%x, tgt ds(0x%x)", __func__, dev_state, tgt->dev_state);
7196 
7197 	switch (dev_state) {
7198 	case PMCS_DEVICE_STATE_IN_RECOVERY:
7199 		if (tgt->dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
7200 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7201 			    "%s: Target 0x%p already IN_RECOVERY", __func__,
7202 			    (void *)tgt);
7203 			rc = 0;	/* This is not an error */
7204 			goto no_action;
7205 		}
7206 
7207 		rc = pmcs_set_dev_state(pwp, tgt,
7208 		    PMCS_DEVICE_STATE_IN_RECOVERY);
7209 		if (rc != 0) {
7210 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7211 			    "%s(1): Failed to SET tgt(0x%p) to _IN_RECOVERY",
7212 			    __func__, (void *)tgt);
7213 		}
7214 
7215 		break;
7216 
7217 	case PMCS_DEVICE_STATE_OPERATIONAL:
7218 		if (tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) {
7219 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7220 			    "%s: Target 0x%p not ready to go OPERATIONAL",
7221 			    __func__, (void *)tgt);
7222 			goto no_action;
7223 		}
7224 
7225 		rc = pmcs_set_dev_state(pwp, tgt,
7226 		    PMCS_DEVICE_STATE_OPERATIONAL);
7227 		tgt->reset_success = 1;
7228 		if (rc != 0) {
7229 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7230 			    "%s(2): Failed to SET tgt(0x%p) to OPERATIONAL",
7231 			    __func__, (void *)tgt);
7232 			tgt->reset_success = 0;
7233 		}
7234 
7235 		break;
7236 
7237 	case PMCS_DEVICE_STATE_NON_OPERATIONAL:
7238 		PHY_CHANGED(pwp, pptr);
7239 		RESTART_DISCOVERY(pwp);
7240 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7241 		    "%s: Device at %s is non-operational",
7242 		    __func__, pptr->path);
7243 		tgt->dev_state = PMCS_DEVICE_STATE_NON_OPERATIONAL;
7244 		rc = 0;
7245 
7246 		break;
7247 
7248 	default:
7249 		pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
7250 		    "%s: Invalid state requested (%d)", __func__,
7251 		    dev_state);
7252 		break;
7253 
7254 	}
7255 
7256 no_action:
7257 	tgt->recovering = 0;
7258 	return (rc);
7259 }
7260 
7261 /*
7262  * pmcs_lock_phy_impl
7263  *
7264  * This function is what does the actual work for pmcs_lock_phy.  It will
7265  * lock all PHYs from phyp down in a top-down fashion.
7266  *
7267  * Locking notes:
7268  * 1. level starts from 0 for the PHY ("parent") that's passed in.  It is
7269  * not a reflection of the actual level of the PHY in the SAS topology.
7270  * 2. If parent is an expander, then parent is locked along with all its
7271  * descendents.
7272  * 3. Expander subsidiary PHYs at level 0 are not locked.  It is the
7273  * responsibility of the caller to individually lock expander subsidiary PHYs
7274  * at level 0 if necessary.
7275  * 4. Siblings at level 0 are not traversed due to the possibility that we're
7276  * locking a PHY on the dead list.  The siblings could be pointing to invalid
7277  * PHYs.  We don't lock siblings at level 0 anyway.
7278  */
7279 static void
7280 pmcs_lock_phy_impl(pmcs_phy_t *phyp, int level)
7281 {
7282 	pmcs_phy_t *tphyp;
7283 
7284 	ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
7285 	    (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
7286 
7287 	/*
7288 	 * Start walking the PHYs.
7289 	 */
7290 	tphyp = phyp;
7291 	while (tphyp) {
7292 		/*
7293 		 * If we're at the top level, only lock ourselves.  For anything
7294 		 * at level > 0, traverse children while locking everything.
7295 		 */
7296 		if ((level > 0) || (tphyp == phyp)) {
7297 			pmcs_prt(tphyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, tphyp,
7298 			    NULL, "%s: PHY 0x%p parent 0x%p path %s lvl %d",
7299 			    __func__, (void *)tphyp, (void *)tphyp->parent,
7300 			    tphyp->path, level);
7301 			mutex_enter(&tphyp->phy_lock);
7302 
7303 			if (tphyp->children) {
7304 				pmcs_lock_phy_impl(tphyp->children, level + 1);
7305 			}
7306 		}
7307 
7308 		if (level == 0) {
7309 			return;
7310 		}
7311 
7312 		tphyp = tphyp->sibling;
7313 	}
7314 }
7315 
7316 /*
7317  * pmcs_lock_phy
7318  *
7319  * This function is responsible for locking a PHY and all its descendents
7320  */
7321 void
7322 pmcs_lock_phy(pmcs_phy_t *phyp)
7323 {
7324 #ifdef DEBUG
7325 	char *callername = NULL;
7326 	ulong_t off;
7327 
7328 	ASSERT(phyp != NULL);
7329 
7330 	callername = modgetsymname((uintptr_t)caller(), &off);
7331 
7332 	if (callername == NULL) {
7333 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7334 		    "%s: PHY 0x%p path %s caller: unknown", __func__,
7335 		    (void *)phyp, phyp->path);
7336 	} else {
7337 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7338 		    "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
7339 		    (void *)phyp, phyp->path, callername, off);
7340 	}
7341 #else
7342 	pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7343 	    "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
7344 #endif
7345 	pmcs_lock_phy_impl(phyp, 0);
7346 }
7347 
7348 /*
7349  * pmcs_unlock_phy_impl
7350  *
7351  * Unlock all PHYs from phyp down in a bottom-up fashion.
7352  */
7353 static void
7354 pmcs_unlock_phy_impl(pmcs_phy_t *phyp, int level)
7355 {
7356 	pmcs_phy_t *phy_next;
7357 
7358 	ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
7359 	    (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
7360 
7361 	/*
7362 	 * Recurse down to the bottom PHYs
7363 	 */
7364 	if (level == 0) {
7365 		if (phyp->children) {
7366 			pmcs_unlock_phy_impl(phyp->children, level + 1);
7367 		}
7368 	} else {
7369 		phy_next = phyp;
7370 		while (phy_next) {
7371 			if (phy_next->children) {
7372 				pmcs_unlock_phy_impl(phy_next->children,
7373 				    level + 1);
7374 			}
7375 			phy_next = phy_next->sibling;
7376 		}
7377 	}
7378 
7379 	/*
7380 	 * Iterate through PHYs unlocking all at level > 0 as well the top PHY
7381 	 */
7382 	phy_next = phyp;
7383 	while (phy_next) {
7384 		if ((level > 0) || (phy_next == phyp)) {
7385 			pmcs_prt(phy_next->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
7386 			    phy_next, NULL,
7387 			    "%s: PHY 0x%p parent 0x%p path %s lvl %d",
7388 			    __func__, (void *)phy_next,
7389 			    (void *)phy_next->parent, phy_next->path, level);
7390 			mutex_exit(&phy_next->phy_lock);
7391 		}
7392 
7393 		if (level == 0) {
7394 			return;
7395 		}
7396 
7397 		phy_next = phy_next->sibling;
7398 	}
7399 }
7400 
7401 /*
7402  * pmcs_unlock_phy
7403  *
7404  * Unlock a PHY and all its descendents
7405  */
7406 void
7407 pmcs_unlock_phy(pmcs_phy_t *phyp)
7408 {
7409 #ifdef DEBUG
7410 	char *callername = NULL;
7411 	ulong_t off;
7412 
7413 	ASSERT(phyp != NULL);
7414 
7415 	callername = modgetsymname((uintptr_t)caller(), &off);
7416 
7417 	if (callername == NULL) {
7418 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7419 		    "%s: PHY 0x%p path %s caller: unknown", __func__,
7420 		    (void *)phyp, phyp->path);
7421 	} else {
7422 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7423 		    "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
7424 		    (void *)phyp, phyp->path, callername, off);
7425 	}
7426 #else
7427 	pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7428 	    "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
7429 #endif
7430 	pmcs_unlock_phy_impl(phyp, 0);
7431 }
7432 
7433 /*
7434  * pmcs_get_root_phy
7435  *
7436  * For a given phy pointer return its root phy.
7437  * The caller must be holding the lock on every PHY from phyp up to the root.
7438  */
7439 pmcs_phy_t *
7440 pmcs_get_root_phy(pmcs_phy_t *phyp)
7441 {
7442 	ASSERT(phyp);
7443 
7444 	while (phyp) {
7445 		if (IS_ROOT_PHY(phyp)) {
7446 			break;
7447 		}
7448 		phyp = phyp->parent;
7449 	}
7450 
7451 	return (phyp);
7452 }
7453 
7454 /*
7455  * pmcs_free_dma_chunklist
7456  *
7457  * Free DMA S/G chunk list
7458  */
7459 void
7460 pmcs_free_dma_chunklist(pmcs_hw_t *pwp)
7461 {
7462 	pmcs_chunk_t	*pchunk;
7463 
7464 	while (pwp->dma_chunklist) {
7465 		pchunk = pwp->dma_chunklist;
7466 		pwp->dma_chunklist = pwp->dma_chunklist->next;
7467 		if (pchunk->dma_handle) {
7468 			if (ddi_dma_unbind_handle(pchunk->dma_handle) !=
7469 			    DDI_SUCCESS) {
7470 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
7471 				    "Condition failed at %s():%d",
7472 				    __func__, __LINE__);
7473 			}
7474 			ddi_dma_free_handle(&pchunk->dma_handle);
7475 			ddi_dma_mem_free(&pchunk->acc_handle);
7476 		}
7477 		kmem_free(pchunk, sizeof (pmcs_chunk_t));
7478 	}
7479 }
7480 
7481 
7482 /*
7483  * Start ssp event recovery. We have to schedule recovery operation because
7484  * it involves sending multiple commands to device and we should not do it
7485  * in the interrupt context.
7486  * If it is failure of a recovery command, let the recovery thread deal with it.
7487  * Called with pmcwork lock held.
7488  */
7489 
7490 void
7491 pmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
7492     size_t amt)
7493 {
7494 	pmcs_xscsi_t *tgt = pwrk->xp;
7495 	uint32_t event = LE_32(iomb[2]);
7496 	pmcs_phy_t *pptr = pwrk->phy;
7497 	uint32_t tag;
7498 
7499 	if (tgt != NULL) {
7500 		mutex_enter(&tgt->statlock);
7501 		if (!tgt->assigned) {
7502 			if (pptr) {
7503 				pmcs_dec_phy_ref_count(pptr);
7504 			}
7505 			pptr = NULL;
7506 			pwrk->phy = NULL;
7507 		}
7508 		mutex_exit(&tgt->statlock);
7509 	}
7510 	if (pptr == NULL) {
7511 		/*
7512 		 * No target, need to run RE-DISCOVERY here.
7513 		 */
7514 		if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) {
7515 			pwrk->state = PMCS_WORK_STATE_INTR;
7516 		}
7517 		/*
7518 		 * Although we cannot mark phy to force abort nor mark phy
7519 		 * as changed, killing of a target would take care of aborting
7520 		 * commands for the device.
7521 		 */
7522 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
7523 		    "%s: No valid target for event processing found. "
7524 		    "Scheduling RECONFIGURE",  __func__);
7525 		pmcs_pwork(pwp, pwrk);
7526 		RESTART_DISCOVERY(pwp);
7527 		return;
7528 	} else {
7529 		pmcs_lock_phy(pptr);
7530 		mutex_enter(&tgt->statlock);
7531 		if (event == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS) {
7532 			if (tgt->dev_state !=
7533 			    PMCS_DEVICE_STATE_NON_OPERATIONAL) {
7534 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7535 				    "%s: Device at %s is non-operational",
7536 				    __func__, pptr->path);
7537 				tgt->dev_state =
7538 				    PMCS_DEVICE_STATE_NON_OPERATIONAL;
7539 			}
7540 			pptr->abort_pending = 1;
7541 			mutex_exit(&tgt->statlock);
7542 			pmcs_unlock_phy(pptr);
7543 			mutex_exit(&pwrk->lock);
7544 			SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
7545 			RESTART_DISCOVERY(pwp);
7546 			return;
7547 		}
7548 
7549 		/*
7550 		 * If this command is run in WAIT mode, it is a failing recovery
7551 		 * command. If so, just wake up recovery thread waiting for
7552 		 * command completion.
7553 		 */
7554 		tag = PMCS_TAG_TYPE(pwrk->htag);
7555 		if (tag == PMCS_TAG_TYPE_WAIT) {
7556 			pwrk->htag |= PMCS_TAG_DONE;
7557 			if (pwrk->arg && amt) {
7558 				(void) memcpy(pwrk->arg, iomb, amt);
7559 			}
7560 			cv_signal(&pwrk->sleep_cv);
7561 			mutex_exit(&tgt->statlock);
7562 			pmcs_unlock_phy(pptr);
7563 			mutex_exit(&pwrk->lock);
7564 			return;
7565 		}
7566 
7567 		/*
7568 		 * To recover from primary failures,
7569 		 * we need to schedule handling events recovery.
7570 		 */
7571 		tgt->event_recovery = 1;
7572 		mutex_exit(&tgt->statlock);
7573 		pmcs_unlock_phy(pptr);
7574 		pwrk->ssp_event = event;
7575 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7576 		    "%s: Scheduling SSP event recovery for tgt(0x%p) "
7577 		    "pwrk(%p) tag(0x%x)", __func__, (void *)tgt, (void *)pwrk,
7578 		    pwrk->htag);
7579 		mutex_exit(&pwrk->lock);
7580 		SCHEDULE_WORK(pwp, PMCS_WORK_SSP_EVT_RECOVERY);
7581 	}
7582 
7583 	/* Work cannot be completed until event recovery is completed. */
7584 }
7585 
7586 /*
7587  * SSP target event recovery
7588  * Entered with a phy lock held
7589  * Pwrk lock is not needed - pwrk is on the target aq and no other thread
7590  * will do anything with it until this thread starts the chain of recovery.
7591  * Statlock may be acquired and released.
7592  */
7593 
7594 void
7595 pmcs_tgt_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk)
7596 {
7597 	pmcs_phy_t *pptr = pwrk->phy;
7598 	pmcs_cmd_t *sp = pwrk->arg;
7599 	pmcs_lun_t *lun = sp->cmd_lun;
7600 	pmcs_xscsi_t *tgt = pwrk->xp;
7601 	uint32_t event;
7602 	uint32_t htag;
7603 	uint32_t status;
7604 	uint8_t dstate;
7605 	int rv;
7606 
7607 	ASSERT(pwrk->arg != NULL);
7608 	ASSERT(pwrk->xp != NULL);
7609 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt, "%s: event recovery for "
7610 	    "target 0x%p", __func__, (void *)pwrk->xp);
7611 	htag = pwrk->htag;
7612 	event = pwrk->ssp_event;
7613 	pwrk->ssp_event = 0xffffffff;
7614 	if (event == PMCOUT_STATUS_XFER_ERR_BREAK ||
7615 	    event == PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY ||
7616 	    event == PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT) {
7617 		/* Command may be still pending on device */
7618 		rv = pmcs_ssp_tmf(pwp, pptr, SAS_QUERY_TASK, htag,
7619 		    lun->lun_num, &status);
7620 		if (rv != 0) {
7621 			goto out;
7622 		}
7623 		if (status == SAS_RSP_TMF_COMPLETE) {
7624 			/* Command NOT pending on a device */
7625 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7626 			    "%s: No pending command for tgt 0x%p",
7627 			    __func__, (void *)tgt);
7628 			/* Nothing more to do, just abort it on chip */
7629 			htag = 0;
7630 		}
7631 	}
7632 	/*
7633 	 * All other events left the command pending in the host
7634 	 * Send abort task and abort it on the chip
7635 	 */
7636 	if (htag != 0) {
7637 		if (pmcs_ssp_tmf(pwp, pptr, SAS_ABORT_TASK, htag,
7638 		    lun->lun_num, &status))
7639 			goto out;
7640 	}
7641 	(void) pmcs_abort(pwp, pptr, pwrk->htag, 0, 1);
7642 	/*
7643 	 * Abort either took care of work completion, or put device in
7644 	 * a recovery state
7645 	 */
7646 	return;
7647 out:
7648 	/* Abort failed, do full device recovery */
7649 	mutex_enter(&tgt->statlock);
7650 	if (!pmcs_get_dev_state(pwp, tgt, &dstate))
7651 		tgt->dev_state = dstate;
7652 
7653 	if ((tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) &&
7654 	    (tgt->dev_state != PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
7655 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
7656 		    "%s: Setting IN_RECOVERY for tgt 0x%p",
7657 		    __func__, (void *)tgt);
7658 		(void) pmcs_send_err_recovery_cmd(pwp,
7659 		    PMCS_DEVICE_STATE_IN_RECOVERY, tgt);
7660 	}
7661 	mutex_exit(&tgt->statlock);
7662 }
7663 
7664 /*
7665  * SSP event recovery task.
7666  */
7667 void
7668 pmcs_ssp_event_recovery(pmcs_hw_t *pwp)
7669 {
7670 	int idx;
7671 	pmcs_xscsi_t *tgt;
7672 	pmcs_cmd_t *cp;
7673 	pmcwork_t *pwrk;
7674 	pmcs_phy_t *pphy;
7675 	int er_flag;
7676 	uint32_t idxpwrk;
7677 
7678 restart:
7679 	for (idx = 0; idx < pwp->max_dev; idx++) {
7680 		mutex_enter(&pwp->lock);
7681 		tgt = pwp->targets[idx];
7682 		mutex_exit(&pwp->lock);
7683 		if (tgt != NULL) {
7684 			mutex_enter(&tgt->statlock);
7685 			if (!tgt->assigned) {
7686 				mutex_exit(&tgt->statlock);
7687 				continue;
7688 			}
7689 			pphy = tgt->phy;
7690 			er_flag = tgt->event_recovery;
7691 			mutex_exit(&tgt->statlock);
7692 			if (pphy != NULL && er_flag != 0) {
7693 				pmcs_lock_phy(pphy);
7694 				mutex_enter(&tgt->statlock);
7695 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt,
7696 				    "%s: found target(0x%p)", __func__,
7697 				    (void *) tgt);
7698 
7699 				/* Check what cmd expects recovery */
7700 				mutex_enter(&tgt->aqlock);
7701 				STAILQ_FOREACH(cp, &tgt->aq, cmd_next) {
7702 					/*
7703 					 * Since work structure is on this
7704 					 * target aq, and only this thread
7705 					 * is accessing it now, we do not need
7706 					 * to lock it
7707 					 */
7708 					idxpwrk = PMCS_TAG_INDEX(cp->cmd_tag);
7709 					pwrk = &pwp->work[idxpwrk];
7710 					if (pwrk->htag != cp->cmd_tag) {
7711 						/*
7712 						 * aq may contain TMF commands,
7713 						 * so we may not find work
7714 						 * structure with htag
7715 						 */
7716 						break;
7717 					}
7718 					if (pwrk->ssp_event != 0 &&
7719 					    pwrk->ssp_event !=
7720 					    PMCS_REC_EVENT) {
7721 						pmcs_prt(pwp,
7722 						    PMCS_PRT_DEBUG, pphy, tgt,
7723 						    "%s: pwrk(%p) ctag(0x%x)",
7724 						    __func__, (void *) pwrk,
7725 						    cp->cmd_tag);
7726 						mutex_exit(&tgt->aqlock);
7727 						mutex_exit(&tgt->statlock);
7728 						pmcs_tgt_event_recovery(
7729 						    pwp, pwrk);
7730 						/*
7731 						 * We dropped statlock, so
7732 						 * restart scanning from scratch
7733 						 */
7734 						pmcs_unlock_phy(pphy);
7735 						goto restart;
7736 					}
7737 				}
7738 				mutex_exit(&tgt->aqlock);
7739 				tgt->event_recovery = 0;
7740 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt,
7741 				    "%s: end of SSP event recovery for "
7742 				    "target(0x%p)", __func__, (void *) tgt);
7743 				mutex_exit(&tgt->statlock);
7744 				pmcs_unlock_phy(pphy);
7745 			}
7746 		}
7747 	}
7748 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt, "%s: "
7749 	    "end of SSP event recovery for pwp(0x%p)", __func__, (void *) pwp);
7750 }
7751 
7752 /*ARGSUSED2*/
7753 int
7754 pmcs_phy_constructor(void *buf, void *arg, int kmflags)
7755 {
7756 	pmcs_hw_t *pwp = (pmcs_hw_t *)arg;
7757 	pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
7758 
7759 	mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
7760 	    DDI_INTR_PRI(pwp->intr_pri));
7761 	cv_init(&phyp->abort_all_cv, NULL, CV_DRIVER, NULL);
7762 	return (0);
7763 }
7764 
7765 /*ARGSUSED1*/
7766 void
7767 pmcs_phy_destructor(void *buf, void *arg)
7768 {
7769 	pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
7770 
7771 	cv_destroy(&phyp->abort_all_cv);
7772 	mutex_destroy(&phyp->phy_lock);
7773 }
7774 
7775 /*
7776  * Free all PHYs from the kmem_cache starting at phyp as well as everything
7777  * on the dead_phys list.
7778  *
7779  * NOTE: This function does not free root PHYs as they are not allocated
7780  * from the kmem_cache.
7781  *
7782  * No PHY locks are acquired as this should only be called during DDI_DETACH
7783  * or soft reset (while pmcs interrupts are disabled).
7784  */
7785 void
7786 pmcs_free_all_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
7787 {
7788 	pmcs_phy_t *tphyp, *nphyp;
7789 
7790 	if (phyp == NULL) {
7791 		return;
7792 	}
7793 
7794 	tphyp = phyp;
7795 	while (tphyp) {
7796 		nphyp = tphyp->sibling;
7797 
7798 		if (tphyp->children) {
7799 			pmcs_free_all_phys(pwp, tphyp->children);
7800 			tphyp->children = NULL;
7801 		}
7802 		if (!IS_ROOT_PHY(tphyp)) {
7803 			kmem_cache_free(pwp->phy_cache, tphyp);
7804 		}
7805 
7806 		tphyp = nphyp;
7807 	}
7808 
7809 	tphyp = pwp->dead_phys;
7810 	while (tphyp) {
7811 		nphyp = tphyp->sibling;
7812 		kmem_cache_free(pwp->phy_cache, tphyp);
7813 		tphyp = nphyp;
7814 	}
7815 	pwp->dead_phys = NULL;
7816 }
7817 
7818 /*
7819  * Free a list of PHYs linked together by the sibling pointer back to the
7820  * kmem cache from whence they came.  This function does not recurse, so the
7821  * caller must ensure there are no children.
7822  */
7823 void
7824 pmcs_free_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
7825 {
7826 	pmcs_phy_t *next_phy;
7827 
7828 	while (phyp) {
7829 		next_phy = phyp->sibling;
7830 		ASSERT(!mutex_owned(&phyp->phy_lock));
7831 		kmem_cache_free(pwp->phy_cache, phyp);
7832 		phyp = next_phy;
7833 	}
7834 }
7835 
7836 /*
7837  * Make a copy of an existing PHY structure.  This is used primarily in
7838  * discovery to compare the contents of an existing PHY with what gets
7839  * reported back by an expander.
7840  *
7841  * This function must not be called from any context where sleeping is
7842  * not possible.
7843  *
7844  * The new PHY is returned unlocked.
7845  */
7846 static pmcs_phy_t *
7847 pmcs_clone_phy(pmcs_phy_t *orig_phy)
7848 {
7849 	pmcs_phy_t *local;
7850 
7851 	local = kmem_cache_alloc(orig_phy->pwp->phy_cache, KM_SLEEP);
7852 
7853 	/*
7854 	 * Go ahead and just copy everything...
7855 	 */
7856 	*local = *orig_phy;
7857 
7858 	/*
7859 	 * But the following must be set appropriately for this copy
7860 	 */
7861 	local->sibling = NULL;
7862 	local->children = NULL;
7863 	mutex_init(&local->phy_lock, NULL, MUTEX_DRIVER,
7864 	    DDI_INTR_PRI(orig_phy->pwp->intr_pri));
7865 
7866 	return (local);
7867 }
7868 
7869 int
7870 pmcs_check_acc_handle(ddi_acc_handle_t handle)
7871 {
7872 	ddi_fm_error_t de;
7873 
7874 	if (handle == NULL) {
7875 		return (DDI_FAILURE);
7876 	}
7877 	ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
7878 	return (de.fme_status);
7879 }
7880 
7881 int
7882 pmcs_check_dma_handle(ddi_dma_handle_t handle)
7883 {
7884 	ddi_fm_error_t de;
7885 
7886 	if (handle == NULL) {
7887 		return (DDI_FAILURE);
7888 	}
7889 	ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
7890 	return (de.fme_status);
7891 }
7892 
7893 
7894 void
7895 pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail)
7896 {
7897 	uint64_t ena;
7898 	char buf[FM_MAX_CLASS];
7899 
7900 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
7901 	ena = fm_ena_generate(0, FM_ENA_FMT1);
7902 	if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities)) {
7903 		ddi_fm_ereport_post(pwp->dip, buf, ena, DDI_NOSLEEP,
7904 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
7905 	}
7906 }
7907 
7908 int
7909 pmcs_check_acc_dma_handle(pmcs_hw_t *pwp)
7910 {
7911 	pmcs_chunk_t *pchunk;
7912 	int i;
7913 
7914 	/* check all acc & dma handles allocated in attach */
7915 	if ((pmcs_check_acc_handle(pwp->pci_acc_handle) != DDI_SUCCESS) ||
7916 	    (pmcs_check_acc_handle(pwp->msg_acc_handle) != DDI_SUCCESS) ||
7917 	    (pmcs_check_acc_handle(pwp->top_acc_handle) != DDI_SUCCESS) ||
7918 	    (pmcs_check_acc_handle(pwp->mpi_acc_handle) != DDI_SUCCESS) ||
7919 	    (pmcs_check_acc_handle(pwp->gsm_acc_handle) != DDI_SUCCESS)) {
7920 		goto check_failed;
7921 	}
7922 
7923 	for (i = 0; i < PMCS_NIQ; i++) {
7924 		if ((pmcs_check_dma_handle(
7925 		    pwp->iqp_handles[i]) != DDI_SUCCESS) ||
7926 		    (pmcs_check_acc_handle(
7927 		    pwp->iqp_acchdls[i]) != DDI_SUCCESS)) {
7928 			goto check_failed;
7929 		}
7930 	}
7931 
7932 	for (i = 0; i < PMCS_NOQ; i++) {
7933 		if ((pmcs_check_dma_handle(
7934 		    pwp->oqp_handles[i]) != DDI_SUCCESS) ||
7935 		    (pmcs_check_acc_handle(
7936 		    pwp->oqp_acchdls[i]) != DDI_SUCCESS)) {
7937 			goto check_failed;
7938 		}
7939 	}
7940 
7941 	if ((pmcs_check_dma_handle(pwp->cip_handles) != DDI_SUCCESS) ||
7942 	    (pmcs_check_acc_handle(pwp->cip_acchdls) != DDI_SUCCESS)) {
7943 		goto check_failed;
7944 	}
7945 
7946 	if (pwp->fwlog &&
7947 	    ((pmcs_check_dma_handle(pwp->fwlog_hndl) != DDI_SUCCESS) ||
7948 	    (pmcs_check_acc_handle(pwp->fwlog_acchdl) != DDI_SUCCESS))) {
7949 		goto check_failed;
7950 	}
7951 
7952 	if (pwp->regdump_hndl && pwp->regdump_acchdl &&
7953 	    ((pmcs_check_dma_handle(pwp->regdump_hndl) != DDI_SUCCESS) ||
7954 	    (pmcs_check_acc_handle(pwp->regdump_acchdl)
7955 	    != DDI_SUCCESS))) {
7956 		goto check_failed;
7957 	}
7958 
7959 
7960 	pchunk = pwp->dma_chunklist;
7961 	while (pchunk) {
7962 		if ((pmcs_check_acc_handle(pchunk->acc_handle)
7963 		    != DDI_SUCCESS) ||
7964 		    (pmcs_check_dma_handle(pchunk->dma_handle)
7965 		    != DDI_SUCCESS)) {
7966 			goto check_failed;
7967 		}
7968 		pchunk = pchunk->next;
7969 	}
7970 
7971 	return (0);
7972 
7973 check_failed:
7974 
7975 	return (1);
7976 }
7977 
7978 /*
7979  * pmcs_handle_dead_phys
7980  *
7981  * If the PHY has no outstanding work associated with it, remove it from
7982  * the dead PHY list and free it.
7983  *
7984  * If pwp->ds_err_recovering or pwp->configuring is set, don't run.
7985  * This keeps routines that need to submit work to the chip from having to
7986  * hold PHY locks to ensure that PHYs don't disappear while they do their work.
7987  */
7988 void
7989 pmcs_handle_dead_phys(pmcs_hw_t *pwp)
7990 {
7991 	pmcs_phy_t *phyp, *nphyp, *pphyp;
7992 
7993 	mutex_enter(&pwp->lock);
7994 	mutex_enter(&pwp->config_lock);
7995 
7996 	if (pwp->configuring | pwp->ds_err_recovering) {
7997 		mutex_exit(&pwp->config_lock);
7998 		mutex_exit(&pwp->lock);
7999 		return;
8000 	}
8001 
8002 	/*
8003 	 * Check every PHY in the dead PHY list
8004 	 */
8005 	mutex_enter(&pwp->dead_phylist_lock);
8006 	phyp = pwp->dead_phys;
8007 	pphyp = NULL;	/* Set previous PHY to NULL */
8008 
8009 	while (phyp != NULL) {
8010 		pmcs_lock_phy(phyp);
8011 		ASSERT(phyp->dead);
8012 
8013 		nphyp = phyp->dead_next;
8014 
8015 		/*
8016 		 * Check for outstanding work
8017 		 */
8018 		if (phyp->ref_count > 0) {
8019 			pmcs_unlock_phy(phyp);
8020 			pphyp = phyp;	/* This PHY becomes "previous" */
8021 		} else if (phyp->target) {
8022 			pmcs_unlock_phy(phyp);
8023 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, phyp, phyp->target,
8024 			    "%s: Not freeing PHY 0x%p: target 0x%p is not free",
8025 			    __func__, (void *)phyp, (void *)phyp->target);
8026 			pphyp = phyp;
8027 		} else {
8028 			/*
8029 			 * No outstanding work or target references. Remove it
8030 			 * from the list and free it
8031 			 */
8032 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
8033 			    "%s: Freeing inactive dead PHY 0x%p @ %s "
8034 			    "target = 0x%p", __func__, (void *)phyp,
8035 			    phyp->path, (void *)phyp->target);
8036 			/*
8037 			 * If pphyp is NULL, then phyp was the head of the list,
8038 			 * so just reset the head to nphyp. Otherwise, the
8039 			 * previous PHY will now point to nphyp (the next PHY)
8040 			 */
8041 			if (pphyp == NULL) {
8042 				pwp->dead_phys = nphyp;
8043 			} else {
8044 				pphyp->dead_next = nphyp;
8045 			}
8046 			/*
8047 			 * If the target still points to this PHY, remove
8048 			 * that linkage now.
8049 			 */
8050 			if (phyp->target) {
8051 				mutex_enter(&phyp->target->statlock);
8052 				if (phyp->target->phy == phyp) {
8053 					phyp->target->phy = NULL;
8054 				}
8055 				mutex_exit(&phyp->target->statlock);
8056 			}
8057 			pmcs_unlock_phy(phyp);
8058 			kmem_cache_free(pwp->phy_cache, phyp);
8059 		}
8060 
8061 		phyp = nphyp;
8062 	}
8063 
8064 	mutex_exit(&pwp->dead_phylist_lock);
8065 	mutex_exit(&pwp->config_lock);
8066 	mutex_exit(&pwp->lock);
8067 }
8068 
8069 void
8070 pmcs_inc_phy_ref_count(pmcs_phy_t *phyp)
8071 {
8072 	atomic_inc_32(&phyp->ref_count);
8073 }
8074 
8075 void
8076 pmcs_dec_phy_ref_count(pmcs_phy_t *phyp)
8077 {
8078 	ASSERT(phyp->ref_count != 0);
8079 	atomic_dec_32(&phyp->ref_count);
8080 }
8081 
8082 /*
8083  * pmcs_reap_dead_phy
8084  *
8085  * This function is called from pmcs_new_tport when we have a PHY
8086  * without a target pointer.  It's possible in that case that this PHY
8087  * may have a "brother" on the dead_phys list.  That is, it may be the same as
8088  * this one but with a different root PHY number (e.g. pp05 vs. pp04).  If
8089  * that's the case, update the dead PHY and this new PHY.  If that's not the
8090  * case, we should get a tran_tgt_init on this after it's reported to SCSA.
8091  *
8092  * Called with PHY locked.
8093  */
8094 static void
8095 pmcs_reap_dead_phy(pmcs_phy_t *phyp)
8096 {
8097 	pmcs_hw_t *pwp = phyp->pwp;
8098 	pmcs_phy_t *ctmp;
8099 
8100 	ASSERT(mutex_owned(&phyp->phy_lock));
8101 
8102 	/*
8103 	 * Check the dead PHYs list
8104 	 */
8105 	mutex_enter(&pwp->dead_phylist_lock);
8106 	ctmp = pwp->dead_phys;
8107 	while (ctmp) {
8108 		if ((ctmp->iport != phyp->iport) ||
8109 		    (memcmp((void *)&ctmp->sas_address[0],
8110 		    (void *)&phyp->sas_address[0], 8))) {
8111 			ctmp = ctmp->dead_next;
8112 			continue;
8113 		}
8114 
8115 		/*
8116 		 * Same SAS address on same iport.  Now check to see if
8117 		 * the PHY path is the same with the possible exception
8118 		 * of the root PHY number.
8119 		 * The "5" is the string length of "pp00."
8120 		 */
8121 		if ((strnlen(phyp->path, 5) >= 5) &&
8122 		    (strnlen(ctmp->path, 5) >= 5)) {
8123 			if (memcmp((void *)&phyp->path[5],
8124 			    (void *)&ctmp->path[5],
8125 			    strnlen(phyp->path, 32) - 5) == 0) {
8126 				break;
8127 			}
8128 		}
8129 
8130 		ctmp = ctmp->dead_next;
8131 	}
8132 	mutex_exit(&pwp->dead_phylist_lock);
8133 
8134 	/*
8135 	 * Found a match.  Remove the target linkage and drop the
8136 	 * ref count on the old PHY.  Then, increment the ref count
8137 	 * on the new PHY to compensate.
8138 	 */
8139 	if (ctmp) {
8140 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
8141 		    "%s: Found match in dead PHY list for new PHY %s",
8142 		    __func__, phyp->path);
8143 		if (ctmp->target) {
8144 			/*
8145 			 * If there is a pointer to the target in the dead
8146 			 * PHY, and that PHY's ref_count drops to 0, we can
8147 			 * clear the target linkage now.  If the PHY's
8148 			 * ref_count is > 1, then there may be multiple
8149 			 * LUNs still remaining, so leave the linkage.
8150 			 */
8151 			pmcs_inc_phy_ref_count(phyp);
8152 			pmcs_dec_phy_ref_count(ctmp);
8153 			phyp->target = ctmp->target;
8154 			/*
8155 			 * Update the target's linkage as well
8156 			 */
8157 			mutex_enter(&phyp->target->statlock);
8158 			phyp->target->phy = phyp;
8159 			phyp->target->dtype = phyp->dtype;
8160 			mutex_exit(&phyp->target->statlock);
8161 
8162 			if (ctmp->ref_count == 0) {
8163 				ctmp->target = NULL;
8164 			}
8165 		}
8166 	}
8167 }
8168 
8169 /*
8170  * Called with iport lock held
8171  */
8172 void
8173 pmcs_add_phy_to_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
8174 {
8175 	ASSERT(mutex_owned(&iport->lock));
8176 	ASSERT(phyp);
8177 	ASSERT(!list_link_active(&phyp->list_node));
8178 	iport->nphy++;
8179 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
8180 	    &iport->nphy);
8181 	list_insert_tail(&iport->phys, phyp);
8182 	mutex_enter(&iport->refcnt_lock);
8183 	iport->refcnt++;
8184 	mutex_exit(&iport->refcnt_lock);
8185 }
8186 
8187 /*
8188  * Called with the iport lock held
8189  */
8190 void
8191 pmcs_remove_phy_from_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
8192 {
8193 	pmcs_phy_t *pptr, *next_pptr;
8194 
8195 	ASSERT(mutex_owned(&iport->lock));
8196 
8197 	/*
8198 	 * If phyp is NULL, remove all PHYs from the iport
8199 	 */
8200 	if (phyp == NULL) {
8201 		for (pptr = list_head(&iport->phys); pptr != NULL;
8202 		    pptr = next_pptr) {
8203 			next_pptr = list_next(&iport->phys, pptr);
8204 			mutex_enter(&pptr->phy_lock);
8205 			pptr->iport = NULL;
8206 			mutex_exit(&pptr->phy_lock);
8207 			pmcs_rele_iport(iport);
8208 			list_remove(&iport->phys, pptr);
8209 		}
8210 		iport->nphy = 0;
8211 		return;
8212 	}
8213 
8214 	ASSERT(phyp);
8215 	ASSERT(iport->nphy > 0);
8216 	ASSERT(list_link_active(&phyp->list_node));
8217 	iport->nphy--;
8218 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
8219 	    &iport->nphy);
8220 	list_remove(&iport->phys, phyp);
8221 	pmcs_rele_iport(iport);
8222 }
8223 
8224 /*
8225  * This function checks to see if the target pointed to by phyp is still
8226  * correct.  This is done by comparing the target's unit address with the
8227  * SAS address in phyp.
8228  *
8229  * Called with PHY locked and target statlock held
8230  */
8231 static boolean_t
8232 pmcs_phy_target_match(pmcs_phy_t *phyp)
8233 {
8234 	uint64_t wwn;
8235 	char unit_address[PMCS_MAX_UA_SIZE];
8236 	boolean_t rval = B_FALSE;
8237 
8238 	ASSERT(phyp);
8239 	ASSERT(phyp->target);
8240 	ASSERT(mutex_owned(&phyp->phy_lock));
8241 	ASSERT(mutex_owned(&phyp->target->statlock));
8242 
8243 	wwn = pmcs_barray2wwn(phyp->sas_address);
8244 	(void) scsi_wwn_to_wwnstr(wwn, 1, unit_address);
8245 
8246 	if (memcmp((void *)unit_address, (void *)phyp->target->unit_address,
8247 	    strnlen(phyp->target->unit_address, PMCS_MAX_UA_SIZE)) == 0) {
8248 		rval = B_TRUE;
8249 	}
8250 
8251 	return (rval);
8252 }
8253 
8254 void
8255 pmcs_start_dev_state_recovery(pmcs_xscsi_t *xp, pmcs_phy_t *phyp)
8256 {
8257 	ASSERT(mutex_owned(&xp->statlock));
8258 	ASSERT(xp->pwp != NULL);
8259 
8260 	if (xp->recover_wait == 0) {
8261 		pmcs_prt(xp->pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
8262 		    "%s: Start ds_recovery for tgt 0x%p/PHY 0x%p (%s)",
8263 		    __func__, (void *)xp, (void *)phyp, phyp->path);
8264 		xp->recover_wait = 1;
8265 
8266 		/*
8267 		 * Rather than waiting for the watchdog timer, we'll
8268 		 * kick it right now.
8269 		 */
8270 		SCHEDULE_WORK(xp->pwp, PMCS_WORK_DS_ERR_RECOVERY);
8271 		(void) ddi_taskq_dispatch(xp->pwp->tq, pmcs_worker, xp->pwp,
8272 		    DDI_NOSLEEP);
8273 	}
8274 }
8275 
8276 /*
8277  * Increment the phy ds error retry count.
8278  * If too many retries, mark phy dead and restart discovery;
8279  * otherwise schedule ds recovery.
8280  */
8281 static void
8282 pmcs_handle_ds_recovery_error(pmcs_phy_t *phyp, pmcs_xscsi_t *tgt,
8283     pmcs_hw_t *pwp, const char *func_name, int line, char *reason_string)
8284 {
8285 	ASSERT(mutex_owned(&phyp->phy_lock));
8286 	ASSERT((tgt == NULL) || mutex_owned(&tgt->statlock));
8287 
8288 	phyp->ds_recovery_retries++;
8289 
8290 	if (phyp->ds_recovery_retries > PMCS_MAX_DS_RECOVERY_RETRIES) {
8291 		pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt,
8292 		    "%s: retry limit reached after %s to PHY %s failed",
8293 		    func_name, reason_string, phyp->path);
8294 		if (tgt != NULL) {
8295 			tgt->recover_wait = 0;
8296 		}
8297 		phyp->dead = 1;
8298 		PHY_CHANGED_AT_LOCATION(pwp, phyp, func_name, line);
8299 		RESTART_DISCOVERY(pwp);
8300 	} else if ((phyp->ds_prev_good_recoveries >
8301 	    PMCS_MAX_DS_RECOVERY_RETRIES) &&
8302 	    (phyp->last_good_recovery + drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME)
8303 	    < ddi_get_lbolt())) {
8304 		pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt, "%s: max number of "
8305 		    "successful recoveries reached, declaring PHY %s dead",
8306 		    __func__, phyp->path);
8307 		if (tgt != NULL) {
8308 			tgt->recover_wait = 0;
8309 		}
8310 		phyp->dead = 1;
8311 		PHY_CHANGED_AT_LOCATION(pwp, phyp, func_name, line);
8312 		RESTART_DISCOVERY(pwp);
8313 	} else {
8314 		SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
8315 	}
8316 }
8317