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