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