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