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