Print this page
OS-68 cfgadm can cause kernel panic when trying to configure a retired device
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/scsi/impl/scsi_hba.c
+++ new/usr/src/uts/common/io/scsi/impl/scsi_hba.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
24 25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
25 26 * Copyright (c) 2016 by Delphix. All rights reserved.
26 27 */
27 28
28 29 #include <sys/note.h>
29 30
30 31 /*
31 32 * Generic SCSI Host Bus Adapter interface implementation
32 33 */
33 34 #include <sys/scsi/scsi.h>
34 35 #include <sys/scsi/generic/sas.h>
35 36 #include <sys/file.h>
36 37 #include <sys/disp.h> /* for minclsyspri */
37 38 #include <sys/ddi_impldefs.h>
38 39 #include <sys/ndi_impldefs.h>
39 40 #include <sys/sunndi.h>
40 41 #include <sys/ddi.h>
41 42 #include <sys/sunmdi.h>
42 43 #include <sys/mdi_impldefs.h>
43 44 #include <sys/callb.h>
44 45 #include <sys/epm.h>
45 46 #include <sys/damap.h>
46 47 #include <sys/time.h>
47 48 #include <sys/sunldi.h>
48 49 #include <sys/fm/protocol.h>
49 50
50 51 extern struct scsi_pkt *scsi_init_cache_pkt(struct scsi_address *,
51 52 struct scsi_pkt *, struct buf *, int, int, int, int,
52 53 int (*)(caddr_t), caddr_t);
53 54 extern void scsi_free_cache_pkt(struct scsi_address *, struct scsi_pkt *);
54 55 extern void scsi_cache_dmafree(struct scsi_address *, struct scsi_pkt *);
55 56 extern void scsi_sync_cache_pkt(struct scsi_address *, struct scsi_pkt *);
56 57 extern int modrootloaded;
57 58
58 59 /*
59 60 * Round up all allocations so that we can guarantee
60 61 * long-long alignment. This is the same alignment
61 62 * provided by kmem_alloc().
62 63 */
63 64 #define ROUNDUP(x) (((x) + 0x07) & ~0x07)
64 65
65 66 /* Magic number to track correct allocations in wrappers */
66 67 #define PKT_WRAPPER_MAGIC 0xa110ced /* alloced correctly */
67 68
68 69 kmutex_t scsi_flag_nointr_mutex;
69 70 kcondvar_t scsi_flag_nointr_cv;
70 71 kmutex_t scsi_log_mutex;
71 72
72 73 /* asynchronous probe barrier deletion data structures */
73 74 static kmutex_t scsi_hba_barrier_mutex;
74 75 static kcondvar_t scsi_hba_barrier_cv;
75 76 static struct scsi_hba_barrier {
76 77 struct scsi_hba_barrier *barrier_next;
77 78 clock_t barrier_endtime;
78 79 dev_info_t *barrier_probe;
79 80 } *scsi_hba_barrier_list;
80 81 static int scsi_hba_devi_is_barrier(dev_info_t *probe);
81 82 static void scsi_hba_barrier_tran_tgt_free(dev_info_t *probe);
82 83 static void scsi_hba_barrier_add(dev_info_t *probe, int seconds);
83 84 static int scsi_hba_remove_node(dev_info_t *child);
84 85 static void scsi_hba_barrier_daemon(void *arg);
85 86
86 87 /* LUN-change ASC/ASCQ processing data structures (stage1 and stage2) */
87 88 static kmutex_t scsi_lunchg1_mutex;
88 89 static kcondvar_t scsi_lunchg1_cv;
89 90 static struct scsi_pkt *scsi_lunchg1_list;
90 91 static void scsi_lunchg1_daemon(void *arg);
91 92 static kmutex_t scsi_lunchg2_mutex;
92 93 static kcondvar_t scsi_lunchg2_cv;
93 94 static struct scsi_lunchg2 {
94 95 struct scsi_lunchg2 *lunchg2_next;
95 96 char *lunchg2_path;
96 97 } *scsi_lunchg2_list;
97 98 static void scsi_lunchg2_daemon(void *arg);
98 99
99 100 static int scsi_findchild(dev_info_t *self, char *name, char *addr,
100 101 int init, dev_info_t **dchildp, mdi_pathinfo_t **pchildp, int *ppi);
101 102
102 103 /* return value defines for scsi_findchild */
103 104 #define CHILD_TYPE_NONE 0
104 105 #define CHILD_TYPE_DEVINFO 1
105 106 #define CHILD_TYPE_PATHINFO 2
106 107
107 108 /*
108 109 * Enumeration code path currently being followed. SE_BUSCONFIG results in
109 110 * DEVI_SID_NODEID, and SE_HP (hotplug) results in DEVI_SID_HP_NODEID.
110 111 *
111 112 * Since hotplug enumeration is based on information obtained from hardware
112 113 * (tgtmap/report_lun) the type/severity of enumeration error messages is
113 114 * sometimes based SE_HP (indirectly via ndi_dev_is_hotplug_node()). By
114 115 * convention, these messages are all produced by scsi_enumeration_failed().
115 116 */
116 117 typedef enum { SE_BUSCONFIG = 0, SE_HP = 1 } scsi_enum_t;
117 118
118 119 /* compatible properties of driver to use during probe/enumeration operations */
119 120 static char *compatible_probe = "scsa,probe";
120 121 static char *compatible_nodev = "scsa,nodev";
121 122 static char *scsi_probe_ascii[] = SCSIPROBE_ASCII;
122 123
123 124 /* number of LUNs we attempt to get on the first SCMD_REPORT_LUNS command */
124 125 int scsi_lunrpt_default_max = 256;
125 126 int scsi_lunrpt_timeout = 3; /* seconds */
126 127
127 128 /*
128 129 * Only enumerate one lun if reportluns fails on a SCSI_VERSION_3 device
129 130 * (tunable based on calling context).
130 131 */
131 132 int scsi_lunrpt_failed_do1lun = (1 << SE_HP);
132 133
133 134 /* 'scsi-binding-set' value for legacy enumerated 'spi' transports */
134 135 char *scsi_binding_set_spi = "spi";
135 136
136 137 /* enable NDI_DEVI_DEBUG for bus_[un]config operations */
137 138 int scsi_hba_bus_config_debug = 0;
138 139
139 140 /* DEBUG: enable NDI_DEVI_REMOVE for bus_unconfig of dynamic node */
140 141 int scsi_hba_bus_unconfig_remove = 0;
141 142
142 143 /* number of probe serilization messages */
143 144 int scsi_hba_wait_msg = 5;
144 145
145 146 /*
146 147 * Establish the timeout used to cache (in the probe node) the fact that the
147 148 * device does not exist. This replaces the target specific probe cache.
148 149 */
149 150 int scsi_hba_barrier_timeout = (60); /* seconds */
150 151
151 152 #ifdef DEBUG
152 153 int scsi_hba_bus_config_failure_msg = 0;
153 154 int scsi_hba_bus_config_failure_dbg = 0;
154 155 int scsi_hba_bus_config_success_msg = 0;
155 156 int scsi_hba_bus_config_success_dbg = 0;
156 157 #endif /* DEBUG */
157 158
158 159 /*
159 160 * Structure for scsi_hba_iportmap_* implementation/wrap.
160 161 */
161 162 typedef struct impl_scsi_iportmap {
162 163 dev_info_t *iportmap_hba_dip;
163 164 damap_t *iportmap_dam;
164 165 int iportmap_create_window;
165 166 uint64_t iportmap_create_time; /* clock64_t */
166 167 int iportmap_create_csync_usec;
167 168 int iportmap_settle_usec;
168 169 int iportmap_sync_cnt;
169 170 } impl_scsi_iportmap_t;
170 171
171 172 /*
172 173 * Structure for scsi_hba_tgtmap_* implementation/wrap.
173 174 *
174 175 * Every call to scsi_hba_tgtmap_set_begin will increment tgtmap_reports,
175 176 * and a call to scsi_hba_tgtmap_set_end will reset tgtmap_reports to zero.
176 177 * If, in scsi_hba_tgtmap_set_begin, we detect a tgtmap_reports value of
177 178 * scsi_hba_tgtmap_reports_max we produce a message to indicate that
178 179 * the caller is never completing an observation (i.e. we are not making
179 180 * any forward progress). If this message occurs, it indicates that the
180 181 * solaris hotplug ramifications at the target and lun level are no longer
181 182 * tracking.
182 183 *
183 184 * NOTE: LUNMAPSIZE OK for now, but should be dynamic in reportlun code.
184 185 */
185 186 typedef struct impl_scsi_tgtmap {
186 187 scsi_hba_tran_t *tgtmap_tran;
187 188 int tgtmap_reports; /* _begin, no _end */
188 189 int tgtmap_noisy;
189 190 scsi_tgt_activate_cb_t tgtmap_activate_cb;
190 191 scsi_tgt_deactivate_cb_t tgtmap_deactivate_cb;
191 192 void *tgtmap_mappriv;
192 193 damap_t *tgtmap_dam[SCSI_TGT_NTYPES];
193 194 int tgtmap_create_window;
194 195 uint64_t tgtmap_create_time; /* clock64_t */
195 196 int tgtmap_create_csync_usec;
196 197 int tgtmap_settle_usec;
197 198 int tgtmap_sync_cnt;
198 199 } impl_scsi_tgtmap_t;
199 200 #define LUNMAPSIZE 256 /* 256 LUNs/target */
200 201
201 202 /* Produce warning if number of begins without an end exceed this value */
202 203 int scsi_hba_tgtmap_reports_max = 256;
203 204
204 205 static int scsi_tgtmap_sync(scsi_hba_tgtmap_t *, int);
205 206
206 207 /* Default settle_usec damap_sync factor */
207 208 int scsi_hba_map_settle_f = 10;
208 209
209 210
210 211 /* Prototype for static dev_ops devo_*() functions */
211 212 static int scsi_hba_info(
212 213 dev_info_t *self,
213 214 ddi_info_cmd_t infocmd,
214 215 void *arg,
215 216 void **result);
216 217
217 218 /* Prototypes for static bus_ops bus_*() functions */
218 219 static int scsi_hba_bus_ctl(
219 220 dev_info_t *self,
220 221 dev_info_t *child,
221 222 ddi_ctl_enum_t op,
222 223 void *arg,
223 224 void *result);
224 225
225 226 static int scsi_hba_map_fault(
226 227 dev_info_t *self,
227 228 dev_info_t *child,
228 229 struct hat *hat,
229 230 struct seg *seg,
230 231 caddr_t addr,
231 232 struct devpage *dp,
232 233 pfn_t pfn,
233 234 uint_t prot,
234 235 uint_t lock);
235 236
236 237 static int scsi_hba_get_eventcookie(
237 238 dev_info_t *self,
238 239 dev_info_t *child,
239 240 char *name,
240 241 ddi_eventcookie_t *eventp);
241 242
242 243 static int scsi_hba_add_eventcall(
243 244 dev_info_t *self,
244 245 dev_info_t *child,
245 246 ddi_eventcookie_t event,
246 247 void (*callback)(
247 248 dev_info_t *dip,
248 249 ddi_eventcookie_t event,
249 250 void *arg,
250 251 void *bus_impldata),
251 252 void *arg,
252 253 ddi_callback_id_t *cb_id);
253 254
254 255 static int scsi_hba_remove_eventcall(
255 256 dev_info_t *self,
256 257 ddi_callback_id_t id);
257 258
258 259 static int scsi_hba_post_event(
259 260 dev_info_t *self,
260 261 dev_info_t *child,
261 262 ddi_eventcookie_t event,
262 263 void *bus_impldata);
263 264
264 265 static int scsi_hba_bus_config(
265 266 dev_info_t *self,
266 267 uint_t flags,
267 268 ddi_bus_config_op_t op,
268 269 void *arg,
269 270 dev_info_t **childp);
270 271
271 272 static int scsi_hba_bus_unconfig(
272 273 dev_info_t *self,
273 274 uint_t flags,
274 275 ddi_bus_config_op_t op,
275 276 void *arg);
276 277
277 278 static int scsi_hba_fm_init_child(
278 279 dev_info_t *self,
279 280 dev_info_t *child,
280 281 int cap,
281 282 ddi_iblock_cookie_t *ibc);
282 283
283 284 static int scsi_hba_bus_power(
284 285 dev_info_t *self,
285 286 void *impl_arg,
286 287 pm_bus_power_op_t op,
287 288 void *arg,
288 289 void *result);
289 290
290 291 /* bus_ops vector for SCSI HBA's. */
291 292 static struct bus_ops scsi_hba_busops = {
292 293 BUSO_REV,
293 294 nullbusmap, /* bus_map */
294 295 NULL, /* bus_get_intrspec */
295 296 NULL, /* bus_add_intrspec */
296 297 NULL, /* bus_remove_intrspec */
297 298 scsi_hba_map_fault, /* bus_map_fault */
298 299 NULL, /* bus_dma_map */
299 300 ddi_dma_allochdl, /* bus_dma_allochdl */
300 301 ddi_dma_freehdl, /* bus_dma_freehdl */
301 302 ddi_dma_bindhdl, /* bus_dma_bindhdl */
302 303 ddi_dma_unbindhdl, /* bus_unbindhdl */
303 304 ddi_dma_flush, /* bus_dma_flush */
304 305 ddi_dma_win, /* bus_dma_win */
305 306 ddi_dma_mctl, /* bus_dma_ctl */
306 307 scsi_hba_bus_ctl, /* bus_ctl */
307 308 ddi_bus_prop_op, /* bus_prop_op */
308 309 scsi_hba_get_eventcookie, /* bus_get_eventcookie */
309 310 scsi_hba_add_eventcall, /* bus_add_eventcall */
310 311 scsi_hba_remove_eventcall, /* bus_remove_eventcall */
311 312 scsi_hba_post_event, /* bus_post_event */
312 313 NULL, /* bus_intr_ctl */
313 314 scsi_hba_bus_config, /* bus_config */
314 315 scsi_hba_bus_unconfig, /* bus_unconfig */
315 316 scsi_hba_fm_init_child, /* bus_fm_init */
316 317 NULL, /* bus_fm_fini */
317 318 NULL, /* bus_fm_access_enter */
318 319 NULL, /* bus_fm_access_exit */
319 320 scsi_hba_bus_power /* bus_power */
320 321 };
321 322
322 323 /* cb_ops for hotplug :devctl and :scsi support */
323 324 static struct cb_ops scsi_hba_cbops = {
324 325 scsi_hba_open,
325 326 scsi_hba_close,
326 327 nodev, /* strategy */
327 328 nodev, /* print */
328 329 nodev, /* dump */
329 330 nodev, /* read */
330 331 nodev, /* write */
331 332 scsi_hba_ioctl, /* ioctl */
332 333 nodev, /* devmap */
333 334 nodev, /* mmap */
334 335 nodev, /* segmap */
335 336 nochpoll, /* poll */
336 337 ddi_prop_op, /* prop_op */
337 338 NULL, /* stream */
338 339 D_NEW|D_MP|D_HOTPLUG, /* cb_flag */
339 340 CB_REV, /* rev */
340 341 nodev, /* int (*cb_aread)() */
341 342 nodev /* int (*cb_awrite)() */
342 343 };
343 344
344 345 /* Prototypes for static scsi_hba.c/SCSA private lunmap interfaces */
345 346 static int scsi_lunmap_create(
346 347 dev_info_t *self,
347 348 impl_scsi_tgtmap_t *tgtmap,
348 349 char *tgt_addr);
349 350 static void scsi_lunmap_destroy(
350 351 dev_info_t *self,
351 352 impl_scsi_tgtmap_t *tgtmap,
352 353 char *tgt_addr);
353 354 static void scsi_lunmap_set_begin(
354 355 dev_info_t *self,
355 356 damap_t *lundam);
356 357 static int scsi_lunmap_set_add(
357 358 dev_info_t *self,
358 359 damap_t *lundam,
359 360 char *taddr,
360 361 scsi_lun64_t lun_num,
361 362 int lun_sfunc);
362 363 static void scsi_lunmap_set_end(
363 364 dev_info_t *self,
364 365 damap_t *lundam);
365 366
366 367 /* Prototypes for static misc. scsi_hba.c private bus_config interfaces */
367 368 static int scsi_hba_bus_config_iports(dev_info_t *self, uint_t flags,
368 369 ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
369 370 static int scsi_hba_bus_config_spi(dev_info_t *self, uint_t flags,
370 371 ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
371 372 static dev_info_t *scsi_hba_bus_config_port(dev_info_t *self,
372 373 char *nameaddr, scsi_enum_t se);
373 374
374 375 #ifdef sparc
375 376 static int scsi_hba_bus_config_prom_node(dev_info_t *self, uint_t flags,
376 377 void *arg, dev_info_t **childp);
377 378 #endif /* sparc */
378 379
379 380
380 381 /*
381 382 * SCSI_HBA_LOG is used for all messages. A logging level is specified when
382 383 * generating a message. Some levels correspond directly to cmn_err levels,
383 384 * some are associated with increasing levels diagnostic/debug output (LOG1-4),
384 385 * and others are associated with specific levels of interface (LOGMAP).
385 386 * For _LOG() messages, a __func__ prefix will identify the function origin
386 387 * of the message. For _LOG_NF messages, there is no function prefix or
387 388 * self/child context. Filtering of messages is provided based on logging
388 389 * level, but messages with cmn_err logging level and messages generated
389 390 * generated with _LOG_NF() are never filtered.
390 391 *
391 392 * For debugging, more complete information can be displayed with each message
392 393 * (full device path and pointer values) by adjusting scsi_hba_log_info.
393 394 */
394 395 /* logging levels */
395 396 #define SCSI_HBA_LOGCONT CE_CONT
396 397 #define SCSI_HBA_LOGNOTE CE_NOTE
397 398 #define SCSI_HBA_LOGWARN CE_WARN
398 399 #define SCSI_HBA_LOGPANIC CE_PANIC
399 400 #define SCSI_HBA_LOGIGNORE CE_IGNORE
400 401 #define SCSI_HBA_LOG_CE_MASK 0x0000000F /* no filter for these levels */
401 402 #define SCSI_HBA_LOG1 0x00000010 /* DIAG1 level enable */
402 403 #define SCSI_HBA_LOG2 0x00000020 /* DIAG2 level enable */
403 404 #define SCSI_HBA_LOG3 0x00000040 /* DIAG3 level enable */
404 405 #define SCSI_HBA_LOG4 0x00000080 /* DIAG4 level enable */
405 406 #define SCSI_HBA_LOGMAPPHY 0x00000100 /* MAPPHY level enable */
406 407 #define SCSI_HBA_LOGMAPIPT 0x00000200 /* MAPIPT level enable */
407 408 #define SCSI_HBA_LOGMAPTGT 0x00000400 /* MAPTGT level enable */
408 409 #define SCSI_HBA_LOGMAPLUN 0x00000800 /* MAPLUN level enable */
409 410 #define SCSI_HBA_LOGMAPCFG 0x00001000 /* MAPCFG level enable */
410 411 #define SCSI_HBA_LOGMAPUNCFG 0x00002000 /* MAPUNCFG level enable */
411 412 #define SCSI_HBA_LOGTRACE 0x00010000 /* TRACE enable */
412 413 #if (CE_CONT | CE_NOTE | CE_WARN | CE_PANIC | CE_IGNORE) > SCSI_HBA_LOG_CE_MASK
413 414 Error, problem with CE_ definitions
414 415 #endif
415 416
416 417 /*
417 418 * Tunable log message augmentation and filters: filters do not apply to
418 419 * SCSI_HBA_LOG_CE_MASK level messages or LOG_NF() messages.
419 420 *
420 421 * An example set of /etc/system tunings to simplify debug a SCSA pHCI HBA
421 422 * driver called "pmcs", including "scsi_vhci" operation, by capturing
422 423 * log information in the system log might be:
423 424 *
424 425 * echo "set scsi:scsi_hba_log_filter_level=0x3ff0" >> /etc/system
425 426 * echo "set scsi:scsi_hba_log_filter_phci=\"pmcs\"" >> /etc/system
426 427 * echo "set scsi:scsi_hba_log_filter_vhci=\"scsi_vhci\"" >> /etc/system
427 428 *
428 429 * To capture information on just HBA-SCSAv3 *map operation, use
429 430 * echo "set scsi:scsi_hba_log_filter_level=0x3f10" >> /etc/system
430 431 *
431 432 * For debugging an HBA driver, you may also want to set:
432 433 *
433 434 * echo "set scsi:scsi_hba_log_align=1" >> /etc/system
434 435 * echo "set scsi:scsi_hba_log_mt_disable=0x6" >> /etc/system
435 436 * echo "set mtc_off=1" >> /etc/system
436 437 * echo "set mdi_mtc_off=1" >> /etc/system
437 438 * echo "set scsi:scsi_hba_log_fcif=0" >> /etc/system
438 439 */
439 440 int scsi_hba_log_filter_level =
440 441 SCSI_HBA_LOG1 |
441 442 0;
442 443 char *scsi_hba_log_filter_phci = "\0\0\0\0\0\0\0\0\0\0\0\0";
443 444 char *scsi_hba_log_filter_vhci = "\0\0\0\0\0\0\0\0\0\0\0\0";
444 445 int scsi_hba_log_align = 0; /* NOTE: will not cause truncation */
445 446 int scsi_hba_log_fcif = '!'; /* "^!?" first char in format */
446 447 /* NOTE: iff level > SCSI_HBA_LOG1 */
447 448 /* '\0'0x00 -> console and system log */
448 449 /* '^' 0x5e -> console_only */
449 450 /* '!' 0x21 -> system log only */
450 451 /* '?' 0x2F -> See cmn_err(9F) */
451 452 int scsi_hba_log_info = /* augmentation: extra info output */
452 453 (0 << 0) | /* 0x0001: process information */
453 454 (0 << 1) | /* 0x0002: full /devices path */
454 455 (0 << 2); /* 0x0004: devinfo pointer */
455 456
456 457 int scsi_hba_log_mt_disable =
457 458 /* SCSI_ENUMERATION_MT_LUN_DISABLE | (ie 0x02) */
458 459 /* SCSI_ENUMERATION_MT_TARGET_DISABLE | (ie 0x04) */
459 460 0;
460 461
461 462 /* static data for HBA logging subsystem */
462 463 static kmutex_t scsi_hba_log_mutex;
463 464 static char scsi_hba_log_i[512];
464 465 static char scsi_hba_log_buf[512];
465 466 static char scsi_hba_fmt[512];
466 467
467 468 /* Macros to use in scsi_hba.c source code below */
468 469 #define SCSI_HBA_LOG(x) scsi_hba_log x
469 470 #define _LOG(level) SCSI_HBA_LOG##level, __func__
470 471 #define _MAP(map) SCSI_HBA_LOGMAP##map, __func__
471 472 #define _LOG_NF(level) SCSI_HBA_LOG##level, NULL, NULL, NULL
472 473 #define _LOG_TRACE _LOG(TRACE)
473 474 #define _LOGLUN _MAP(LUN)
474 475 #define _LOGTGT _MAP(TGT)
475 476 #define _LOGIPT _MAP(IPT)
476 477 #define _LOGPHY _MAP(PHY)
477 478 #define _LOGCFG _MAP(CFG)
478 479 #define _LOGUNCFG _MAP(UNCFG)
479 480
480 481 /*PRINTFLIKE5*/
481 482 static void
482 483 scsi_hba_log(int level, const char *func, dev_info_t *self, dev_info_t *child,
483 484 const char *fmt, ...)
484 485 {
485 486 va_list ap;
486 487 int clevel;
487 488 int align;
488 489 char *info;
489 490 char *f;
490 491 char *ua;
491 492
492 493 /* derive self from child's parent */
493 494 if ((self == NULL) && child)
494 495 self = ddi_get_parent(child);
495 496
496 497 /* no filtering of SCSI_HBA_LOG_CE_MASK or LOG_NF messages */
497 498 if (((level & SCSI_HBA_LOG_CE_MASK) != level) && (func != NULL)) {
498 499 /* scsi_hba_log_filter_level: filter on level as bitmask */
499 500 if ((level & scsi_hba_log_filter_level) == 0)
500 501 return;
501 502
502 503 /* scsi_hba_log_filter_phci/vhci: on name of driver */
503 504 if (*scsi_hba_log_filter_phci &&
504 505 ((self == NULL) ||
505 506 (ddi_driver_name(self) == NULL) ||
506 507 strcmp(ddi_driver_name(self), scsi_hba_log_filter_phci))) {
507 508 /* does not match pHCI, check vHCI */
508 509 if (*scsi_hba_log_filter_vhci &&
509 510 ((self == NULL) ||
510 511 (ddi_driver_name(self) == NULL) ||
511 512 strcmp(ddi_driver_name(self),
512 513 scsi_hba_log_filter_vhci))) {
513 514 /* does not match vHCI */
514 515 return;
515 516 }
516 517 }
517 518
518 519
519 520 /* passed filters, determine align */
520 521 align = scsi_hba_log_align;
521 522
522 523 /* shorten func for filtered output */
523 524 if (strncmp(func, "scsi_hba_", 9) == 0)
524 525 func += 9;
525 526 if (strncmp(func, "scsi_", 5) == 0)
526 527 func += 5;
527 528 } else {
528 529 /* don't align output that is never filtered */
529 530 align = 0;
530 531 }
531 532
532 533 /* determine the cmn_err form from the level */
533 534 clevel = ((level & SCSI_HBA_LOG_CE_MASK) == level) ? level : CE_CONT;
534 535
535 536 /* protect common buffers used to format output */
536 537 mutex_enter(&scsi_hba_log_mutex);
537 538
538 539 /* skip special first characters, we add them back below */
539 540 f = (char *)fmt;
540 541 if (*f && strchr("^!?", *f))
541 542 f++;
542 543 va_start(ap, fmt);
543 544 (void) vsprintf(scsi_hba_log_buf, f, ap);
544 545 va_end(ap);
545 546
546 547 /* augment message with 'information' */
547 548 info = scsi_hba_log_i;
548 549 *info = '\0';
549 550 if ((scsi_hba_log_info & 0x0001) && curproc && PTOU(curproc)->u_comm) {
550 551 (void) sprintf(info, "%s[%d]%p ",
551 552 PTOU(curproc)->u_comm, curproc->p_pid, (void *)curthread);
552 553 info += strlen(info);
553 554 }
554 555 if (self) {
555 556 if ((scsi_hba_log_info & 0x0004) && (child || self)) {
556 557 (void) sprintf(info, "%p ",
557 558 (void *)(child ? child : self));
558 559 info += strlen(info);
559 560 }
560 561 if (scsi_hba_log_info & 0x0002) {
561 562 (void) ddi_pathname(child ? child : self, info);
562 563 (void) strcat(info, " ");
563 564 info += strlen(info);
564 565 }
565 566
566 567 /* always provide 'default' information about self &child */
567 568 (void) sprintf(info, "%s%d ", ddi_driver_name(self),
568 569 ddi_get_instance(self));
569 570 info += strlen(info);
570 571 if (child) {
571 572 ua = ddi_get_name_addr(child);
572 573 (void) sprintf(info, "%s@%s ",
573 574 ddi_node_name(child), (ua && *ua) ? ua : "");
574 575 info += strlen(info);
575 576 }
576 577 }
577 578
578 579 /* turn off alignment if truncation would occur */
579 580 if (align && ((strlen(func) > 18) || (strlen(scsi_hba_log_i) > 36)))
580 581 align = 0;
581 582
582 583 /* adjust for aligned output */
583 584 if (align) {
584 585 if (func == NULL)
585 586 func = "";
586 587 /* remove trailing blank with align output */
587 588 if ((info != scsi_hba_log_i) && (*(info -1) == '\b'))
588 589 *(info - 1) = '\0';
589 590 }
590 591
591 592 /* special "first character in format" must be in format itself */
592 593 f = scsi_hba_fmt;
593 594 if (fmt[0] && strchr("^!?", fmt[0]))
594 595 *f++ = fmt[0];
595 596 else if (scsi_hba_log_fcif && (level > SCSI_HBA_LOG1))
596 597 *f++ = (char)scsi_hba_log_fcif; /* add global fcif */
597 598 if (align)
598 599 (void) sprintf(f, "%s", "%-18.18s: %36.36s: %s%s");
599 600 else
600 601 (void) sprintf(f, "%s", func ? "%s: %s%s%s" : "%s%s%s");
601 602
602 603 if (func)
603 604 cmn_err(clevel, scsi_hba_fmt, func, scsi_hba_log_i,
604 605 scsi_hba_log_buf, clevel == CE_CONT ? "\n" : "");
605 606 else
606 607 cmn_err(clevel, scsi_hba_fmt, scsi_hba_log_i,
607 608 scsi_hba_log_buf, clevel == CE_CONT ? "\n" : "");
608 609 mutex_exit(&scsi_hba_log_mutex);
609 610 }
610 611
611 612 int scsi_enumeration_failed_panic = 0;
612 613 int scsi_enumeration_failed_hotplug = 1;
613 614
614 615 static void
615 616 scsi_enumeration_failed(dev_info_t *child, scsi_enum_t se,
616 617 char *arg, char *when)
617 618 {
618 619 /* If 'se' is -1 the 'se' value comes from child. */
619 620 if (se == -1) {
620 621 ASSERT(child);
621 622 se = ndi_dev_is_hotplug_node(child) ? SE_HP : SE_BUSCONFIG;
622 623 }
623 624
624 625 if (scsi_enumeration_failed_panic) {
625 626 /* set scsi_enumeration_failed_panic to debug */
626 627 SCSI_HBA_LOG((_LOG(PANIC), NULL, child,
627 628 "%s%senumeration failed during %s",
628 629 arg ? arg : "", arg ? " " : "", when));
629 630 } else if (scsi_enumeration_failed_hotplug && (se == SE_HP)) {
630 631 /* set scsi_enumeration_failed_hotplug for console messages */
631 632 SCSI_HBA_LOG((_LOG(WARN), NULL, child,
632 633 "%s%senumeration failed during %s",
633 634 arg ? arg : "", arg ? " " : "", when));
634 635 } else {
635 636 /* default */
636 637 SCSI_HBA_LOG((_LOG(2), NULL, child,
637 638 "%s%senumeration failed during %s",
638 639 arg ? arg : "", arg ? " " : "", when));
639 640 }
640 641 }
641 642
642 643 /*
643 644 * scsi_hba version of [nm]di_devi_enter/[nm]di_devi_exit that detects if HBA
644 645 * is a PHCI, and chooses mdi/ndi locking implementation.
645 646 */
646 647 static void
647 648 scsi_hba_devi_enter(dev_info_t *self, int *circp)
648 649 {
649 650 if (MDI_PHCI(self))
650 651 mdi_devi_enter(self, circp);
651 652 else
652 653 ndi_devi_enter(self, circp);
653 654 }
654 655
655 656 static int
656 657 scsi_hba_devi_tryenter(dev_info_t *self, int *circp)
657 658 {
658 659 if (MDI_PHCI(self))
659 660 return (mdi_devi_tryenter(self, circp));
660 661 else
661 662 return (ndi_devi_tryenter(self, circp));
662 663 }
663 664
664 665 static void
665 666 scsi_hba_devi_exit(dev_info_t *self, int circ)
666 667 {
667 668 if (MDI_PHCI(self))
668 669 mdi_devi_exit(self, circ);
669 670 else
670 671 ndi_devi_exit(self, circ);
671 672 }
672 673
673 674 static void
674 675 scsi_hba_devi_enter_phci(dev_info_t *self, int *circp)
675 676 {
676 677 if (MDI_PHCI(self))
677 678 mdi_devi_enter_phci(self, circp);
678 679 }
679 680
680 681 static void
681 682 scsi_hba_devi_exit_phci(dev_info_t *self, int circ)
682 683 {
683 684 if (MDI_PHCI(self))
684 685 mdi_devi_exit_phci(self, circ);
685 686 }
686 687
687 688 static int
688 689 scsi_hba_dev_is_sid(dev_info_t *child)
689 690 {
690 691 /*
691 692 * Use ndi_dev_is_persistent_node instead of ddi_dev_is_sid to avoid
692 693 * any possible locking issues in mixed nexus devctl code (like usb).
693 694 */
694 695 return (ndi_dev_is_persistent_node(child));
695 696 }
696 697
697 698 /*
698 699 * Called from _init() when loading "scsi" module
699 700 */
700 701 void
701 702 scsi_initialize_hba_interface()
702 703 {
703 704 SCSI_HBA_LOG((_LOG_TRACE, NULL, NULL, __func__));
704 705
705 706 /* We need "scsiprobe" and "scsinodev" as an alias or a driver. */
706 707 if (ddi_name_to_major(compatible_probe) == DDI_MAJOR_T_NONE) {
707 708 SCSI_HBA_LOG((_LOG_NF(WARN), "failed to resolve '%s' "
708 709 "driver alias, defaulting to 'nulldriver'",
709 710 compatible_probe));
710 711
711 712 /* If no "nulldriver" driver nothing will work... */
712 713 compatible_probe = "nulldriver";
713 714 if (ddi_name_to_major(compatible_probe) == DDI_MAJOR_T_NONE)
714 715 SCSI_HBA_LOG((_LOG_NF(WARN), "no probe '%s' driver, "
715 716 "system misconfigured", compatible_probe));
716 717 }
717 718 if (ddi_name_to_major(compatible_nodev) == DDI_MAJOR_T_NONE) {
718 719 SCSI_HBA_LOG((_LOG_NF(WARN), "failed to resolve '%s' "
719 720 "driver alias, defaulting to 'nulldriver'",
720 721 compatible_nodev));
721 722
722 723 /* If no "nulldriver" driver nothing will work... */
723 724 compatible_nodev = "nulldriver";
724 725 if (ddi_name_to_major(compatible_nodev) == DDI_MAJOR_T_NONE)
725 726 SCSI_HBA_LOG((_LOG_NF(WARN), "no nodev '%s' driver, "
726 727 "system misconfigured", compatible_nodev));
727 728 }
728 729
729 730 /*
730 731 * Verify our special node name "probe" will not be used in other ways.
731 732 * Don't expect things to work if they are.
732 733 */
733 734 if (ddi_major_to_name(ddi_name_to_major("probe")))
734 735 SCSI_HBA_LOG((_LOG_NF(WARN),
735 736 "driver already using special node name 'probe'"));
736 737
737 738 mutex_init(&scsi_log_mutex, NULL, MUTEX_DRIVER, NULL);
738 739 mutex_init(&scsi_flag_nointr_mutex, NULL, MUTEX_DRIVER, NULL);
739 740 cv_init(&scsi_flag_nointr_cv, NULL, CV_DRIVER, NULL);
740 741 mutex_init(&scsi_hba_log_mutex, NULL, MUTEX_DRIVER, NULL);
741 742
742 743 /* initialize the asynchronous barrier deletion daemon */
743 744 mutex_init(&scsi_hba_barrier_mutex, NULL, MUTEX_DRIVER, NULL);
744 745 cv_init(&scsi_hba_barrier_cv, NULL, CV_DRIVER, NULL);
745 746 (void) thread_create(NULL, 0,
746 747 (void (*)())scsi_hba_barrier_daemon, NULL,
747 748 0, &p0, TS_RUN, minclsyspri);
748 749
749 750 /* initialize lun change ASC/ASCQ processing daemon (stage1 & stage2) */
750 751 mutex_init(&scsi_lunchg1_mutex, NULL, MUTEX_DRIVER, NULL);
751 752 cv_init(&scsi_lunchg1_cv, NULL, CV_DRIVER, NULL);
752 753 (void) thread_create(NULL, 0,
753 754 (void (*)())scsi_lunchg1_daemon, NULL,
754 755 0, &p0, TS_RUN, minclsyspri);
755 756 mutex_init(&scsi_lunchg2_mutex, NULL, MUTEX_DRIVER, NULL);
756 757 cv_init(&scsi_lunchg2_cv, NULL, CV_DRIVER, NULL);
757 758 (void) thread_create(NULL, 0,
758 759 (void (*)())scsi_lunchg2_daemon, NULL,
759 760 0, &p0, TS_RUN, minclsyspri);
760 761 }
761 762
762 763 int
763 764 scsi_hba_pkt_constructor(void *buf, void *arg, int kmflag)
764 765 {
765 766 struct scsi_pkt_cache_wrapper *pktw;
766 767 struct scsi_pkt *pkt;
767 768 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
768 769 int pkt_len;
769 770 char *ptr;
770 771
771 772 /*
772 773 * allocate a chunk of memory for the following:
773 774 * scsi_pkt
774 775 * pcw_* fields
775 776 * pkt_ha_private
776 777 * pkt_cdbp, if needed
777 778 * (pkt_private always null)
778 779 * pkt_scbp, if needed
779 780 */
780 781 pkt_len = tran->tran_hba_len + sizeof (struct scsi_pkt_cache_wrapper);
781 782 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CDB)
782 783 pkt_len += DEFAULT_CDBLEN;
783 784 if (tran->tran_hba_flags & SCSI_HBA_TRAN_SCB)
784 785 pkt_len += DEFAULT_SCBLEN;
785 786 bzero(buf, pkt_len);
786 787
787 788 ptr = buf;
788 789 pktw = buf;
789 790 ptr += sizeof (struct scsi_pkt_cache_wrapper);
790 791 pkt = &(pktw->pcw_pkt);
791 792 pkt->pkt_ha_private = (opaque_t)ptr;
792 793
793 794 pktw->pcw_magic = PKT_WRAPPER_MAGIC; /* alloced correctly */
794 795 /*
795 796 * keep track of the granularity at the time this handle was
796 797 * allocated
797 798 */
798 799 pktw->pcw_granular = tran->tran_dma_attr.dma_attr_granular;
799 800
800 801 if (ddi_dma_alloc_handle(tran->tran_hba_dip, &tran->tran_dma_attr,
801 802 kmflag == KM_SLEEP ? SLEEP_FUNC: NULL_FUNC, NULL,
802 803 &pkt->pkt_handle) != DDI_SUCCESS) {
803 804
804 805 return (-1);
805 806 }
806 807 ptr += tran->tran_hba_len;
807 808 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CDB) {
808 809 pkt->pkt_cdbp = (opaque_t)ptr;
809 810 ptr += DEFAULT_CDBLEN;
810 811 }
811 812 pkt->pkt_private = NULL;
812 813 if (tran->tran_hba_flags & SCSI_HBA_TRAN_SCB)
813 814 pkt->pkt_scbp = (opaque_t)ptr;
814 815 if (tran->tran_pkt_constructor)
815 816 return ((*tran->tran_pkt_constructor)(pkt, arg, kmflag));
816 817 else
817 818 return (0);
818 819 }
819 820
820 821 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
821 822
822 823 void
823 824 scsi_hba_pkt_destructor(void *buf, void *arg)
824 825 {
825 826 struct scsi_pkt_cache_wrapper *pktw = buf;
826 827 struct scsi_pkt *pkt = &(pktw->pcw_pkt);
827 828 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
828 829
829 830 ASSERT(pktw->pcw_magic == PKT_WRAPPER_MAGIC);
830 831 ASSERT((pktw->pcw_flags & PCW_BOUND) == 0);
831 832 if (tran->tran_pkt_destructor)
832 833 (*tran->tran_pkt_destructor)(pkt, arg);
833 834
834 835 /* make sure nobody messed with our pointers */
835 836 ASSERT(pkt->pkt_ha_private == (opaque_t)((char *)pkt +
836 837 sizeof (struct scsi_pkt_cache_wrapper)));
837 838 ASSERT(((tran->tran_hba_flags & SCSI_HBA_TRAN_SCB) == 0) ||
838 839 (pkt->pkt_scbp == (opaque_t)((char *)pkt +
839 840 tran->tran_hba_len +
840 841 (((tran->tran_hba_flags & SCSI_HBA_TRAN_CDB) == 0) ?
841 842 0 : DEFAULT_CDBLEN) +
842 843 DEFAULT_PRIVLEN + sizeof (struct scsi_pkt_cache_wrapper))));
843 844 ASSERT(((tran->tran_hba_flags & SCSI_HBA_TRAN_CDB) == 0) ||
844 845 (pkt->pkt_cdbp == (opaque_t)((char *)pkt +
845 846 tran->tran_hba_len +
846 847 sizeof (struct scsi_pkt_cache_wrapper))));
847 848 ASSERT(pkt->pkt_handle);
848 849 ddi_dma_free_handle(&pkt->pkt_handle);
849 850 pkt->pkt_handle = NULL;
850 851 pkt->pkt_numcookies = 0;
851 852 pktw->pcw_total_xfer = 0;
852 853 pktw->pcw_totalwin = 0;
853 854 pktw->pcw_curwin = 0;
854 855 }
855 856
856 857 /*
857 858 * Called by an HBA from _init() to plumb in common SCSA bus_ops and
858 859 * cb_ops for the HBA's :devctl and :scsi minor nodes.
859 860 */
860 861 int
861 862 scsi_hba_init(struct modlinkage *modlp)
862 863 {
863 864 struct dev_ops *hba_dev_ops;
864 865
865 866 SCSI_HBA_LOG((_LOG_TRACE, NULL, NULL, __func__));
866 867
867 868 /*
868 869 * Get a pointer to the dev_ops structure of the HBA and plumb our
869 870 * bus_ops vector into the HBA's dev_ops structure.
870 871 */
871 872 hba_dev_ops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
872 873 ASSERT(hba_dev_ops->devo_bus_ops == NULL);
873 874 hba_dev_ops->devo_bus_ops = &scsi_hba_busops;
874 875
875 876 /*
876 877 * Plumb our cb_ops vector into the HBA's dev_ops structure to
877 878 * provide getinfo and hotplugging ioctl support if the HBA driver
878 879 * does not already provide this support.
879 880 */
880 881 if (hba_dev_ops->devo_cb_ops == NULL) {
881 882 hba_dev_ops->devo_cb_ops = &scsi_hba_cbops;
882 883 }
883 884 if (hba_dev_ops->devo_cb_ops->cb_open == scsi_hba_open) {
884 885 ASSERT(hba_dev_ops->devo_cb_ops->cb_close == scsi_hba_close);
885 886 hba_dev_ops->devo_getinfo = scsi_hba_info;
886 887 }
887 888 return (0);
888 889 }
889 890
890 891 /*
891 892 * Called by an HBA attach(9E) to allocate a scsi_hba_tran(9S) structure. An
892 893 * HBA driver will then initialize the structure and then call
893 894 * scsi_hba_attach_setup(9F).
894 895 */
895 896 /*ARGSUSED*/
896 897 scsi_hba_tran_t *
897 898 scsi_hba_tran_alloc(
898 899 dev_info_t *self,
899 900 int flags)
900 901 {
901 902 scsi_hba_tran_t *tran;
902 903
903 904 SCSI_HBA_LOG((_LOG_TRACE, self, NULL, __func__));
904 905
905 906 /* allocate SCSA flavors for self */
906 907 ndi_flavorv_alloc(self, SCSA_NFLAVORS);
907 908
908 909 tran = kmem_zalloc(sizeof (scsi_hba_tran_t),
909 910 (flags & SCSI_HBA_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP);
910 911
911 912 if (tran) {
912 913 tran->tran_interconnect_type = INTERCONNECT_PARALLEL;
913 914
914 915 /*
915 916 * HBA driver called scsi_hba_tran_alloc(), so tran structure
916 917 * is proper size and unused/newer fields are zero.
917 918 *
918 919 * NOTE: We use SCSA_HBA_SCSA_TA as an obtuse form of
919 920 * versioning to detect old HBA drivers that do not use
920 921 * scsi_hba_tran_alloc, and would present garbage data
921 922 * (instead of valid/zero data) for newer tran fields.
922 923 */
923 924 tran->tran_hba_flags |= SCSI_HBA_SCSA_TA;
924 925 }
925 926
926 927 return (tran);
927 928 }
928 929
929 930 /*
930 931 * Called by an HBA to free a scsi_hba_tran structure
931 932 */
932 933 void
933 934 scsi_hba_tran_free(
934 935 scsi_hba_tran_t *tran)
935 936 {
936 937 SCSI_HBA_LOG((_LOG_TRACE, tran->tran_hba_dip, NULL, __func__));
937 938
938 939 kmem_free(tran, sizeof (scsi_hba_tran_t));
939 940 }
940 941
941 942 int
942 943 scsi_tran_ext_alloc(
943 944 scsi_hba_tran_t *tran,
944 945 size_t length,
945 946 int flags)
946 947 {
947 948 void *tran_ext;
948 949 int ret = DDI_FAILURE;
949 950
950 951 tran_ext = kmem_zalloc(length,
951 952 (flags & SCSI_HBA_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP);
952 953 if (tran_ext != NULL) {
953 954 tran->tran_extension = tran_ext;
954 955 ret = DDI_SUCCESS;
955 956 }
956 957 return (ret);
957 958 }
958 959
959 960 void
960 961 scsi_tran_ext_free(
961 962 scsi_hba_tran_t *tran,
962 963 size_t length)
963 964 {
964 965 if (tran->tran_extension != NULL) {
965 966 kmem_free(tran->tran_extension, length);
966 967 tran->tran_extension = NULL;
967 968 }
968 969 }
969 970
970 971 /*
971 972 * Common nexus teardown code: used by both scsi_hba_detach() on SCSA HBA node
972 973 * and iport_postdetach_tran_scsi_device() on a SCSA HBA iport node (and for
973 974 * failure cleanup). Undo scsa_nexus_setup in reverse order.
974 975 *
975 976 * NOTE: Since we are in the Solaris IO framework, we can depend on
976 977 * undocumented cleanup operations performed by other parts of the framework:
977 978 * like detach_node() calling ddi_prop_remove_all() and
978 979 * ddi_remove_minor_node(,NULL).
979 980 */
980 981 static void
981 982 scsa_nexus_teardown(dev_info_t *self, scsi_hba_tran_t *tran)
982 983 {
983 984 /* Teardown FMA. */
984 985 if (tran->tran_hba_flags & SCSI_HBA_SCSA_FM) {
985 986 ddi_fm_fini(self);
986 987 tran->tran_hba_flags &= ~SCSI_HBA_SCSA_FM;
987 988 }
988 989 }
989 990
990 991 /*
991 992 * Common nexus setup code: used by both scsi_hba_attach_setup() on SCSA HBA
992 993 * node and iport_preattach_tran_scsi_device() on a SCSA HBA iport node.
993 994 *
994 995 * This code makes no assumptions about tran use by scsi_device children.
995 996 */
996 997 static int
997 998 scsa_nexus_setup(dev_info_t *self, scsi_hba_tran_t *tran)
998 999 {
999 1000 int capable;
1000 1001 int scsa_minor;
1001 1002
1002 1003 /*
1003 1004 * NOTE: SCSA maintains an 'fm-capable' domain, in tran_fm_capable,
1004 1005 * that is not dependent (limited by) the capabilities of its parents.
1005 1006 * For example a devinfo node in a branch that is not
1006 1007 * DDI_FM_EREPORT_CAPABLE may report as capable, via tran_fm_capable,
1007 1008 * to its scsi_device children.
1008 1009 *
1009 1010 * Get 'fm-capable' property from driver.conf, if present. If not
1010 1011 * present, default to the scsi_fm_capable global (which has
1011 1012 * DDI_FM_EREPORT_CAPABLE set by default).
1012 1013 */
1013 1014 if (tran->tran_fm_capable == DDI_FM_NOT_CAPABLE)
1014 1015 tran->tran_fm_capable = ddi_prop_get_int(DDI_DEV_T_ANY, self,
1015 1016 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1016 1017 "fm-capable", scsi_fm_capable);
1017 1018
1018 1019 /*
1019 1020 * If an HBA is *not* doing its own fma support by calling
1020 1021 * ddi_fm_init() prior to scsi_hba_attach_setup(), we provide a minimal
1021 1022 * common SCSA implementation so that scsi_device children can generate
1022 1023 * ereports via scsi_fm_ereport_post(). We use ddi_fm_capable() to
1023 1024 * detect an HBA calling ddi_fm_init() prior to scsi_hba_attach_setup().
1024 1025 */
1025 1026 if (tran->tran_fm_capable &&
1026 1027 (ddi_fm_capable(self) == DDI_FM_NOT_CAPABLE)) {
1027 1028 /*
1028 1029 * We are capable of something, pass our capabilities up the
1029 1030 * tree, but use a local variable so our parent can't limit
1030 1031 * our capabilities (we don't want our parent to clear
1031 1032 * DDI_FM_EREPORT_CAPABLE).
1032 1033 *
1033 1034 * NOTE: iblock cookies are not important because scsi HBAs
1034 1035 * always interrupt below LOCK_LEVEL.
1035 1036 */
1036 1037 capable = tran->tran_fm_capable;
1037 1038 ddi_fm_init(self, &capable, NULL);
1038 1039
1039 1040 /*
1040 1041 * Set SCSI_HBA_SCSA_FM bit to mark us as using the common
1041 1042 * minimal SCSA fm implementation - we called ddi_fm_init(),
1042 1043 * so we are responsible for calling ddi_fm_fini() in
1043 1044 * scsi_hba_detach().
1044 1045 *
1045 1046 * NOTE: if ddi_fm_init fails to establish handle, SKIP cleanup.
1046 1047 */
1047 1048 if (DEVI(self)->devi_fmhdl)
1048 1049 tran->tran_hba_flags |= SCSI_HBA_SCSA_FM;
1049 1050 }
1050 1051
1051 1052 /* If SCSA responsible for for minor nodes, create :devctl minor. */
1052 1053 scsa_minor = (ddi_get_driver(self)->devo_cb_ops->cb_open ==
1053 1054 scsi_hba_open) ? 1 : 0;
1054 1055 if (scsa_minor && ((ddi_create_minor_node(self, "devctl", S_IFCHR,
1055 1056 INST2DEVCTL(ddi_get_instance(self)), DDI_NT_SCSI_NEXUS, 0) !=
1056 1057 DDI_SUCCESS))) {
1057 1058 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
1058 1059 "can't create :devctl minor node"));
1059 1060 goto fail;
1060 1061 }
1061 1062
1062 1063 return (DDI_SUCCESS);
1063 1064
1064 1065 fail: scsa_nexus_teardown(self, tran);
1065 1066 return (DDI_FAILURE);
1066 1067 }
1067 1068
1068 1069 /*
1069 1070 * Common tran teardown code: used by iport_postdetach_tran_scsi_device() on a
1070 1071 * SCSA HBA iport node and (possibly) by scsi_hba_detach() on SCSA HBA node
1071 1072 * (and for failure cleanup). Undo scsa_tran_setup in reverse order.
1072 1073 *
1073 1074 * NOTE: Since we are in the Solaris IO framework, we can depend on
1074 1075 * undocumented cleanup operations performed by other parts of the framework:
1075 1076 * like detach_node() calling ddi_prop_remove_all() and
1076 1077 * ddi_remove_minor_node(,NULL).
1077 1078 */
1078 1079 static void
1079 1080 scsa_tran_teardown(dev_info_t *self, scsi_hba_tran_t *tran)
1080 1081 {
1081 1082 tran->tran_iport_dip = NULL;
1082 1083
1083 1084 /* Teardown pHCI registration */
1084 1085 if (tran->tran_hba_flags & SCSI_HBA_SCSA_PHCI) {
1085 1086 (void) mdi_phci_unregister(self, 0);
1086 1087 tran->tran_hba_flags &= ~SCSI_HBA_SCSA_PHCI;
1087 1088 }
1088 1089 }
1089 1090
1090 1091 /*
1091 1092 * Common tran setup code: used by iport_preattach_tran_scsi_device() on a
1092 1093 * SCSA HBA iport node and (possibly) by scsi_hba_attach_setup() on SCSA HBA
1093 1094 * node.
1094 1095 */
1095 1096 static int
1096 1097 scsa_tran_setup(dev_info_t *self, scsi_hba_tran_t *tran)
1097 1098 {
1098 1099 int scsa_minor;
1099 1100 int id;
1100 1101 char *scsi_binding_set;
1101 1102 static const char *interconnect[] = INTERCONNECT_TYPE_ASCII;
1102 1103
1103 1104 SCSI_HBA_LOG((_LOG_TRACE, self, NULL, __func__));
1104 1105
1105 1106 /* If SCSA responsible for for minor nodes, create ":scsi" */
1106 1107 scsa_minor = (ddi_get_driver(self)->devo_cb_ops->cb_open ==
1107 1108 scsi_hba_open) ? 1 : 0;
1108 1109 if (scsa_minor && (ddi_create_minor_node(self, "scsi", S_IFCHR,
1109 1110 INST2SCSI(ddi_get_instance(self)),
1110 1111 DDI_NT_SCSI_ATTACHMENT_POINT, 0) != DDI_SUCCESS)) {
1111 1112 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
1112 1113 "can't create :scsi minor node"));
1113 1114 goto fail;
1114 1115 }
1115 1116
1116 1117 /*
1117 1118 * If the property does not already exist on self then see if we can
1118 1119 * pull it from further up the tree and define it on self. If the
1119 1120 * property does not exist above (including options.conf) then use the
1120 1121 * default value specified (global variable). We pull things down from
1121 1122 * above for faster "DDI_PROP_NOTPROM | DDI_PROP_DONTPASS" runtime
1122 1123 * access.
1123 1124 *
1124 1125 * Future: Should we avoid creating properties when value == global?
1125 1126 */
1126 1127 #define CONFIG_INT_PROP(s, p, dv) { \
1127 1128 if ((ddi_prop_exists(DDI_DEV_T_ANY, s, \
1128 1129 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, p) == 0) && \
1129 1130 (ndi_prop_update_int(DDI_DEV_T_NONE, s, p, \
1130 1131 ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(s), \
1131 1132 DDI_PROP_NOTPROM, p, dv)) != DDI_PROP_SUCCESS)) \
1132 1133 SCSI_HBA_LOG((_LOG(WARN), NULL, s, \
1133 1134 "can't create property '%s'", p)); \
1134 1135 }
1135 1136
1136 1137 /* Decorate with scsi configuration properties */
1137 1138 CONFIG_INT_PROP(self, "scsi-enumeration", scsi_enumeration);
1138 1139 CONFIG_INT_PROP(self, "scsi-options", scsi_options);
1139 1140 CONFIG_INT_PROP(self, "scsi-reset-delay", scsi_reset_delay);
1140 1141 CONFIG_INT_PROP(self, "scsi-watchdog-tick", scsi_watchdog_tick);
1141 1142 CONFIG_INT_PROP(self, "scsi-selection-timeout", scsi_selection_timeout);
1142 1143 CONFIG_INT_PROP(self, "scsi-tag-age-limit", scsi_tag_age_limit);
1143 1144
1144 1145 /*
1145 1146 * Pull down the scsi-initiator-id from further up the tree, or as
1146 1147 * defined by OBP. Place on node for faster access. NOTE: there is
1147 1148 * some confusion about what the name of the property should be.
1148 1149 */
1149 1150 id = ddi_prop_get_int(DDI_DEV_T_ANY, self, 0, "initiator-id", -1);
1150 1151 if (id == -1)
1151 1152 id = ddi_prop_get_int(DDI_DEV_T_ANY, self, 0,
1152 1153 "scsi-initiator-id", -1);
1153 1154 if (id != -1)
1154 1155 CONFIG_INT_PROP(self, "scsi-initiator-id", id);
1155 1156
1156 1157 /*
1157 1158 * If we are responsible for tran allocation, establish
1158 1159 * 'initiator-interconnect-type'.
1159 1160 */
1160 1161 if ((tran->tran_hba_flags & SCSI_HBA_SCSA_TA) &&
1161 1162 (tran->tran_interconnect_type > 0) &&
1162 1163 (tran->tran_interconnect_type < INTERCONNECT_MAX)) {
1163 1164 if (ndi_prop_update_string(DDI_DEV_T_NONE, self,
1164 1165 "initiator-interconnect-type",
1165 1166 (char *)interconnect[tran->tran_interconnect_type])
1166 1167 != DDI_PROP_SUCCESS) {
1167 1168 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
1168 1169 "failed to establish "
1169 1170 "'initiator-interconnect-type'"));
1170 1171 goto fail;
1171 1172 }
1172 1173 }
1173 1174
1174 1175 /*
1175 1176 * The 'scsi-binding-set' property can be defined in driver.conf
1176 1177 * files of legacy drivers on an as-needed basis. If 'scsi-binding-set'
1177 1178 * is not driver.conf defined, and the HBA is not implementing its own
1178 1179 * private bus_config, we define scsi-binding-set to the default
1179 1180 * 'spi' legacy value.
1180 1181 *
1181 1182 * NOTE: This default 'spi' value will be deleted if an HBA driver
1182 1183 * ends up using the scsi_hba_tgtmap_create() enumeration services.
1183 1184 *
1184 1185 * NOTE: If we were ever to decide to derive 'scsi-binding-set' from
1185 1186 * the IEEE-1275 'device_type' property then this is where that code
1186 1187 * should go - there is not enough consistency in 'device_type' to do
1187 1188 * this correctly at this point in time.
1188 1189 */
1189 1190 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, self,
1190 1191 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-binding-set",
1191 1192 &scsi_binding_set) == DDI_PROP_SUCCESS) {
1192 1193 SCSI_HBA_LOG((_LOG(2), NULL, self,
1193 1194 "external 'scsi-binding-set' \"%s\"", scsi_binding_set));
1194 1195 ddi_prop_free(scsi_binding_set);
1195 1196 } else if (scsi_binding_set_spi &&
1196 1197 ((tran->tran_bus_config == NULL) ||
1197 1198 (tran->tran_bus_config == scsi_hba_bus_config_spi))) {
1198 1199 if (ndi_prop_update_string(DDI_DEV_T_NONE, self,
1199 1200 "scsi-binding-set", scsi_binding_set_spi) !=
1200 1201 DDI_PROP_SUCCESS) {
1201 1202 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
1202 1203 "failed to establish 'scsi_binding_set' default"));
1203 1204 goto fail;
1204 1205 }
1205 1206 SCSI_HBA_LOG((_LOG(2), NULL, self,
1206 1207 "default 'scsi-binding-set' \"%s\"", scsi_binding_set_spi));
1207 1208 } else
1208 1209 SCSI_HBA_LOG((_LOG(2), NULL, self,
1209 1210 "no 'scsi-binding-set'"));
1210 1211
1211 1212 /*
1212 1213 * If SCSI_HBA_TRAN_PHCI is set, take care of pHCI registration of the
1213 1214 * initiator.
1214 1215 */
1215 1216 if ((tran->tran_hba_flags & SCSI_HBA_TRAN_PHCI) &&
1216 1217 (mdi_phci_register(MDI_HCI_CLASS_SCSI, self, 0) == MDI_SUCCESS))
1217 1218 tran->tran_hba_flags |= SCSI_HBA_SCSA_PHCI;
1218 1219
1219 1220 /* NOTE: tran_hba_dip is for DMA operation at the HBA node level */
1220 1221 tran->tran_iport_dip = self; /* for iport association */
1221 1222 return (DDI_SUCCESS);
1222 1223
1223 1224 fail: scsa_tran_teardown(self, tran);
1224 1225 return (DDI_FAILURE);
1225 1226 }
1226 1227
1227 1228 /*
1228 1229 * Called by a SCSA HBA driver to attach an instance of the driver to
1229 1230 * SCSA HBA node enumerated by PCI.
1230 1231 */
1231 1232 int
1232 1233 scsi_hba_attach_setup(
1233 1234 dev_info_t *self,
1234 1235 ddi_dma_attr_t *hba_dma_attr,
1235 1236 scsi_hba_tran_t *tran,
1236 1237 int flags)
1237 1238 {
1238 1239 int len;
1239 1240 char cache_name[96];
1240 1241
1241 1242 SCSI_HBA_LOG((_LOG_TRACE, self, NULL, __func__));
1242 1243
1243 1244 /*
1244 1245 * Verify that we are a driver so other code does not need to
1245 1246 * check for NULL ddi_get_driver() result.
1246 1247 */
1247 1248 if (ddi_get_driver(self) == NULL)
1248 1249 return (DDI_FAILURE);
1249 1250
1250 1251 /*
1251 1252 * Verify that we are called on a SCSA HBA node (function enumerated
1252 1253 * by PCI), not on an iport node.
1253 1254 */
1254 1255 ASSERT(scsi_hba_iport_unit_address(self) == NULL);
1255 1256 if (scsi_hba_iport_unit_address(self))
1256 1257 return (DDI_FAILURE); /* self can't be an iport */
1257 1258
1258 1259 /* Caller must provide the tran. */
1259 1260 ASSERT(tran);
1260 1261 if (tran == NULL)
1261 1262 return (DDI_FAILURE);
1262 1263
1263 1264 /*
1264 1265 * Verify correct scsi_hba_tran_t form:
1265 1266 *
1266 1267 * o Both or none of tran_get_name/tran_get_addr.
1267 1268 * NOTE: Older SCSA HBA drivers for SCSI transports with addressing
1268 1269 * that did not fit the SPI "struct scsi_address" model were required
1269 1270 * to implement tran_get_name and tran_get_addr. This is no longer
1270 1271 * true - modern transport drivers should now use common SCSA
1271 1272 * enumeration services. The SCSA enumeration code will represent
1272 1273 * the unit-address using well-known address properties
1273 1274 * (SCSI_ADDR_PROP_TARGET_PORT, SCSI_ADDR_PROP_LUN64) during
1274 1275 * devinfo/pathinfo node creation. The HBA driver can obtain values
1275 1276 * using scsi_device_prop_lookup_*() from its tran_tgt_init(9E).
1276 1277 *
1277 1278 */
1278 1279 if ((tran->tran_get_name == NULL) ^ (tran->tran_get_bus_addr == NULL)) {
1279 1280 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
1280 1281 "should support both or neither: "
1281 1282 "tran_get_name, tran_get_bus_addr"));
1282 1283 return (DDI_FAILURE);
1283 1284 }
1284 1285
1285 1286 /*
1286 1287 * Establish the devinfo context of this tran structure, preserving
1287 1288 * knowledge of how the tran was allocated.
1288 1289 */
1289 1290 tran->tran_hba_dip = self; /* for DMA */
1290 1291 tran->tran_hba_flags = (flags & ~SCSI_HBA_SCSA_TA) |
1291 1292 (tran->tran_hba_flags & SCSI_HBA_SCSA_TA);
1292 1293
1293 1294 /* Establish flavor of transport (and ddi_get_driver_private()) */
1294 1295 ndi_flavorv_set(self, SCSA_FLAVOR_SCSI_DEVICE, tran);
1295 1296
1296 1297 /*
1297 1298 * Note: We only need dma_attr_minxfer and dma_attr_burstsizes
1298 1299 * from the DMA attributes. scsi_hba_attach(9f) only guarantees
1299 1300 * that these two fields are initialized properly. If this
1300 1301 * changes, be sure to revisit the implementation of
1301 1302 * scsi_hba_attach(9F).
1302 1303 */
1303 1304 (void) memcpy(&tran->tran_dma_attr, hba_dma_attr,
1304 1305 sizeof (ddi_dma_attr_t));
1305 1306
1306 1307 /* Create tran_setup_pkt(9E) kmem_cache. */
1307 1308 if (tran->tran_setup_pkt) {
1308 1309 ASSERT(tran->tran_init_pkt == NULL);
1309 1310 ASSERT(tran->tran_destroy_pkt == NULL);
1310 1311 if (tran->tran_init_pkt || tran->tran_destroy_pkt)
1311 1312 goto fail;
1312 1313
1313 1314 tran->tran_init_pkt = scsi_init_cache_pkt;
1314 1315 tran->tran_destroy_pkt = scsi_free_cache_pkt;
1315 1316 tran->tran_sync_pkt = scsi_sync_cache_pkt;
1316 1317 tran->tran_dmafree = scsi_cache_dmafree;
1317 1318
1318 1319 len = sizeof (struct scsi_pkt_cache_wrapper);
1319 1320 len += ROUNDUP(tran->tran_hba_len);
1320 1321 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CDB)
1321 1322 len += ROUNDUP(DEFAULT_CDBLEN);
1322 1323 if (tran->tran_hba_flags & SCSI_HBA_TRAN_SCB)
1323 1324 len += ROUNDUP(DEFAULT_SCBLEN);
1324 1325
1325 1326 (void) snprintf(cache_name, sizeof (cache_name),
1326 1327 "pkt_cache_%s_%d", ddi_driver_name(self),
1327 1328 ddi_get_instance(self));
1328 1329
1329 1330 tran->tran_pkt_cache_ptr = kmem_cache_create(
1330 1331 cache_name, len, 8, scsi_hba_pkt_constructor,
1331 1332 scsi_hba_pkt_destructor, NULL, tran, NULL, 0);
1332 1333 }
1333 1334
1334 1335 /* Perform node setup independent of initiator role */
1335 1336 if (scsa_nexus_setup(self, tran) != DDI_SUCCESS)
1336 1337 goto fail;
1337 1338
1338 1339 /*
1339 1340 * The SCSI_HBA_HBA flag is passed to scsi_hba_attach_setup when the
1340 1341 * HBA driver knows that *all* children of the SCSA HBA node will be
1341 1342 * 'iports'. If the SCSA HBA node can have iport children and also
1342 1343 * function as an initiator for xxx_device children then it should
1343 1344 * not specify SCSI_HBA_HBA in its scsi_hba_attach_setup call. An
1344 1345 * HBA driver that does not manage iports should not set SCSA_HBA_HBA.
1345 1346 */
1346 1347 if (tran->tran_hba_flags & SCSI_HBA_HBA) {
1347 1348 /*
1348 1349 * Set the 'ddi-config-driver-node' property on the nexus
1349 1350 * node that notify attach_driver_nodes() to configure all
1350 1351 * immediate children so that nodes which bind to the
1351 1352 * same driver as parent are able to be added into per-driver
1352 1353 * list.
1353 1354 */
1354 1355 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
1355 1356 self, "ddi-config-driver-node") != DDI_PROP_SUCCESS)
1356 1357 goto fail;
1357 1358 } else {
1358 1359 if (scsa_tran_setup(self, tran) != DDI_SUCCESS)
1359 1360 goto fail;
1360 1361 }
1361 1362
1362 1363 return (DDI_SUCCESS);
1363 1364
1364 1365 fail: (void) scsi_hba_detach(self);
1365 1366 return (DDI_FAILURE);
1366 1367 }
1367 1368
1368 1369 /*
1369 1370 * Called by an HBA to detach an instance of the driver. This may be called
1370 1371 * for SCSA HBA nodes and for SCSA iport nodes.
1371 1372 */
1372 1373 int
1373 1374 scsi_hba_detach(dev_info_t *self)
1374 1375 {
1375 1376 scsi_hba_tran_t *tran;
1376 1377
1377 1378 ASSERT(scsi_hba_iport_unit_address(self) == NULL);
1378 1379 if (scsi_hba_iport_unit_address(self))
1379 1380 return (DDI_FAILURE); /* self can't be an iport */
1380 1381
1381 1382 /* Check all error return conditions upfront */
1382 1383 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
1383 1384 ASSERT(tran);
1384 1385 if (tran == NULL)
1385 1386 return (DDI_FAILURE);
1386 1387
1387 1388 ASSERT(tran->tran_open_flag == 0);
1388 1389 if (tran->tran_open_flag)
1389 1390 return (DDI_FAILURE);
1390 1391
1391 1392 if (!(tran->tran_hba_flags & SCSI_HBA_HBA))
1392 1393 scsa_tran_teardown(self, tran);
1393 1394 scsa_nexus_teardown(self, tran);
1394 1395
1395 1396 /* Teardown tran_setup_pkt(9E) kmem_cache. */
1396 1397 if (tran->tran_pkt_cache_ptr) {
1397 1398 kmem_cache_destroy(tran->tran_pkt_cache_ptr);
1398 1399 tran->tran_pkt_cache_ptr = NULL;
1399 1400 }
1400 1401
1401 1402 (void) memset(&tran->tran_dma_attr, 0, sizeof (ddi_dma_attr_t));
1402 1403
1403 1404 /* Teardown flavor of transport (and ddi_get_driver_private()) */
1404 1405 ndi_flavorv_set(self, SCSA_FLAVOR_SCSI_DEVICE, NULL);
1405 1406
1406 1407 tran->tran_hba_dip = NULL;
1407 1408
1408 1409 return (DDI_SUCCESS);
1409 1410 }
1410 1411
1411 1412
1412 1413 /*
1413 1414 * Called by an HBA from _fini()
1414 1415 */
1415 1416 void
1416 1417 scsi_hba_fini(struct modlinkage *modlp)
1417 1418 {
1418 1419 struct dev_ops *hba_dev_ops;
1419 1420
1420 1421 SCSI_HBA_LOG((_LOG_TRACE, NULL, NULL, __func__));
1421 1422
1422 1423 /* Get the devops structure of this module and clear bus_ops vector. */
1423 1424 hba_dev_ops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
1424 1425
1425 1426 if (hba_dev_ops->devo_cb_ops == &scsi_hba_cbops)
1426 1427 hba_dev_ops->devo_cb_ops = NULL;
1427 1428
1428 1429 if (hba_dev_ops->devo_getinfo == scsi_hba_info)
1429 1430 hba_dev_ops->devo_getinfo = NULL;
1430 1431
1431 1432 hba_dev_ops->devo_bus_ops = (struct bus_ops *)NULL;
1432 1433 }
1433 1434
1434 1435 /*
1435 1436 * SAS specific functions
1436 1437 */
1437 1438 smp_hba_tran_t *
1438 1439 smp_hba_tran_alloc(dev_info_t *self)
1439 1440 {
1440 1441 /* allocate SCSA flavors for self */
1441 1442 ndi_flavorv_alloc(self, SCSA_NFLAVORS);
1442 1443 return (kmem_zalloc(sizeof (smp_hba_tran_t), KM_SLEEP));
1443 1444 }
1444 1445
1445 1446 void
1446 1447 smp_hba_tran_free(smp_hba_tran_t *tran)
1447 1448 {
1448 1449 kmem_free(tran, sizeof (smp_hba_tran_t));
1449 1450 }
1450 1451
1451 1452 int
1452 1453 smp_hba_attach_setup(
1453 1454 dev_info_t *self,
1454 1455 smp_hba_tran_t *tran)
1455 1456 {
1456 1457 ASSERT(scsi_hba_iport_unit_address(self) == NULL);
1457 1458 if (scsi_hba_iport_unit_address(self))
1458 1459 return (DDI_FAILURE); /* self can't be an iport */
1459 1460
1460 1461 /*
1461 1462 * The owner of the this devinfo_t was responsible
1462 1463 * for informing the framework already about
1463 1464 * additional flavors.
1464 1465 */
1465 1466 ndi_flavorv_set(self, SCSA_FLAVOR_SMP, tran);
1466 1467 return (DDI_SUCCESS);
1467 1468 }
1468 1469
1469 1470 int
1470 1471 smp_hba_detach(dev_info_t *self)
1471 1472 {
1472 1473 ASSERT(scsi_hba_iport_unit_address(self) == NULL);
1473 1474 if (scsi_hba_iport_unit_address(self))
1474 1475 return (DDI_FAILURE); /* self can't be an iport */
1475 1476
1476 1477 ndi_flavorv_set(self, SCSA_FLAVOR_SMP, NULL);
1477 1478 return (DDI_SUCCESS);
1478 1479 }
1479 1480
1480 1481 /*
1481 1482 * SMP child flavored functions
1482 1483 */
1483 1484 static int
1484 1485 smp_busctl_ua(dev_info_t *child, char *addr, int maxlen)
1485 1486 {
1486 1487 char *tport;
1487 1488 char *wwn;
1488 1489
1489 1490 /* limit ndi_devi_findchild_by_callback to expected flavor */
1490 1491 if (ndi_flavor_get(child) != SCSA_FLAVOR_SMP)
1491 1492 return (DDI_FAILURE);
1492 1493
1493 1494 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
1494 1495 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1495 1496 SCSI_ADDR_PROP_TARGET_PORT, &tport) == DDI_SUCCESS) {
1496 1497 (void) snprintf(addr, maxlen, "%s", tport);
1497 1498 ddi_prop_free(tport);
1498 1499 return (DDI_SUCCESS);
1499 1500 }
1500 1501
1501 1502 /*
1502 1503 * NOTE: the following code should be deleted when mpt is changed to
1503 1504 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1504 1505 */
1505 1506 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
1506 1507 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1507 1508 SMP_WWN, &wwn) == DDI_SUCCESS) {
1508 1509 (void) snprintf(addr, maxlen, "w%s", wwn);
1509 1510 ddi_prop_free(wwn);
1510 1511 return (DDI_SUCCESS);
1511 1512 }
1512 1513 return (DDI_FAILURE);
1513 1514 }
1514 1515
1515 1516 static int
1516 1517 smp_busctl_reportdev(dev_info_t *child)
1517 1518 {
1518 1519 dev_info_t *self = ddi_get_parent(child);
1519 1520 char *tport;
1520 1521 char *wwn;
1521 1522
1522 1523 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
1523 1524 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1524 1525 SCSI_ADDR_PROP_TARGET_PORT, &tport) == DDI_SUCCESS) {
1525 1526 SCSI_HBA_LOG((_LOG_NF(CONT), "?%s%d at %s%d: target-port %s",
1526 1527 ddi_driver_name(child), ddi_get_instance(child),
1527 1528 ddi_driver_name(self), ddi_get_instance(self), tport));
1528 1529 ddi_prop_free(tport);
1529 1530 return (DDI_SUCCESS);
1530 1531 }
1531 1532
1532 1533 /*
1533 1534 * NOTE: the following code should be deleted when mpt is changed to
1534 1535 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1535 1536 */
1536 1537 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
1537 1538 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1538 1539 SMP_WWN, &wwn) == DDI_SUCCESS) {
1539 1540 SCSI_HBA_LOG((_LOG_NF(CONT), "?%s%d at %s%d: wwn %s",
1540 1541 ddi_driver_name(child), ddi_get_instance(child),
1541 1542 ddi_driver_name(self), ddi_get_instance(self), wwn));
1542 1543 ddi_prop_free(wwn);
1543 1544 return (DDI_SUCCESS);
1544 1545 }
1545 1546 return (DDI_FAILURE);
1546 1547 }
1547 1548
1548 1549 static int
1549 1550 smp_busctl_initchild(dev_info_t *child)
1550 1551 {
1551 1552 dev_info_t *self = ddi_get_parent(child);
1552 1553 smp_hba_tran_t *tran;
1553 1554 dev_info_t *dup;
1554 1555 char addr[SCSI_MAXNAMELEN];
1555 1556 struct smp_device *smp_sd;
1556 1557 uint64_t wwn;
1557 1558
1558 1559 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SMP);
1559 1560 ASSERT(tran);
1560 1561 if (tran == NULL)
1561 1562 return (DDI_FAILURE);
1562 1563
1563 1564 if (smp_busctl_ua(child, addr, sizeof (addr)) != DDI_SUCCESS)
1564 1565 return (DDI_NOT_WELL_FORMED);
1565 1566 if (scsi_wwnstr_to_wwn(addr, &wwn))
1566 1567 return (DDI_NOT_WELL_FORMED);
1567 1568
1568 1569 /* Prevent duplicate nodes. */
1569 1570 dup = ndi_devi_findchild_by_callback(self, ddi_node_name(child), addr,
1570 1571 smp_busctl_ua);
1571 1572 if (dup) {
1572 1573 ASSERT(ndi_flavor_get(dup) == SCSA_FLAVOR_SMP);
1573 1574 if (ndi_flavor_get(dup) != SCSA_FLAVOR_SMP) {
1574 1575 SCSI_HBA_LOG((_LOG(1), NULL, child,
1575 1576 "init failed: %s@%s: not SMP flavored",
1576 1577 ddi_node_name(child), addr));
1577 1578 return (DDI_FAILURE);
1578 1579 }
1579 1580 if (dup != child) {
1580 1581 SCSI_HBA_LOG((_LOG(4), NULL, child,
1581 1582 "init failed: %s@%s: detected duplicate %p",
1582 1583 ddi_node_name(child), addr, (void *)dup));
1583 1584 return (DDI_FAILURE);
1584 1585 }
1585 1586 }
1586 1587
1587 1588
1588 1589 /* set the node @addr string */
1589 1590 ddi_set_name_addr(child, addr);
1590 1591
1591 1592 /* Allocate and initialize smp_device. */
1592 1593 smp_sd = kmem_zalloc(sizeof (struct smp_device), KM_SLEEP);
1593 1594 smp_sd->smp_sd_dev = child;
1594 1595 smp_sd->smp_sd_address.smp_a_hba_tran = tran;
1595 1596 bcopy(&wwn, smp_sd->smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
1596 1597
1597 1598 ddi_set_driver_private(child, smp_sd);
1598 1599
1599 1600 if (tran->smp_tran_init && ((*tran->smp_tran_init)(self, child,
1600 1601 tran, smp_sd) != DDI_SUCCESS)) {
1601 1602 kmem_free(smp_sd, sizeof (struct smp_device));
1602 1603 scsi_enumeration_failed(child, -1, NULL, "smp_tran_init");
1603 1604 ddi_set_driver_private(child, NULL);
1604 1605 ddi_set_name_addr(child, NULL);
1605 1606 return (DDI_FAILURE);
1606 1607 }
1607 1608
1608 1609 return (DDI_SUCCESS);
1609 1610 }
1610 1611
1611 1612 /*ARGSUSED*/
1612 1613 static int
1613 1614 smp_busctl_uninitchild(dev_info_t *child)
1614 1615 {
1615 1616 dev_info_t *self = ddi_get_parent(child);
1616 1617 struct smp_device *smp_sd = ddi_get_driver_private(child);
1617 1618 smp_hba_tran_t *tran;
1618 1619
1619 1620 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SMP);
1620 1621 ASSERT(smp_sd && tran);
1621 1622 if ((smp_sd == NULL) || (tran == NULL))
1622 1623 return (DDI_FAILURE);
1623 1624
1624 1625 if (tran->smp_tran_free)
1625 1626 (*tran->smp_tran_free) (self, child, tran, smp_sd);
1626 1627
1627 1628 kmem_free(smp_sd, sizeof (*smp_sd));
1628 1629 ddi_set_driver_private(child, NULL);
1629 1630 ddi_set_name_addr(child, NULL);
1630 1631 return (DDI_SUCCESS);
1631 1632 }
1632 1633
1633 1634 /* Find an "smp" child at the specified address. */
1634 1635 static dev_info_t *
1635 1636 smp_findchild(dev_info_t *self, char *addr)
1636 1637 {
1637 1638 dev_info_t *child;
1638 1639
1639 1640 /* Search "smp" devinfo child at specified address. */
1640 1641 ASSERT(self && DEVI_BUSY_OWNED(self) && addr);
1641 1642 for (child = ddi_get_child(self); child;
1642 1643 child = ddi_get_next_sibling(child)) {
1643 1644 /* skip non-"smp" nodes */
1644 1645 if (ndi_flavor_get(child) != SCSA_FLAVOR_SMP)
1645 1646 continue;
1646 1647
1647 1648 /* Attempt initchild to establish unit-address */
1648 1649 if (i_ddi_node_state(child) < DS_INITIALIZED)
1649 1650 (void) ddi_initchild(self, child);
1650 1651
1651 1652 /* Verify state and non-NULL unit-address. */
1652 1653 if ((i_ddi_node_state(child) < DS_INITIALIZED) ||
1653 1654 (ddi_get_name_addr(child) == NULL))
1654 1655 continue;
1655 1656
1656 1657 /* Return "smp" child if unit-address matches. */
1657 1658 if (strcmp(ddi_get_name_addr(child), addr) == 0)
1658 1659 return (child);
1659 1660 }
1660 1661 return (NULL);
1661 1662 }
1662 1663
1663 1664 /*
1664 1665 * Search for "smp" child of self at the specified address. If found, online
1665 1666 * and return with a hold. Unlike general SCSI configuration, we can assume
1666 1667 * the the device is actually there when we are called (i.e., device is
1667 1668 * created by hotplug, not by bus_config).
1668 1669 */
1669 1670 int
1670 1671 smp_hba_bus_config(dev_info_t *self, char *addr, dev_info_t **childp)
1671 1672 {
1672 1673 dev_info_t *child;
1673 1674 int circ;
1674 1675
1675 1676 ASSERT(self && addr && childp);
1676 1677 *childp = NULL;
1677 1678
1678 1679 /* Search for "smp" child. */
1679 1680 scsi_hba_devi_enter(self, &circ);
1680 1681 if ((child = smp_findchild(self, addr)) == NULL) {
1681 1682 scsi_hba_devi_exit(self, circ);
1682 1683 return (NDI_FAILURE);
1683 1684 }
1684 1685
1685 1686 /* Attempt online. */
1686 1687 if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
1687 1688 scsi_hba_devi_exit(self, circ);
1688 1689 return (NDI_FAILURE);
1689 1690 }
1690 1691
1691 1692 /* On success, return with active hold. */
1692 1693 ndi_hold_devi(child);
1693 1694 scsi_hba_devi_exit(self, circ);
1694 1695 *childp = child;
1695 1696 return (NDI_SUCCESS);
1696 1697 }
1697 1698
1698 1699
1699 1700
1700 1701 /* Create "smp" child devinfo node at specified unit-address. */
1701 1702 int
1702 1703 smp_hba_bus_config_taddr(dev_info_t *self, char *addr)
1703 1704 {
1704 1705 dev_info_t *child;
1705 1706 int circ;
1706 1707
1707 1708 /*
1708 1709 * NOTE: If we ever uses a generic node name (.vs. a driver name)
1709 1710 * or define a 'compatible' property, this code will need to use
1710 1711 * a 'probe' node (ala scsi_device support) to obtain identity
1711 1712 * information from the device.
1712 1713 */
1713 1714
1714 1715 /* Search for "smp" child. */
1715 1716 scsi_hba_devi_enter(self, &circ);
1716 1717 child = smp_findchild(self, addr);
1717 1718 if (child) {
1718 1719 /* Child exists, note if this was a new reinsert. */
1719 1720 if (ndi_devi_device_insert(child))
1720 1721 SCSI_HBA_LOG((_LOGCFG, self, NULL,
1721 1722 "devinfo smp@%s device_reinsert", addr));
1722 1723
1723 1724 scsi_hba_devi_exit(self, circ);
1724 1725 return (NDI_SUCCESS);
1725 1726 }
1726 1727
1727 1728 /* Allocate "smp" child devinfo node and establish flavor of child. */
1728 1729 ndi_devi_alloc_sleep(self, "smp", DEVI_SID_HP_NODEID, &child);
1729 1730 ASSERT(child);
1730 1731 ndi_flavor_set(child, SCSA_FLAVOR_SMP);
1731 1732
1732 1733 /* Add unit-address property to child. */
1733 1734 if (ndi_prop_update_string(DDI_DEV_T_NONE, child,
1734 1735 SCSI_ADDR_PROP_TARGET_PORT, addr) != DDI_PROP_SUCCESS) {
1735 1736 (void) ndi_devi_free(child);
1736 1737 scsi_hba_devi_exit(self, circ);
1737 1738 return (NDI_FAILURE);
1738 1739 }
1739 1740
1740 1741 /* Attempt to online the new "smp" node. */
1741 1742 (void) ndi_devi_online(child, 0);
1742 1743
1743 1744 scsi_hba_devi_exit(self, circ);
1744 1745 return (NDI_SUCCESS);
1745 1746 }
1746 1747
1747 1748 /*
1748 1749 * Wrapper to scsi_ua_get which takes a devinfo argument instead of a
1749 1750 * scsi_device structure.
1750 1751 */
1751 1752 static int
1752 1753 scsi_busctl_ua(dev_info_t *child, char *addr, int maxlen)
1753 1754 {
1754 1755 struct scsi_device *sd;
1755 1756
1756 1757 /* limit ndi_devi_findchild_by_callback to expected flavor */
1757 1758 if (ndi_flavor_get(child) != SCSA_FLAVOR_SCSI_DEVICE)
1758 1759 return (DDI_FAILURE);
1759 1760
1760 1761 /* nodes are named by tran_get_name or default "tgt,lun" */
1761 1762 sd = ddi_get_driver_private(child);
1762 1763 if (sd && (scsi_ua_get(sd, addr, maxlen) == 1))
1763 1764 return (DDI_SUCCESS);
1764 1765
1765 1766 return (DDI_FAILURE);
1766 1767 }
1767 1768
1768 1769 static int
1769 1770 scsi_busctl_reportdev(dev_info_t *child)
1770 1771 {
1771 1772 dev_info_t *self = ddi_get_parent(child);
1772 1773 struct scsi_device *sd = ddi_get_driver_private(child);
1773 1774 scsi_hba_tran_t *tran;
1774 1775 char ua[SCSI_MAXNAMELEN];
1775 1776 char ra[SCSI_MAXNAMELEN];
1776 1777
1777 1778 SCSI_HBA_LOG((_LOG_TRACE, NULL, child, __func__));
1778 1779
1779 1780 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
1780 1781 ASSERT(tran && sd);
1781 1782 if ((tran == NULL) || (sd == NULL))
1782 1783 return (DDI_FAILURE);
1783 1784
1784 1785 /* get the unit_address and bus_addr information */
1785 1786 if ((scsi_ua_get(sd, ua, sizeof (ua)) == 0) ||
1786 1787 (scsi_ua_get_reportdev(sd, ra, sizeof (ra)) == 0)) {
1787 1788 SCSI_HBA_LOG((_LOG(WARN), NULL, child, "REPORTDEV failure"));
1788 1789 return (DDI_FAILURE);
1789 1790 }
1790 1791
1791 1792 if (tran->tran_get_name == NULL)
1792 1793 SCSI_HBA_LOG((_LOG_NF(CONT), "?%s%d at %s%d: %s",
1793 1794 ddi_driver_name(child), ddi_get_instance(child),
1794 1795 ddi_driver_name(self), ddi_get_instance(self), ra));
1795 1796 else if (*ra)
1796 1797 SCSI_HBA_LOG((_LOG_NF(CONT),
1797 1798 "?%s%d at %s%d: unit-address %s: %s",
1798 1799 ddi_driver_name(child), ddi_get_instance(child),
1799 1800 ddi_driver_name(self), ddi_get_instance(self), ua, ra));
1800 1801 else
1801 1802 SCSI_HBA_LOG((_LOG_NF(CONT),
1802 1803 "?%s%d at %s%d: unit-address %s",
1803 1804 ddi_driver_name(child), ddi_get_instance(child),
1804 1805 ddi_driver_name(self), ddi_get_instance(self), ua));
1805 1806
1806 1807 return (DDI_SUCCESS);
1807 1808 }
1808 1809
1809 1810
1810 1811 /*
1811 1812 * scsi_busctl_initchild is called to initialize the SCSA transport for
1812 1813 * communication with a particular child scsi target device. Successful
1813 1814 * initialization requires properties on the node which describe the address
1814 1815 * of the target device. If the address of the target device can't be
1815 1816 * determined from properties then DDI_NOT_WELL_FORMED is returned. Nodes that
1816 1817 * are DDI_NOT_WELL_FORMED are considered an implementation artifact and
1817 1818 * are hidden from devinfo snapshots by calling ndi_devi_set_hidden().
1818 1819 * The child may be one of the following types of devinfo nodes:
1819 1820 *
1820 1821 * OBP node:
1821 1822 * OBP does not enumerate target devices attached a SCSI bus. These
1822 1823 * template/stub/wild-card nodes are a legacy artifact for support of old
1823 1824 * driver loading methods. Since they have no properties,
1824 1825 * DDI_NOT_WELL_FORMED will be returned.
1825 1826 *
1826 1827 * SID node:
1827 1828 * The node may be either a:
1828 1829 * o probe/barrier SID node
1829 1830 * o a dynamic SID target node
1830 1831 *
1831 1832 * driver.conf node: The situation for this nexus is different than most.
1832 1833 * Typically a driver.conf node definition is used to either define a
1833 1834 * new child devinfo node or to further decorate (via merge) a SID
1834 1835 * child with properties. In our case we use the nodes for *both*
1835 1836 * purposes.
1836 1837 *
1837 1838 * In both the SID node and driver.conf node cases we must form the nodes
1838 1839 * "@addr" from the well-known scsi(9P) device unit-address properties on
1839 1840 * the node.
1840 1841 *
1841 1842 * For HBA drivers that implement the deprecated tran_get_name interface,
1842 1843 * "@addr" construction involves having that driver interpret properties via
1843 1844 * scsi_busctl_ua -> scsi_ua_get -> tran_get_name: there is no
1844 1845 * requirement for the property names to be well-known.
1845 1846 *
1846 1847 * NOTE: We don't currently support "merge". When this support is added a
1847 1848 * specific property, like "unit-address", should *always* identify a
1848 1849 * driver.conf node that needs to be merged into a specific SID node. When
1849 1850 * enumeration is enabled, a .conf node without the "unit-address" property
1850 1851 * should be ignored. The best way to establish the "unit-address" property
1851 1852 * would be to have the system assign parent= and unit-address= from an
1852 1853 * instance=# driver.conf entry (by using the instance tree).
1853 1854 */
1854 1855 static int
1855 1856 scsi_busctl_initchild(dev_info_t *child)
1856 1857 {
1857 1858 dev_info_t *self = ddi_get_parent(child);
1858 1859 dev_info_t *dup;
1859 1860 scsi_hba_tran_t *tran;
1860 1861 struct scsi_device *sd;
1861 1862 scsi_hba_tran_t *tran_clone;
1862 1863 char *class;
1863 1864 int tgt;
1864 1865 int lun;
1865 1866 int sfunc;
1866 1867 int err = DDI_FAILURE;
1867 1868 char addr[SCSI_MAXNAMELEN];
1868 1869
1869 1870 ASSERT(DEVI_BUSY_OWNED(self));
1870 1871 SCSI_HBA_LOG((_LOG(4), NULL, child, "init begin"));
1871 1872
1872 1873 /*
1873 1874 * For a driver like fp with multiple upper-layer-protocols
1874 1875 * it is possible for scsi_hba_init in _init to plumb SCSA
1875 1876 * and have the load of fcp (which does scsi_hba_attach_setup)
1876 1877 * to fail. In this case we may get here with a NULL hba.
1877 1878 */
1878 1879 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
1879 1880 if (tran == NULL)
1880 1881 return (DDI_NOT_WELL_FORMED);
1881 1882
1882 1883 /*
1883 1884 * OBP may create template/stub/wild-card nodes for legacy driver
1884 1885 * loading methods. These nodes have no properties, so we lack the
1885 1886 * addressing properties to initchild them. Hide the node and return
1886 1887 * DDI_NOT_WELL_FORMED.
1887 1888 *
1888 1889 * Future: define/use a ndi_devi_has_properties(dip) type interface.
1889 1890 *
1890 1891 * NOTE: It would be nice if we could delete these ill formed nodes by
1891 1892 * implementing a DDI_NOT_WELL_FORMED_DELETE return code. This can't
1892 1893 * be done until leadville debug code removes its dependencies
1893 1894 * on the devinfo still being present after a failed ndi_devi_online.
1894 1895 */
1895 1896 if ((DEVI(child)->devi_hw_prop_ptr == NULL) &&
1896 1897 (DEVI(child)->devi_drv_prop_ptr == NULL) &&
1897 1898 (DEVI(child)->devi_sys_prop_ptr == NULL)) {
1898 1899 SCSI_HBA_LOG((_LOG(4), NULL, child,
1899 1900 "init failed: no properties"));
1900 1901 ndi_devi_set_hidden(child);
1901 1902 return (DDI_NOT_WELL_FORMED);
1902 1903 }
1903 1904
1904 1905 /* get legacy SPI addressing properties */
1905 1906 if ((tgt = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1906 1907 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1907 1908 SCSI_ADDR_PROP_TARGET, -1)) == -1) {
1908 1909 tgt = 0;
1909 1910 /*
1910 1911 * A driver.conf node for merging always has a target= property,
1911 1912 * even if it is just a dummy that does not contain the real
1912 1913 * target address. However drivers that register devids may
1913 1914 * create stub driver.conf nodes without a target= property so
1914 1915 * that pathological devid resolution works. Hide the stub
1915 1916 * node and return DDI_NOT_WELL_FORMED.
1916 1917 */
1917 1918 if (!scsi_hba_dev_is_sid(child)) {
1918 1919 SCSI_HBA_LOG((_LOG(4), NULL, child,
1919 1920 "init failed: stub .conf node"));
1920 1921 ndi_devi_set_hidden(child);
1921 1922 return (DDI_NOT_WELL_FORMED);
1922 1923 }
1923 1924 }
1924 1925 lun = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1925 1926 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, SCSI_ADDR_PROP_LUN, 0);
1926 1927 sfunc = ddi_prop_get_int(DDI_DEV_T_ANY, child,
1927 1928 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, SCSI_ADDR_PROP_SFUNC, -1);
1928 1929
1929 1930 /*
1930 1931 * The scsi_address structure may not specify all the addressing
1931 1932 * information. For an old HBA that doesn't support tran_get_name
1932 1933 * (most pre-SCSI-3 HBAs) the scsi_address structure is still used,
1933 1934 * so the target property must exist and the LUN must be < 256.
1934 1935 */
1935 1936 if ((tran->tran_get_name == NULL) &&
1936 1937 ((tgt >= USHRT_MAX) || (lun >= 256))) {
1937 1938 SCSI_HBA_LOG((_LOG(1), NULL, child,
1938 1939 "init failed: illegal/missing properties"));
1939 1940 ndi_devi_set_hidden(child);
1940 1941 return (DDI_NOT_WELL_FORMED);
1941 1942 }
1942 1943
1943 1944 /*
1944 1945 * We need to initialize a fair amount of our environment to invoke
1945 1946 * tran_get_name (via scsi_busctl_ua and scsi_ua_get) to
1946 1947 * produce the "@addr" name from addressing properties. Allocate and
1947 1948 * initialize scsi device structure.
1948 1949 */
1949 1950 sd = kmem_zalloc(sizeof (struct scsi_device), KM_SLEEP);
1950 1951 mutex_init(&sd->sd_mutex, NULL, MUTEX_DRIVER, NULL);
1951 1952 sd->sd_dev = child;
1952 1953 sd->sd_pathinfo = NULL;
1953 1954 sd->sd_uninit_prevent = 0;
1954 1955 ddi_set_driver_private(child, sd);
1955 1956
1956 1957 if (tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX) {
1957 1958 /*
1958 1959 * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
1959 1960 * scsi_device in the scsi_address structure. This allows an
1960 1961 * HBA driver to find its per-scsi_device private data
1961 1962 * (accessible to the HBA given just the scsi_address by using
1962 1963 * scsi_address_device(9F)/scsi_device_hba_private_get(9F)).
1963 1964 */
1964 1965 sd->sd_address.a.a_sd = sd;
1965 1966 tran_clone = NULL;
1966 1967 } else {
1967 1968 /*
1968 1969 * Initialize the scsi_address so that a SCSI-2 target driver
1969 1970 * talking to a SCSI-2 device on a SCSI-3 bus (spi) continues
1970 1971 * to work. We skew the secondary function value so that we
1971 1972 * can tell from the address structure if we are processing
1972 1973 * a secondary function request.
1973 1974 */
1974 1975 sd->sd_address.a_target = (ushort_t)tgt;
1975 1976 sd->sd_address.a_lun = (uchar_t)lun;
1976 1977 if (sfunc == -1)
1977 1978 sd->sd_address.a_sublun = (uchar_t)0;
1978 1979 else
1979 1980 sd->sd_address.a_sublun = (uchar_t)sfunc + 1;
1980 1981
1981 1982 /*
1982 1983 * NOTE: Don't limit LUNs to scsi_options value because a
1983 1984 * scsi_device discovered via SPI dynamic enumeration might
1984 1985 * still support SCMD_REPORT_LUNS.
1985 1986 */
1986 1987
1987 1988 /*
1988 1989 * Deprecated: Use SCSI_HBA_ADDR_COMPLEX:
1989 1990 * Clone transport structure if requested. Cloning allows
1990 1991 * an HBA to maintain target-specific information if
1991 1992 * necessary, such as target addressing information that
1992 1993 * does not adhere to the scsi_address structure format.
1993 1994 */
1994 1995 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
1995 1996 tran_clone = kmem_alloc(
1996 1997 sizeof (scsi_hba_tran_t), KM_SLEEP);
1997 1998 bcopy((caddr_t)tran,
1998 1999 (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
1999 2000 tran = tran_clone;
2000 2001 tran->tran_sd = sd;
2001 2002 } else {
2002 2003 tran_clone = NULL;
2003 2004 ASSERT(tran->tran_sd == NULL);
2004 2005 }
2005 2006 }
2006 2007
2007 2008 /* establish scsi_address pointer to the HBA's tran structure */
2008 2009 sd->sd_address.a_hba_tran = tran;
2009 2010
2010 2011 /*
2011 2012 * This is a grotty hack that allows direct-access (non-scsa) drivers
2012 2013 * (like chs, ata, and mlx which all make cmdk children) to put its
2013 2014 * own vector in the 'a_hba_tran' field. When all the drivers that do
2014 2015 * this are fixed, please remove this hack.
2015 2016 *
2016 2017 * NOTE: This hack is also shows up in the DEVP_TO_TRAN implementation
2017 2018 * in scsi_confsubr.c.
2018 2019 */
2019 2020 sd->sd_tran_safe = tran;
2020 2021
2021 2022 /*
2022 2023 * If the class property is not already established, set it to "scsi".
2023 2024 * This is done so that parent= driver.conf nodes have class.
2024 2025 */
2025 2026 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
2026 2027 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "class",
2027 2028 &class) == DDI_PROP_SUCCESS) {
2028 2029 ddi_prop_free(class);
2029 2030 } else if (ndi_prop_update_string(DDI_DEV_T_NONE, child,
2030 2031 "class", "scsi") != DDI_PROP_SUCCESS) {
2031 2032 SCSI_HBA_LOG((_LOG(2), NULL, child, "init failed: class"));
2032 2033 ndi_devi_set_hidden(child);
2033 2034 err = DDI_NOT_WELL_FORMED;
2034 2035 goto failure;
2035 2036 }
2036 2037
2037 2038 /* Establish the @addr name of the child. */
2038 2039 *addr = '\0';
2039 2040 if (scsi_busctl_ua(child, addr, sizeof (addr)) != DDI_SUCCESS) {
2040 2041 /*
2041 2042 * Some driver.conf files add bogus target properties (relative
2042 2043 * to their nexus representation of target) to their stub
2043 2044 * nodes, causing the check above to not filter them.
2044 2045 */
2045 2046 SCSI_HBA_LOG((_LOG(3), NULL, child,
2046 2047 "init failed: scsi_busctl_ua call"));
2047 2048 ndi_devi_set_hidden(child);
2048 2049 err = DDI_NOT_WELL_FORMED;
2049 2050 goto failure;
2050 2051 }
2051 2052 if (*addr == '\0') {
2052 2053 SCSI_HBA_LOG((_LOG(2), NULL, child, "init failed: ua"));
2053 2054 ndi_devi_set_hidden(child);
2054 2055 err = DDI_NOT_WELL_FORMED;
2055 2056 goto failure;
2056 2057 }
2057 2058
2058 2059 /* Prevent duplicate nodes. */
2059 2060 dup = ndi_devi_findchild_by_callback(self, ddi_node_name(child), addr,
2060 2061 scsi_busctl_ua);
2061 2062 if (dup) {
2062 2063 ASSERT(ndi_flavor_get(dup) == SCSA_FLAVOR_SCSI_DEVICE);
2063 2064 if (ndi_flavor_get(dup) != SCSA_FLAVOR_SCSI_DEVICE) {
2064 2065 SCSI_HBA_LOG((_LOG(1), NULL, child,
2065 2066 "init failed: %s@%s: not SCSI_DEVICE flavored",
2066 2067 ddi_node_name(child), addr));
2067 2068 goto failure;
2068 2069 }
2069 2070 if (dup != child) {
2070 2071 SCSI_HBA_LOG((_LOG(4), NULL, child,
2071 2072 "init failed: %s@%s: detected duplicate %p",
2072 2073 ddi_node_name(child), addr, (void *)dup));
2073 2074 goto failure;
2074 2075 }
2075 2076 }
2076 2077
2077 2078 /* set the node @addr string */
2078 2079 ddi_set_name_addr(child, addr);
2079 2080
2080 2081 /* call HBA's target init entry point if it exists */
2081 2082 if (tran->tran_tgt_init != NULL) {
2082 2083 SCSI_HBA_LOG((_LOG(4), NULL, child, "init tran_tgt_init"));
2083 2084 sd->sd_tran_tgt_free_done = 0;
2084 2085 if ((*tran->tran_tgt_init)
2085 2086 (self, child, tran, sd) != DDI_SUCCESS) {
2086 2087 scsi_enumeration_failed(child, -1, NULL,
2087 2088 "tran_tgt_init");
2088 2089 goto failure;
2089 2090 }
2090 2091 }
2091 2092
2092 2093 SCSI_HBA_LOG((_LOG(3), NULL, child, "init successful"));
2093 2094 return (DDI_SUCCESS);
2094 2095
2095 2096 failure:
2096 2097 if (tran_clone)
2097 2098 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
2098 2099 mutex_destroy(&sd->sd_mutex);
2099 2100 kmem_free(sd, sizeof (*sd));
2100 2101 ddi_set_driver_private(child, NULL);
2101 2102 ddi_set_name_addr(child, NULL);
2102 2103
2103 2104 return (err); /* remove the node */
2104 2105 }
2105 2106
2106 2107 static int
2107 2108 scsi_busctl_uninitchild(dev_info_t *child)
2108 2109 {
2109 2110 dev_info_t *self = ddi_get_parent(child);
2110 2111 struct scsi_device *sd = ddi_get_driver_private(child);
2111 2112 scsi_hba_tran_t *tran;
2112 2113 scsi_hba_tran_t *tran_clone;
2113 2114
2114 2115 ASSERT(DEVI_BUSY_OWNED(self));
2115 2116
2116 2117 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
2117 2118 ASSERT(tran && sd);
2118 2119 if ((tran == NULL) || (sd == NULL))
2119 2120 return (DDI_FAILURE);
2120 2121
2121 2122 /*
2122 2123 * We use sd_uninit_prevent to avoid uninitializing barrier/probe
2123 2124 * nodes that are still in use. Since barrier/probe nodes are not
2124 2125 * attached we can't prevent their state demotion via ndi_hold_devi.
2125 2126 */
2126 2127 if (sd->sd_uninit_prevent) {
2127 2128 SCSI_HBA_LOG((_LOG(2), NULL, child, "uninit prevented"));
2128 2129 return (DDI_FAILURE);
2129 2130 }
2130 2131
2131 2132 /*
2132 2133 * Don't uninitialize a client node if it still has paths.
2133 2134 */
2134 2135 if (MDI_CLIENT(child) && mdi_client_get_path_count(child)) {
2135 2136 SCSI_HBA_LOG((_LOG(2), NULL, child,
2136 2137 "uninit prevented, client has paths"));
2137 2138 return (DDI_FAILURE);
2138 2139 }
2139 2140
2140 2141 SCSI_HBA_LOG((_LOG(3), NULL, child, "uninit begin"));
2141 2142
2142 2143 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE) {
2143 2144 tran_clone = sd->sd_address.a_hba_tran;
2144 2145
2145 2146 /* ... grotty hack, involving sd_tran_safe, continued. */
2146 2147 if (tran_clone != sd->sd_tran_safe) {
2147 2148 tran_clone = sd->sd_tran_safe;
2148 2149 #ifdef DEBUG
2149 2150 /*
2150 2151 * Complain so things get fixed and hack can, at
2151 2152 * some point in time, be removed.
2152 2153 */
2153 2154 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
2154 2155 "'%s' is corrupting a_hba_tran", sd->sd_dev ?
2155 2156 ddi_driver_name(sd->sd_dev) : "unknown_driver"));
2156 2157 #endif /* DEBUG */
2157 2158 }
2158 2159
2159 2160 ASSERT(tran_clone->tran_hba_flags & SCSI_HBA_TRAN_CLONE);
2160 2161 ASSERT(tran_clone->tran_sd == sd);
2161 2162 tran = tran_clone;
2162 2163 } else {
2163 2164 tran_clone = NULL;
2164 2165 ASSERT(tran->tran_sd == NULL);
2165 2166 }
2166 2167
2167 2168 /*
2168 2169 * To simplify host adapter drivers we guarantee that multiple
2169 2170 * tran_tgt_init(9E) calls of the same unit address are never
2170 2171 * active at the same time. This requires that we always call
2171 2172 * tran_tgt_free on probe/barrier nodes directly prior to
2172 2173 * uninitchild.
2173 2174 *
2174 2175 * NOTE: To correctly support SCSI_HBA_TRAN_CLONE, we must use
2175 2176 * the (possibly cloned) hba_tran pointer from the scsi_device
2176 2177 * instead of hba_tran.
2177 2178 */
2178 2179 if (tran->tran_tgt_free) {
2179 2180 if (!sd->sd_tran_tgt_free_done) {
2180 2181 SCSI_HBA_LOG((_LOG(4), NULL, child,
2181 2182 "uninit tran_tgt_free"));
2182 2183 (*tran->tran_tgt_free) (self, child, tran, sd);
2183 2184 sd->sd_tran_tgt_free_done = 1;
2184 2185 } else {
2185 2186 SCSI_HBA_LOG((_LOG(4), NULL, child,
2186 2187 "uninit tran_tgt_free already done"));
2187 2188 }
2188 2189 }
2189 2190
2190 2191 /*
2191 2192 * If a inquiry data is still allocated (by scsi_probe()) we
2192 2193 * free the allocation here. This keeps scsi_inq valid for the
2193 2194 * same duration as the corresponding inquiry properties. It
2194 2195 * also allows a tran_tgt_init() implementation that establishes
2195 2196 * sd_inq to deal with deallocation in its tran_tgt_free
2196 2197 * (setting sd_inq back to NULL) without upsetting the
2197 2198 * framework. Moving the inquiry free here also allows setting
2198 2199 * of sd_uninit_prevent to preserve the data for lun0 based
2199 2200 * scsi_get_device_type_scsi_options() calls.
2200 2201 */
2201 2202 if (sd->sd_inq) {
2202 2203 kmem_free(sd->sd_inq, SUN_INQSIZE);
2203 2204 sd->sd_inq = (struct scsi_inquiry *)NULL;
2204 2205 }
2205 2206
2206 2207 mutex_destroy(&sd->sd_mutex);
2207 2208 if (tran_clone)
2208 2209 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
2209 2210 kmem_free(sd, sizeof (*sd));
2210 2211
2211 2212 ddi_set_driver_private(child, NULL);
2212 2213 SCSI_HBA_LOG((_LOG(3), NULL, child, "uninit complete"));
2213 2214 ddi_set_name_addr(child, NULL);
2214 2215 return (DDI_SUCCESS);
2215 2216 }
2216 2217
2217 2218 static int
2218 2219 iport_busctl_ua(dev_info_t *child, char *addr, int maxlen)
2219 2220 {
2220 2221 char *iport_ua;
2221 2222
2222 2223 /* limit ndi_devi_findchild_by_callback to expected flavor */
2223 2224 if (ndi_flavor_get(child) != SCSA_FLAVOR_IPORT)
2224 2225 return (DDI_FAILURE);
2225 2226
2226 2227 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
2227 2228 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2228 2229 SCSI_ADDR_PROP_IPORTUA, &iport_ua) != DDI_SUCCESS) {
2229 2230 return (DDI_FAILURE);
2230 2231 }
2231 2232
2232 2233 (void) snprintf(addr, maxlen, "%s", iport_ua);
2233 2234 ddi_prop_free(iport_ua);
2234 2235 return (DDI_SUCCESS);
2235 2236 }
2236 2237
2237 2238 static int
2238 2239 iport_busctl_reportdev(dev_info_t *child)
2239 2240 {
2240 2241 dev_info_t *self = ddi_get_parent(child);
2241 2242 char *iport_ua;
2242 2243 char *initiator_port = NULL;
2243 2244
2244 2245 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
2245 2246 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2246 2247 SCSI_ADDR_PROP_IPORTUA, &iport_ua) != DDI_SUCCESS)
2247 2248 return (DDI_FAILURE);
2248 2249
2249 2250 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
2250 2251 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2251 2252 SCSI_ADDR_PROP_INITIATOR_PORT, &initiator_port);
2252 2253
2253 2254 if (initiator_port) {
2254 2255 SCSI_HBA_LOG((_LOG_NF(CONT),
2255 2256 "?%s%d at %s%d: %s %s %s %s",
2256 2257 ddi_driver_name(child), ddi_get_instance(child),
2257 2258 ddi_driver_name(self), ddi_get_instance(self),
2258 2259 SCSI_ADDR_PROP_INITIATOR_PORT, initiator_port,
2259 2260 SCSI_ADDR_PROP_IPORTUA, iport_ua));
2260 2261 ddi_prop_free(initiator_port);
2261 2262 } else {
2262 2263 SCSI_HBA_LOG((_LOG_NF(CONT), "?%s%d at %s%d: %s %s",
2263 2264 ddi_driver_name(child), ddi_get_instance(child),
2264 2265 ddi_driver_name(self), ddi_get_instance(self),
2265 2266 SCSI_ADDR_PROP_IPORTUA, iport_ua));
2266 2267 }
2267 2268 ddi_prop_free(iport_ua);
2268 2269 return (DDI_SUCCESS);
2269 2270 }
2270 2271
2271 2272 /* initchild SCSA iport 'child' node */
2272 2273 static int
2273 2274 iport_busctl_initchild(dev_info_t *child)
2274 2275 {
2275 2276 dev_info_t *self = ddi_get_parent(child);
2276 2277 dev_info_t *dup = NULL;
2277 2278 char addr[SCSI_MAXNAMELEN];
2278 2279
2279 2280 if (iport_busctl_ua(child, addr, sizeof (addr)) != DDI_SUCCESS)
2280 2281 return (DDI_NOT_WELL_FORMED);
2281 2282
2282 2283 /* Prevent duplicate nodes. */
2283 2284 dup = ndi_devi_findchild_by_callback(self, ddi_node_name(child), addr,
2284 2285 iport_busctl_ua);
2285 2286 if (dup) {
2286 2287 ASSERT(ndi_flavor_get(dup) == SCSA_FLAVOR_IPORT);
2287 2288 if (ndi_flavor_get(dup) != SCSA_FLAVOR_IPORT) {
2288 2289 SCSI_HBA_LOG((_LOG(1), NULL, child,
2289 2290 "init failed: %s@%s: not IPORT flavored",
2290 2291 ddi_node_name(child), addr));
2291 2292 return (DDI_FAILURE);
2292 2293 }
2293 2294 if (dup != child) {
2294 2295 SCSI_HBA_LOG((_LOG(4), NULL, child,
2295 2296 "init failed: %s@%s: detected duplicate %p",
2296 2297 ddi_node_name(child), addr, (void *)dup));
2297 2298 return (DDI_FAILURE);
2298 2299 }
2299 2300 }
2300 2301
2301 2302 /* set the node @addr string */
2302 2303 ddi_set_name_addr(child, addr);
2303 2304
2304 2305 return (DDI_SUCCESS);
2305 2306 }
2306 2307
2307 2308 /* uninitchild SCSA iport 'child' node */
2308 2309 static int
2309 2310 iport_busctl_uninitchild(dev_info_t *child)
2310 2311 {
2311 2312 ddi_set_name_addr(child, NULL);
2312 2313 return (DDI_SUCCESS);
2313 2314 }
2314 2315
2315 2316 /* Uninitialize scsi_device flavor of transport on SCSA iport 'child' node. */
2316 2317 static void
2317 2318 iport_postdetach_tran_scsi_device(dev_info_t *child)
2318 2319 {
2319 2320 scsi_hba_tran_t *tran;
2320 2321
2321 2322 tran = ndi_flavorv_get(child, SCSA_FLAVOR_SCSI_DEVICE);
2322 2323 if (tran == NULL)
2323 2324 return;
2324 2325
2325 2326 scsa_tran_teardown(child, tran);
2326 2327 scsa_nexus_teardown(child, tran);
2327 2328
2328 2329 ndi_flavorv_set(child, SCSA_FLAVOR_SCSI_DEVICE, NULL);
2329 2330 scsi_hba_tran_free(tran);
2330 2331 }
2331 2332
2332 2333 /* Initialize scsi_device flavor of transport on SCSA iport 'child' node. */
2333 2334 static void
2334 2335 iport_preattach_tran_scsi_device(dev_info_t *child)
2335 2336 {
2336 2337 dev_info_t *hba = ddi_get_parent(child);
2337 2338 scsi_hba_tran_t *htran;
2338 2339 scsi_hba_tran_t *tran;
2339 2340
2340 2341 /* parent HBA node scsi_device tran is required */
2341 2342 htran = ndi_flavorv_get(hba, SCSA_FLAVOR_SCSI_DEVICE);
2342 2343 ASSERT(htran);
2343 2344
2344 2345 /* Allocate iport child's scsi_device transport vector */
2345 2346 tran = scsi_hba_tran_alloc(child, SCSI_HBA_CANSLEEP);
2346 2347 ASSERT(tran);
2347 2348
2348 2349 /* Structure-copy scsi_device transport of HBA to iport. */
2349 2350 *tran = *htran;
2350 2351
2351 2352 /*
2352 2353 * Reset scsi_device transport fields not shared with the
2353 2354 * parent, and not established below.
2354 2355 */
2355 2356 tran->tran_open_flag = 0;
2356 2357 tran->tran_hba_private = NULL;
2357 2358
2358 2359 /* Establish the devinfo context of this tran structure. */
2359 2360 tran->tran_iport_dip = child;
2360 2361
2361 2362 /* Clear SCSI_HBA_SCSA flags (except TA) */
2362 2363 tran->tran_hba_flags &=
2363 2364 ~(SCSI_HBA_SCSA_FM | SCSI_HBA_SCSA_PHCI); /* clear parent state */
2364 2365 tran->tran_hba_flags |= SCSI_HBA_SCSA_TA; /* always TA */
2365 2366 tran->tran_hba_flags &= ~SCSI_HBA_HBA; /* never HBA */
2366 2367
2367 2368 /* Establish flavor of transport (and ddi_get_driver_private()) */
2368 2369 ndi_flavorv_set(child, SCSA_FLAVOR_SCSI_DEVICE, tran);
2369 2370
2370 2371 /* Setup iport node */
2371 2372 if ((scsa_nexus_setup(child, tran) != DDI_SUCCESS) ||
2372 2373 (scsa_tran_setup(child, tran) != DDI_SUCCESS))
2373 2374 iport_postdetach_tran_scsi_device(child);
2374 2375 }
2375 2376
2376 2377 /* Uninitialize smp_device flavor of transport on SCSA iport 'child' node. */
2377 2378 static void
2378 2379 iport_postdetach_tran_smp_device(dev_info_t *child)
2379 2380 {
2380 2381 smp_hba_tran_t *tran;
2381 2382
2382 2383 tran = ndi_flavorv_get(child, SCSA_FLAVOR_SMP);
2383 2384 if (tran == NULL)
2384 2385 return;
2385 2386
2386 2387 ndi_flavorv_set(child, SCSA_FLAVOR_SMP, NULL);
2387 2388 smp_hba_tran_free(tran);
2388 2389 }
2389 2390
2390 2391 /* Initialize smp_device flavor of transport on SCSA iport 'child' node. */
2391 2392 static void
2392 2393 iport_preattach_tran_smp_device(dev_info_t *child)
2393 2394 {
2394 2395 dev_info_t *hba = ddi_get_parent(child);
2395 2396 smp_hba_tran_t *htran;
2396 2397 smp_hba_tran_t *tran;
2397 2398
2398 2399 /* parent HBA node smp_device tran is optional */
2399 2400 htran = ndi_flavorv_get(hba, SCSA_FLAVOR_SMP);
2400 2401 if (htran == NULL) {
2401 2402 ndi_flavorv_set(child, SCSA_FLAVOR_SMP, NULL);
2402 2403 return;
2403 2404 }
2404 2405
2405 2406 /* Allocate iport child's smp_device transport vector */
2406 2407 tran = smp_hba_tran_alloc(child);
2407 2408
2408 2409 /* Structure-copy smp_device transport of HBA to iport. */
2409 2410 *tran = *htran;
2410 2411
2411 2412 /* Establish flavor of transport */
2412 2413 ndi_flavorv_set(child, SCSA_FLAVOR_SMP, tran);
2413 2414 }
2414 2415
2415 2416 /*
2416 2417 * Generic bus_ctl operations for SCSI HBA's,
2417 2418 * hiding the busctl interface from the HBA.
2418 2419 */
2419 2420 /*ARGSUSED*/
2420 2421 static int
2421 2422 scsi_hba_bus_ctl(
2422 2423 dev_info_t *self,
2423 2424 dev_info_t *child,
2424 2425 ddi_ctl_enum_t op,
2425 2426 void *arg,
2426 2427 void *result)
2427 2428 {
2428 2429 int child_flavor = 0;
2429 2430 int val;
2430 2431 ddi_dma_attr_t *attr;
2431 2432 scsi_hba_tran_t *tran;
2432 2433 struct attachspec *as;
2433 2434 struct detachspec *ds;
2434 2435
2435 2436 /* For some ops, child is 'arg'. */
2436 2437 if ((op == DDI_CTLOPS_INITCHILD) || (op == DDI_CTLOPS_UNINITCHILD))
2437 2438 child = (dev_info_t *)arg;
2438 2439
2439 2440 /* Determine the flavor of the child: scsi, smp, iport */
2440 2441 child_flavor = ndi_flavor_get(child);
2441 2442
2442 2443 switch (op) {
2443 2444 case DDI_CTLOPS_INITCHILD:
2444 2445 switch (child_flavor) {
2445 2446 case SCSA_FLAVOR_SCSI_DEVICE:
2446 2447 return (scsi_busctl_initchild(child));
2447 2448 case SCSA_FLAVOR_SMP:
2448 2449 return (smp_busctl_initchild(child));
2449 2450 case SCSA_FLAVOR_IPORT:
2450 2451 return (iport_busctl_initchild(child));
2451 2452 default:
2452 2453 return (DDI_FAILURE);
2453 2454 }
2454 2455 /* NOTREACHED */
2455 2456
2456 2457 case DDI_CTLOPS_UNINITCHILD:
2457 2458 switch (child_flavor) {
2458 2459 case SCSA_FLAVOR_SCSI_DEVICE:
2459 2460 return (scsi_busctl_uninitchild(child));
2460 2461 case SCSA_FLAVOR_SMP:
2461 2462 return (smp_busctl_uninitchild(child));
2462 2463 case SCSA_FLAVOR_IPORT:
2463 2464 return (iport_busctl_uninitchild(child));
2464 2465 default:
2465 2466 return (DDI_FAILURE);
2466 2467 }
2467 2468 /* NOTREACHED */
2468 2469
2469 2470 case DDI_CTLOPS_REPORTDEV:
2470 2471 switch (child_flavor) {
2471 2472 case SCSA_FLAVOR_SCSI_DEVICE:
2472 2473 return (scsi_busctl_reportdev(child));
2473 2474 case SCSA_FLAVOR_SMP:
2474 2475 return (smp_busctl_reportdev(child));
2475 2476 case SCSA_FLAVOR_IPORT:
2476 2477 return (iport_busctl_reportdev(child));
2477 2478 default:
2478 2479 return (DDI_FAILURE);
2479 2480 }
2480 2481 /* NOTREACHED */
2481 2482
2482 2483 case DDI_CTLOPS_ATTACH:
2483 2484 as = (struct attachspec *)arg;
2484 2485
2485 2486 if (child_flavor != SCSA_FLAVOR_IPORT)
2486 2487 return (DDI_SUCCESS);
2487 2488
2488 2489 /* iport processing */
2489 2490 if (as->when == DDI_PRE) {
2490 2491 /* setup pre attach(9E) */
2491 2492 iport_preattach_tran_scsi_device(child);
2492 2493 iport_preattach_tran_smp_device(child);
2493 2494 } else if ((as->when == DDI_POST) &&
2494 2495 (as->result != DDI_SUCCESS)) {
2495 2496 /* cleanup if attach(9E) failed */
2496 2497 iport_postdetach_tran_scsi_device(child);
2497 2498 iport_postdetach_tran_smp_device(child);
2498 2499 }
2499 2500 return (DDI_SUCCESS);
2500 2501
2501 2502 case DDI_CTLOPS_DETACH:
2502 2503 ds = (struct detachspec *)arg;
2503 2504
2504 2505 if (child_flavor != SCSA_FLAVOR_IPORT)
2505 2506 return (DDI_SUCCESS);
2506 2507
2507 2508 /* iport processing */
2508 2509 if ((ds->when == DDI_POST) &&
2509 2510 (ds->result == DDI_SUCCESS)) {
2510 2511 /* cleanup if detach(9E) was successful */
2511 2512 iport_postdetach_tran_scsi_device(child);
2512 2513 iport_postdetach_tran_smp_device(child);
2513 2514 }
2514 2515 return (DDI_SUCCESS);
2515 2516
2516 2517 case DDI_CTLOPS_IOMIN:
2517 2518 tran = ddi_get_driver_private(self);
2518 2519 ASSERT(tran);
2519 2520 if (tran == NULL)
2520 2521 return (DDI_FAILURE);
2521 2522
2522 2523 /*
2523 2524 * The 'arg' value of nonzero indicates 'streaming'
2524 2525 * mode. If in streaming mode, pick the largest
2525 2526 * of our burstsizes available and say that that
2526 2527 * is our minimum value (modulo what minxfer is).
2527 2528 */
2528 2529 attr = &tran->tran_dma_attr;
2529 2530 val = *((int *)result);
2530 2531 val = maxbit(val, attr->dma_attr_minxfer);
2531 2532 *((int *)result) = maxbit(val, ((intptr_t)arg ?
2532 2533 (1<<ddi_ffs(attr->dma_attr_burstsizes)-1) :
2533 2534 (1<<(ddi_fls(attr->dma_attr_burstsizes)-1))));
2534 2535
2535 2536 return (ddi_ctlops(self, child, op, arg, result));
2536 2537
2537 2538 case DDI_CTLOPS_SIDDEV:
2538 2539 return (ndi_dev_is_persistent_node(child) ?
2539 2540 DDI_SUCCESS : DDI_FAILURE);
2540 2541
2541 2542 case DDI_CTLOPS_POWER:
2542 2543 return (DDI_SUCCESS);
2543 2544
2544 2545 /*
2545 2546 * These ops correspond to functions that "shouldn't" be called
2546 2547 * by a SCSI target driver. So we whine when we're called.
2547 2548 */
2548 2549 case DDI_CTLOPS_DMAPMAPC:
2549 2550 case DDI_CTLOPS_REPORTINT:
2550 2551 case DDI_CTLOPS_REGSIZE:
2551 2552 case DDI_CTLOPS_NREGS:
2552 2553 case DDI_CTLOPS_SLAVEONLY:
2553 2554 case DDI_CTLOPS_AFFINITY:
2554 2555 case DDI_CTLOPS_POKE:
2555 2556 case DDI_CTLOPS_PEEK:
2556 2557 SCSI_HBA_LOG((_LOG(WARN), self, NULL, "invalid op (%d)", op));
2557 2558 return (DDI_FAILURE);
2558 2559
2559 2560 /* Everything else we pass up */
2560 2561 case DDI_CTLOPS_PTOB:
2561 2562 case DDI_CTLOPS_BTOP:
2562 2563 case DDI_CTLOPS_BTOPR:
2563 2564 case DDI_CTLOPS_DVMAPAGESIZE:
2564 2565 default:
2565 2566 return (ddi_ctlops(self, child, op, arg, result));
2566 2567 }
2567 2568 /* NOTREACHED */
2568 2569 }
2569 2570
2570 2571 /*
2571 2572 * Private wrapper for scsi_pkt's allocated via scsi_hba_pkt_alloc()
2572 2573 */
2573 2574 struct scsi_pkt_wrapper {
2574 2575 struct scsi_pkt scsi_pkt;
2575 2576 int pkt_wrapper_magic;
2576 2577 int pkt_wrapper_len;
2577 2578 };
2578 2579
2579 2580 #if !defined(lint)
2580 2581 _NOTE(SCHEME_PROTECTS_DATA("unique per thread", scsi_pkt_wrapper))
2581 2582 _NOTE(SCHEME_PROTECTS_DATA("Unshared Data", dev_ops))
2582 2583 #endif
2583 2584
2584 2585 /*
2585 2586 * Called by an HBA to allocate a scsi_pkt
2586 2587 */
2587 2588 /*ARGSUSED*/
2588 2589 struct scsi_pkt *
2589 2590 scsi_hba_pkt_alloc(
2590 2591 dev_info_t *self,
2591 2592 struct scsi_address *ap,
2592 2593 int cmdlen,
2593 2594 int statuslen,
2594 2595 int tgtlen,
2595 2596 int hbalen,
2596 2597 int (*callback)(caddr_t arg),
2597 2598 caddr_t arg)
2598 2599 {
2599 2600 struct scsi_pkt *pkt;
2600 2601 struct scsi_pkt_wrapper *hba_pkt;
2601 2602 caddr_t p;
2602 2603 int acmdlen, astatuslen, atgtlen, ahbalen;
2603 2604 int pktlen;
2604 2605
2605 2606 /* Sanity check */
2606 2607 if (callback != SLEEP_FUNC && callback != NULL_FUNC)
2607 2608 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
2608 2609 "callback must be SLEEP_FUNC or NULL_FUNC"));
2609 2610
2610 2611 /*
2611 2612 * Round up so everything gets allocated on long-word boundaries
2612 2613 */
2613 2614 acmdlen = ROUNDUP(cmdlen);
2614 2615 astatuslen = ROUNDUP(statuslen);
2615 2616 atgtlen = ROUNDUP(tgtlen);
2616 2617 ahbalen = ROUNDUP(hbalen);
2617 2618 pktlen = sizeof (struct scsi_pkt_wrapper) +
2618 2619 acmdlen + astatuslen + atgtlen + ahbalen;
2619 2620
2620 2621 hba_pkt = kmem_zalloc(pktlen,
2621 2622 (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP);
2622 2623 if (hba_pkt == NULL) {
2623 2624 ASSERT(callback == NULL_FUNC);
2624 2625 return (NULL);
2625 2626 }
2626 2627
2627 2628 /*
2628 2629 * Set up our private info on this pkt
2629 2630 */
2630 2631 hba_pkt->pkt_wrapper_len = pktlen;
2631 2632 hba_pkt->pkt_wrapper_magic = PKT_WRAPPER_MAGIC; /* alloced correctly */
2632 2633 pkt = &hba_pkt->scsi_pkt;
2633 2634
2634 2635 /*
2635 2636 * Set up pointers to private data areas, cdb, and status.
2636 2637 */
2637 2638 p = (caddr_t)(hba_pkt + 1);
2638 2639 if (hbalen > 0) {
2639 2640 pkt->pkt_ha_private = (opaque_t)p;
2640 2641 p += ahbalen;
2641 2642 }
2642 2643 if (tgtlen > 0) {
2643 2644 pkt->pkt_private = (opaque_t)p;
2644 2645 p += atgtlen;
2645 2646 }
2646 2647 if (statuslen > 0) {
2647 2648 pkt->pkt_scbp = (uchar_t *)p;
2648 2649 p += astatuslen;
2649 2650 }
2650 2651 if (cmdlen > 0) {
2651 2652 pkt->pkt_cdbp = (uchar_t *)p;
2652 2653 }
2653 2654
2654 2655 /*
2655 2656 * Initialize the pkt's scsi_address
2656 2657 */
2657 2658 pkt->pkt_address = *ap;
2658 2659
2659 2660 /*
2660 2661 * NB: It may not be safe for drivers, esp target drivers, to depend
2661 2662 * on the following fields being set until all the scsi_pkt
2662 2663 * allocation violations discussed in scsi_pkt.h are all resolved.
2663 2664 */
2664 2665 pkt->pkt_cdblen = cmdlen;
2665 2666 pkt->pkt_tgtlen = tgtlen;
2666 2667 pkt->pkt_scblen = statuslen;
2667 2668
2668 2669 return (pkt);
2669 2670 }
2670 2671
2671 2672 /*
2672 2673 * Called by an HBA to free a scsi_pkt
2673 2674 */
2674 2675 /*ARGSUSED*/
2675 2676 void
2676 2677 scsi_hba_pkt_free(
2677 2678 struct scsi_address *ap,
2678 2679 struct scsi_pkt *pkt)
2679 2680 {
2680 2681 kmem_free(pkt, ((struct scsi_pkt_wrapper *)pkt)->pkt_wrapper_len);
2681 2682 }
2682 2683
2683 2684 /*
2684 2685 * Return 1 if the scsi_pkt used a proper allocator.
2685 2686 *
2686 2687 * The DDI does not allow a driver to allocate it's own scsi_pkt(9S), a
2687 2688 * driver should not have *any* compiled in dependencies on "sizeof (struct
2688 2689 * scsi_pkt)". While this has been the case for many years, a number of
2689 2690 * drivers have still not been fixed. This function can be used to detect
2690 2691 * improperly allocated scsi_pkt structures, and produce messages identifying
2691 2692 * drivers that need to be fixed.
2692 2693 *
2693 2694 * While drivers in violation are being fixed, this function can also
2694 2695 * be used by the framework to detect packets that violated allocation
2695 2696 * rules.
2696 2697 *
2697 2698 * NB: It is possible, but very unlikely, for this code to return a false
2698 2699 * positive (finding correct magic, but for wrong reasons). Careful
2699 2700 * consideration is needed for callers using this interface to condition
2700 2701 * access to newer scsi_pkt fields (those after pkt_reason).
2701 2702 *
2702 2703 * NB: As an aid to minimizing the amount of work involved in 'fixing' legacy
2703 2704 * drivers that violate scsi_*(9S) allocation rules, private
2704 2705 * scsi_pkt_size()/scsi_size_clean() functions are available (see their
2705 2706 * implementation for details).
2706 2707 *
2707 2708 * *** Non-legacy use of scsi_pkt_size() is discouraged. ***
2708 2709 *
2709 2710 * NB: When supporting broken HBA drivers is not longer a concern, this
2710 2711 * code should be removed.
2711 2712 */
2712 2713 int
2713 2714 scsi_pkt_allocated_correctly(struct scsi_pkt *pkt)
2714 2715 {
2715 2716 struct scsi_pkt_wrapper *hba_pkt = (struct scsi_pkt_wrapper *)pkt;
2716 2717 int magic;
2717 2718 major_t major;
2718 2719 #ifdef DEBUG
2719 2720 int *pspwm, *pspcwm;
2720 2721
2721 2722 /*
2722 2723 * We are getting scsi packets from two 'correct' wrapper schemes,
2723 2724 * make sure we are looking at the same place in both to detect
2724 2725 * proper allocation.
2725 2726 */
2726 2727 pspwm = &((struct scsi_pkt_wrapper *)0)->pkt_wrapper_magic;
2727 2728 pspcwm = &((struct scsi_pkt_cache_wrapper *)0)->pcw_magic;
2728 2729 ASSERT(pspwm == pspcwm);
2729 2730 #endif /* DEBUG */
2730 2731
2731 2732
2732 2733 /*
2733 2734 * Check to see if driver is scsi_size_clean(), assume it
2734 2735 * is using the scsi_pkt_size() interface everywhere it needs to
2735 2736 * if the driver indicates it is scsi_size_clean().
2736 2737 */
2737 2738 major = ddi_driver_major(P_TO_TRAN(pkt)->tran_hba_dip);
2738 2739 if (devnamesp[major].dn_flags & DN_SCSI_SIZE_CLEAN)
2739 2740 return (1); /* ok */
2740 2741
2741 2742 /*
2742 2743 * Special case crossing a page boundary. If the scsi_pkt was not
2743 2744 * allocated correctly, then across a page boundary we have a
2744 2745 * fault hazard.
2745 2746 */
2746 2747 if ((((uintptr_t)(&hba_pkt->scsi_pkt)) & MMU_PAGEMASK) ==
2747 2748 (((uintptr_t)(&hba_pkt->pkt_wrapper_magic)) & MMU_PAGEMASK)) {
2748 2749 /* fastpath, no cross-page hazard */
2749 2750 magic = hba_pkt->pkt_wrapper_magic;
2750 2751 } else {
2751 2752 /* add protection for cross-page hazard */
2752 2753 if (ddi_peek32((dev_info_t *)NULL,
2753 2754 &hba_pkt->pkt_wrapper_magic, &magic) == DDI_FAILURE) {
2754 2755 return (0); /* violation */
2755 2756 }
2756 2757 }
2757 2758
2758 2759 /* properly allocated packet always has correct magic */
2759 2760 return ((magic == PKT_WRAPPER_MAGIC) ? 1 : 0);
2760 2761 }
2761 2762
2762 2763 /*
2763 2764 * Private interfaces to simplify conversion of legacy drivers so they don't
2764 2765 * depend on scsi_*(9S) size. Instead of using these private interface, HBA
2765 2766 * drivers should use DDI sanctioned allocation methods:
2766 2767 *
2767 2768 * scsi_pkt Use scsi_hba_pkt_alloc(9F), or implement
2768 2769 * tran_setup_pkt(9E).
2769 2770 *
2770 2771 * scsi_device You are doing something strange/special, a scsi_device
2771 2772 * structure should only be allocated by scsi_hba.c
2772 2773 * initchild code or scsi_vhci.c code.
2773 2774 *
2774 2775 * scsi_hba_tran Use scsi_hba_tran_alloc(9F).
2775 2776 */
2776 2777 size_t
2777 2778 scsi_pkt_size()
2778 2779 {
2779 2780 return (sizeof (struct scsi_pkt));
2780 2781 }
2781 2782
2782 2783 size_t
2783 2784 scsi_hba_tran_size()
2784 2785 {
2785 2786 return (sizeof (scsi_hba_tran_t));
2786 2787 }
2787 2788
2788 2789 size_t
2789 2790 scsi_device_size()
2790 2791 {
2791 2792 return (sizeof (struct scsi_device));
2792 2793 }
2793 2794
2794 2795 /*
2795 2796 * Legacy compliance to scsi_pkt(9S) allocation rules through use of
2796 2797 * scsi_pkt_size() is detected by the 'scsi-size-clean' driver.conf property
2797 2798 * or an HBA driver calling to scsi_size_clean() from attach(9E). A driver
2798 2799 * developer should only indicate that a legacy driver is clean after using
2799 2800 * SCSI_SIZE_CLEAN_VERIFY to ensure compliance (see scsi_pkt.h).
2800 2801 */
2801 2802 void
2802 2803 scsi_size_clean(dev_info_t *self)
2803 2804 {
2804 2805 major_t major;
2805 2806 struct devnames *dnp;
2806 2807
2807 2808 ASSERT(self);
2808 2809 major = ddi_driver_major(self);
2809 2810 ASSERT(major < devcnt);
2810 2811 if (major >= devcnt) {
2811 2812 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
2812 2813 "scsi_pkt_size: bogus major: %d", major));
2813 2814 return;
2814 2815 }
2815 2816
2816 2817 /* Set DN_SCSI_SIZE_CLEAN flag in dn_flags. */
2817 2818 dnp = &devnamesp[major];
2818 2819 if ((dnp->dn_flags & DN_SCSI_SIZE_CLEAN) == 0) {
2819 2820 LOCK_DEV_OPS(&dnp->dn_lock);
2820 2821 dnp->dn_flags |= DN_SCSI_SIZE_CLEAN;
2821 2822 UNLOCK_DEV_OPS(&dnp->dn_lock);
2822 2823 }
2823 2824 }
2824 2825
2825 2826
2826 2827 /*
2827 2828 * Called by an HBA to map strings to capability indices
2828 2829 */
2829 2830 int
2830 2831 scsi_hba_lookup_capstr(
2831 2832 char *capstr)
2832 2833 {
2833 2834 /*
2834 2835 * Capability strings: only add entries to mask the legacy
2835 2836 * '_' vs. '-' misery. All new capabilities should use '-',
2836 2837 * and be captured be added to SCSI_CAP_ASCII.
2837 2838 */
2838 2839 static struct cap_strings {
2839 2840 char *cap_string;
2840 2841 int cap_index;
2841 2842 } cap_strings[] = {
2842 2843 { "dma_max", SCSI_CAP_DMA_MAX },
2843 2844 { "msg_out", SCSI_CAP_MSG_OUT },
2844 2845 { "wide_xfer", SCSI_CAP_WIDE_XFER },
2845 2846 { NULL, 0 }
2846 2847 };
2847 2848 static char *cap_ascii[] = SCSI_CAP_ASCII;
2848 2849 char **cap;
2849 2850 int i;
2850 2851 struct cap_strings *cp;
2851 2852
2852 2853 for (cap = cap_ascii, i = 0; *cap != NULL; cap++, i++)
2853 2854 if (strcmp(*cap, capstr) == 0)
2854 2855 return (i);
2855 2856
2856 2857 for (cp = cap_strings; cp->cap_string != NULL; cp++)
2857 2858 if (strcmp(cp->cap_string, capstr) == 0)
2858 2859 return (cp->cap_index);
2859 2860
2860 2861 return (-1);
2861 2862 }
2862 2863
2863 2864 /*
2864 2865 * Called by an HBA to determine if the system is in 'panic' state.
2865 2866 */
2866 2867 int
2867 2868 scsi_hba_in_panic()
2868 2869 {
2869 2870 return (panicstr != NULL);
2870 2871 }
2871 2872
2872 2873 /*
2873 2874 * If a SCSI target driver attempts to mmap memory,
2874 2875 * the buck stops here.
2875 2876 */
2876 2877 /*ARGSUSED*/
2877 2878 static int
2878 2879 scsi_hba_map_fault(
2879 2880 dev_info_t *self,
2880 2881 dev_info_t *child,
2881 2882 struct hat *hat,
2882 2883 struct seg *seg,
2883 2884 caddr_t addr,
2884 2885 struct devpage *dp,
2885 2886 pfn_t pfn,
2886 2887 uint_t prot,
2887 2888 uint_t lock)
2888 2889 {
2889 2890 return (DDI_FAILURE);
2890 2891 }
2891 2892
2892 2893 static int
2893 2894 scsi_hba_get_eventcookie(
2894 2895 dev_info_t *self,
2895 2896 dev_info_t *child,
2896 2897 char *name,
2897 2898 ddi_eventcookie_t *eventp)
2898 2899 {
2899 2900 scsi_hba_tran_t *tran;
2900 2901
2901 2902 tran = ddi_get_driver_private(self);
2902 2903 if (tran->tran_get_eventcookie &&
2903 2904 ((*tran->tran_get_eventcookie)(self,
2904 2905 child, name, eventp) == DDI_SUCCESS)) {
2905 2906 return (DDI_SUCCESS);
2906 2907 }
2907 2908
2908 2909 return (ndi_busop_get_eventcookie(self, child, name, eventp));
2909 2910 }
2910 2911
2911 2912 static int
2912 2913 scsi_hba_add_eventcall(
2913 2914 dev_info_t *self,
2914 2915 dev_info_t *child,
2915 2916 ddi_eventcookie_t event,
2916 2917 void (*callback)(
2917 2918 dev_info_t *self,
2918 2919 ddi_eventcookie_t event,
2919 2920 void *arg,
2920 2921 void *bus_impldata),
2921 2922 void *arg,
2922 2923 ddi_callback_id_t *cb_id)
2923 2924 {
2924 2925 scsi_hba_tran_t *tran;
2925 2926
2926 2927 tran = ddi_get_driver_private(self);
2927 2928 if (tran->tran_add_eventcall &&
2928 2929 ((*tran->tran_add_eventcall)(self, child,
2929 2930 event, callback, arg, cb_id) == DDI_SUCCESS)) {
2930 2931 return (DDI_SUCCESS);
2931 2932 }
2932 2933
2933 2934 return (DDI_FAILURE);
2934 2935 }
2935 2936
2936 2937 static int
2937 2938 scsi_hba_remove_eventcall(dev_info_t *self, ddi_callback_id_t cb_id)
2938 2939 {
2939 2940 scsi_hba_tran_t *tran;
2940 2941 ASSERT(cb_id);
2941 2942
2942 2943 tran = ddi_get_driver_private(self);
2943 2944 if (tran->tran_remove_eventcall &&
2944 2945 ((*tran->tran_remove_eventcall)(
2945 2946 self, cb_id) == DDI_SUCCESS)) {
2946 2947 return (DDI_SUCCESS);
2947 2948 }
2948 2949
2949 2950 return (DDI_FAILURE);
2950 2951 }
2951 2952
2952 2953 static int
2953 2954 scsi_hba_post_event(
2954 2955 dev_info_t *self,
2955 2956 dev_info_t *child,
2956 2957 ddi_eventcookie_t event,
2957 2958 void *bus_impldata)
2958 2959 {
2959 2960 scsi_hba_tran_t *tran;
2960 2961
2961 2962 tran = ddi_get_driver_private(self);
2962 2963 if (tran->tran_post_event &&
2963 2964 ((*tran->tran_post_event)(self,
2964 2965 child, event, bus_impldata) == DDI_SUCCESS)) {
2965 2966 return (DDI_SUCCESS);
2966 2967 }
2967 2968
2968 2969 return (DDI_FAILURE);
2969 2970 }
2970 2971
2971 2972 /*
2972 2973 * Default getinfo(9e) for scsi_hba
2973 2974 */
2974 2975 /* ARGSUSED */
2975 2976 static int
2976 2977 scsi_hba_info(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg,
2977 2978 void **result)
2978 2979 {
2979 2980 int error = DDI_SUCCESS;
2980 2981
2981 2982 switch (infocmd) {
2982 2983 case DDI_INFO_DEVT2INSTANCE:
2983 2984 *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg)));
2984 2985 break;
2985 2986 default:
2986 2987 error = DDI_FAILURE;
2987 2988 }
2988 2989 return (error);
2989 2990 }
2990 2991
2991 2992 /*
2992 2993 * Default open and close routine for scsi_hba
2993 2994 */
2994 2995 /* ARGSUSED */
2995 2996 int
2996 2997 scsi_hba_open(dev_t *devp, int flags, int otyp, cred_t *credp)
2997 2998 {
2998 2999 dev_info_t *self;
2999 3000 scsi_hba_tran_t *tran;
3000 3001 int rv = 0;
3001 3002
3002 3003 if (otyp != OTYP_CHR)
3003 3004 return (EINVAL);
3004 3005
3005 3006 if ((self = e_ddi_hold_devi_by_dev(*devp, 0)) == NULL)
3006 3007 return (ENXIO);
3007 3008
3008 3009 tran = ddi_get_driver_private(self);
3009 3010 if (tran == NULL) {
3010 3011 ddi_release_devi(self);
3011 3012 return (ENXIO);
3012 3013 }
3013 3014
3014 3015 /*
3015 3016 * tran_open_flag bit field:
3016 3017 * 0: closed
3017 3018 * 1: shared open by minor at bit position
3018 3019 * 1 at 31st bit: exclusive open
3019 3020 */
3020 3021 mutex_enter(&(tran->tran_open_lock));
3021 3022 if (flags & FEXCL) {
3022 3023 if (tran->tran_open_flag != 0) {
3023 3024 rv = EBUSY; /* already open */
3024 3025 } else {
3025 3026 tran->tran_open_flag = TRAN_OPEN_EXCL;
3026 3027 }
3027 3028 } else {
3028 3029 if (tran->tran_open_flag == TRAN_OPEN_EXCL) {
3029 3030 rv = EBUSY; /* already excl. open */
3030 3031 } else {
3031 3032 int minor = getminor(*devp) & TRAN_MINOR_MASK;
3032 3033 tran->tran_open_flag |= (1 << minor);
3033 3034 /*
3034 3035 * Ensure that the last framework reserved minor
3035 3036 * is unused. Otherwise, the exclusive open
3036 3037 * mechanism may break.
3037 3038 */
3038 3039 ASSERT(minor != 31);
3039 3040 }
3040 3041 }
3041 3042 mutex_exit(&(tran->tran_open_lock));
3042 3043
3043 3044 ddi_release_devi(self);
3044 3045 return (rv);
3045 3046 }
3046 3047
3047 3048 /* ARGSUSED */
3048 3049 int
3049 3050 scsi_hba_close(dev_t dev, int flag, int otyp, cred_t *credp)
3050 3051 {
3051 3052 dev_info_t *self;
3052 3053 scsi_hba_tran_t *tran;
3053 3054
3054 3055 if (otyp != OTYP_CHR)
3055 3056 return (EINVAL);
3056 3057
3057 3058 if ((self = e_ddi_hold_devi_by_dev(dev, 0)) == NULL)
3058 3059 return (ENXIO);
3059 3060
3060 3061 tran = ddi_get_driver_private(self);
3061 3062 if (tran == NULL) {
3062 3063 ddi_release_devi(self);
3063 3064 return (ENXIO);
3064 3065 }
3065 3066
3066 3067 mutex_enter(&(tran->tran_open_lock));
3067 3068 if (tran->tran_open_flag == TRAN_OPEN_EXCL) {
3068 3069 tran->tran_open_flag = 0;
3069 3070 } else {
3070 3071 int minor = getminor(dev) & TRAN_MINOR_MASK;
3071 3072 tran->tran_open_flag &= ~(1 << minor);
3072 3073 }
3073 3074 mutex_exit(&(tran->tran_open_lock));
3074 3075
3075 3076 ddi_release_devi(self);
3076 3077 return (0);
3077 3078 }
3078 3079
3079 3080 /*
3080 3081 * standard ioctl commands for SCSI hotplugging
3081 3082 */
3082 3083 /* ARGSUSED */
3083 3084 int
3084 3085 scsi_hba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
3085 3086 int *rvalp)
3086 3087 {
3087 3088 dev_info_t *self;
3088 3089 struct devctl_iocdata *dcp = NULL;
3089 3090 dev_info_t *child = NULL;
3090 3091 mdi_pathinfo_t *path = NULL;
3091 3092 struct scsi_device *sd;
3092 3093 scsi_hba_tran_t *tran;
|
↓ open down ↓ |
3059 lines elided |
↑ open up ↑ |
3093 3094 uint_t bus_state;
3094 3095 int rv = 0;
3095 3096 int circ;
3096 3097 char *name;
3097 3098 char *addr;
3098 3099
3099 3100 self = e_ddi_hold_devi_by_dev(dev, 0);
3100 3101 if (self == NULL) {
3101 3102 rv = ENXIO;
3102 3103 goto out;
3104 + }
3105 +
3106 + if (DEVI(self)->devi_flags & (DEVI_RETIRED | DEVI_RETIRING)) {
3107 + rv = ENXIO;
3108 + goto out;
3103 3109 }
3104 3110
3105 3111 tran = ddi_get_driver_private(self);
3106 3112 if (tran == NULL) {
3107 3113 rv = ENXIO;
3108 3114 goto out;
3109 3115 }
3110 3116
3111 3117 /* Ioctls for which the generic implementation suffices. */
3112 3118 switch (cmd) {
3113 3119 case DEVCTL_BUS_GETSTATE:
3114 3120 rv = ndi_devctl_ioctl(self, cmd, arg, mode, 0);
3115 3121 goto out;
3116 3122 }
3117 3123
3118 3124 /* read devctl ioctl data */
3119 3125 if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) {
3120 3126 rv = EFAULT;
3121 3127 goto out;
3122 3128 }
3123 3129
3124 3130 /* Ioctls that require child identification */
3125 3131 switch (cmd) {
3126 3132 case DEVCTL_DEVICE_GETSTATE:
3127 3133 case DEVCTL_DEVICE_ONLINE:
3128 3134 case DEVCTL_DEVICE_OFFLINE:
3129 3135 case DEVCTL_DEVICE_REMOVE:
3130 3136 case DEVCTL_DEVICE_RESET:
3131 3137 name = ndi_dc_getname(dcp);
3132 3138 addr = ndi_dc_getaddr(dcp);
3133 3139 if ((name == NULL) || (addr == NULL)) {
3134 3140 rv = EINVAL;
3135 3141 goto out;
3136 3142 }
3137 3143
3138 3144 /*
3139 3145 * Find child with name@addr - might find a devinfo
3140 3146 * child (child), a pathinfo child (path), or nothing.
3141 3147 */
3142 3148 scsi_hba_devi_enter(self, &circ);
3143 3149
3144 3150 (void) scsi_findchild(self, name, addr, 1, &child, &path, NULL);
3145 3151 if (path) {
3146 3152 /* Found a pathinfo */
3147 3153 ASSERT(path && (child == NULL));
3148 3154 mdi_hold_path(path);
3149 3155 scsi_hba_devi_exit_phci(self, circ);
3150 3156 sd = NULL;
3151 3157 } else if (child) {
3152 3158 /* Found a devinfo */
3153 3159 ASSERT(child && (path == NULL));
3154 3160
3155 3161 /* verify scsi_device of child */
3156 3162 if (ndi_flavor_get(child) == SCSA_FLAVOR_SCSI_DEVICE)
3157 3163 sd = ddi_get_driver_private(child);
3158 3164 else
3159 3165 sd = NULL;
3160 3166 } else {
3161 3167 ASSERT((path == NULL) && (child == NULL));
3162 3168 scsi_hba_devi_exit(self, circ);
3163 3169 rv = ENXIO; /* found nothing */
3164 3170 goto out;
3165 3171 }
3166 3172 break;
3167 3173
3168 3174 case DEVCTL_BUS_RESETALL: /* ioctl that operate on any child */
3169 3175 /*
3170 3176 * Find a child's scsi_address so we can invoke tran_reset.
3171 3177 *
3172 3178 * Future: If no child exists, we could fake a child. This will
3173 3179 * be a enhancement for the future - for now, we fall back to
3174 3180 * BUS_RESET.
3175 3181 */
3176 3182 scsi_hba_devi_enter(self, &circ);
3177 3183 child = ddi_get_child(self);
3178 3184 sd = NULL;
3179 3185 while (child) {
3180 3186 /* verify scsi_device of child */
3181 3187 if (ndi_flavor_get(child) == SCSA_FLAVOR_SCSI_DEVICE)
3182 3188 sd = ddi_get_driver_private(child);
3183 3189 if (sd != NULL) {
3184 3190 /*
3185 3191 * NOTE: node has a scsi_device structure, so
3186 3192 * it must be initialized.
3187 3193 */
3188 3194 ndi_hold_devi(child);
3189 3195 break;
3190 3196 }
3191 3197 child = ddi_get_next_sibling(child);
3192 3198 }
3193 3199 scsi_hba_devi_exit(self, circ);
3194 3200 break;
3195 3201 }
3196 3202
3197 3203 switch (cmd) {
3198 3204 case DEVCTL_DEVICE_GETSTATE:
3199 3205 if (path) {
3200 3206 if (mdi_dc_return_dev_state(path, dcp) != MDI_SUCCESS)
3201 3207 rv = EFAULT;
3202 3208 } else if (child) {
3203 3209 if (ndi_dc_return_dev_state(child, dcp) != NDI_SUCCESS)
3204 3210 rv = EFAULT;
3205 3211 } else {
3206 3212 rv = ENXIO;
3207 3213 }
3208 3214 break;
3209 3215
3210 3216 case DEVCTL_DEVICE_RESET:
3211 3217 if (sd == NULL) {
3212 3218 rv = ENOTTY;
3213 3219 break;
3214 3220 }
3215 3221 if (tran->tran_reset == NULL) {
3216 3222 rv = ENOTSUP;
3217 3223 break;
3218 3224 }
3219 3225
3220 3226 /* Start with the small stick */
3221 3227 if (scsi_reset(&sd->sd_address, RESET_LUN) == 1)
3222 3228 break; /* LUN reset worked */
3223 3229 if (scsi_reset(&sd->sd_address, RESET_TARGET) != 1)
3224 3230 rv = EIO; /* Target reset failed */
3225 3231 break;
3226 3232
3227 3233 case DEVCTL_BUS_QUIESCE:
3228 3234 if ((ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) &&
3229 3235 (bus_state == BUS_QUIESCED))
3230 3236 rv = EALREADY;
3231 3237 else if (tran->tran_quiesce == NULL)
3232 3238 rv = ENOTSUP; /* man ioctl(7I) says ENOTTY */
3233 3239 else if (tran->tran_quiesce(self) != 0)
3234 3240 rv = EIO;
3235 3241 else if (ndi_set_bus_state(self, BUS_QUIESCED) != NDI_SUCCESS)
3236 3242 rv = EIO;
3237 3243 break;
3238 3244
3239 3245 case DEVCTL_BUS_UNQUIESCE:
3240 3246 if ((ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) &&
3241 3247 (bus_state == BUS_ACTIVE))
3242 3248 rv = EALREADY;
3243 3249 else if (tran->tran_unquiesce == NULL)
3244 3250 rv = ENOTSUP; /* man ioctl(7I) says ENOTTY */
3245 3251 else if (tran->tran_unquiesce(self) != 0)
3246 3252 rv = EIO;
3247 3253 else if (ndi_set_bus_state(self, BUS_ACTIVE) != NDI_SUCCESS)
3248 3254 rv = EIO;
3249 3255 break;
3250 3256
3251 3257 case DEVCTL_BUS_RESET:
3252 3258 if (tran->tran_bus_reset == NULL)
3253 3259 rv = ENOTSUP; /* man ioctl(7I) says ENOTTY */
3254 3260 else if (tran->tran_bus_reset(self, RESET_BUS) != 1)
3255 3261 rv = EIO;
3256 3262 break;
3257 3263
3258 3264 case DEVCTL_BUS_RESETALL:
3259 3265 if ((sd != NULL) &&
3260 3266 (scsi_reset(&sd->sd_address, RESET_ALL) == 1)) {
3261 3267 break; /* reset all worked */
3262 3268 }
3263 3269 if (tran->tran_bus_reset == NULL) {
3264 3270 rv = ENOTSUP; /* man ioctl(7I) says ENOTTY */
3265 3271 break;
3266 3272 }
3267 3273 if (tran->tran_bus_reset(self, RESET_BUS) != 1)
3268 3274 rv = EIO; /* bus reset failed */
3269 3275 break;
3270 3276
3271 3277 case DEVCTL_BUS_CONFIGURE:
3272 3278 if (ndi_devi_config(self, NDI_DEVFS_CLEAN | NDI_DEVI_PERSIST |
3273 3279 NDI_CONFIG_REPROBE) != NDI_SUCCESS) {
3274 3280 rv = EIO;
3275 3281 }
3276 3282 break;
3277 3283
3278 3284 case DEVCTL_BUS_UNCONFIGURE:
3279 3285 if (ndi_devi_unconfig(self,
3280 3286 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) != NDI_SUCCESS) {
3281 3287 rv = EBUSY;
3282 3288 }
3283 3289 break;
3284 3290
3285 3291 case DEVCTL_DEVICE_ONLINE:
3286 3292 ASSERT(child || path);
3287 3293 if (path) {
3288 3294 if (mdi_pi_online(path, NDI_USER_REQ) != MDI_SUCCESS)
3289 3295 rv = EIO;
3290 3296 } else {
3291 3297 if (ndi_devi_online(child, 0) != NDI_SUCCESS)
3292 3298 rv = EIO;
3293 3299 }
3294 3300 break;
3295 3301
3296 3302 case DEVCTL_DEVICE_OFFLINE:
3297 3303 ASSERT(child || path);
3298 3304 if (sd != NULL)
3299 3305 (void) scsi_clear_task_set(&sd->sd_address);
3300 3306 if (path) {
3301 3307 if (mdi_pi_offline(path, NDI_USER_REQ) != MDI_SUCCESS)
3302 3308 rv = EIO;
3303 3309 } else {
3304 3310 if (ndi_devi_offline(child,
3305 3311 NDI_DEVFS_CLEAN) != NDI_SUCCESS)
3306 3312 rv = EIO;
3307 3313 }
3308 3314 break;
3309 3315
3310 3316 case DEVCTL_DEVICE_REMOVE:
3311 3317 ASSERT(child || path);
3312 3318 if (sd != NULL)
3313 3319 (void) scsi_clear_task_set(&sd->sd_address);
3314 3320 if (path) {
3315 3321 /* NOTE: don't pass NDI_DEVI_REMOVE to mdi_pi_offline */
3316 3322 if (mdi_pi_offline(path, NDI_USER_REQ) == MDI_SUCCESS) {
3317 3323 scsi_hba_devi_enter_phci(self, &circ);
3318 3324 mdi_rele_path(path);
3319 3325
3320 3326 /* ... here is the DEVICE_REMOVE part. */
3321 3327 (void) mdi_pi_free(path, 0);
3322 3328 path = NULL;
3323 3329 } else {
3324 3330 rv = EIO;
3325 3331 }
3326 3332 } else {
3327 3333 if (ndi_devi_offline(child,
3328 3334 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) != NDI_SUCCESS)
3329 3335 rv = EIO;
3330 3336 }
3331 3337 break;
3332 3338
3333 3339 default:
3334 3340 ASSERT(dcp != NULL);
3335 3341 rv = ENOTTY;
3336 3342 break;
3337 3343 }
3338 3344
3339 3345 /* all done -- clean up and return */
3340 3346 out:
3341 3347 /* release hold on what we found */
3342 3348 if (path) {
3343 3349 scsi_hba_devi_enter_phci(self, &circ);
3344 3350 mdi_rele_path(path);
3345 3351 }
3346 3352 if (path || child)
3347 3353 scsi_hba_devi_exit(self, circ);
3348 3354
3349 3355 if (dcp)
3350 3356 ndi_dc_freehdl(dcp);
3351 3357
3352 3358 if (self)
3353 3359 ddi_release_devi(self);
3354 3360
3355 3361 *rvalp = rv;
3356 3362
3357 3363 return (rv);
3358 3364 }
3359 3365
3360 3366 /*ARGSUSED*/
3361 3367 static int
3362 3368 scsi_hba_fm_init_child(dev_info_t *self, dev_info_t *child, int cap,
3363 3369 ddi_iblock_cookie_t *ibc)
3364 3370 {
3365 3371 scsi_hba_tran_t *tran = ddi_get_driver_private(self);
3366 3372
3367 3373 return (tran ? tran->tran_fm_capable : scsi_fm_capable);
3368 3374 }
3369 3375
3370 3376 static int
3371 3377 scsi_hba_bus_power(dev_info_t *self, void *impl_arg, pm_bus_power_op_t op,
3372 3378 void *arg, void *result)
3373 3379 {
3374 3380 scsi_hba_tran_t *tran;
3375 3381
3376 3382 tran = ddi_get_driver_private(self);
3377 3383 if (tran && tran->tran_bus_power) {
3378 3384 return (tran->tran_bus_power(self, impl_arg,
3379 3385 op, arg, result));
3380 3386 }
3381 3387
3382 3388 return (pm_busop_bus_power(self, impl_arg, op, arg, result));
3383 3389 }
3384 3390
3385 3391 /*
3386 3392 * Return the lun64 value from a address string: "addr,lun[,sfunc]". Either
3387 3393 * the lun is after the first ',' or the entire address string is the lun.
3388 3394 * Return SCSI_LUN64_ILLEGAL if the format is incorrect. A lun64 is at most
3389 3395 * 16 hex digits long.
3390 3396 *
3391 3397 * If the address string specified has incorrect syntax (busconfig one of
3392 3398 * bogus /devices path) then scsi_addr_to_lun64 can return SCSI_LUN64_ILLEGAL.
3393 3399 */
3394 3400 static scsi_lun64_t
3395 3401 scsi_addr_to_lun64(char *addr)
3396 3402 {
3397 3403 scsi_lun64_t lun64;
3398 3404 char *s;
3399 3405 int i;
3400 3406
3401 3407 if (addr) {
3402 3408 s = strchr(addr, ','); /* "addr,lun" */
3403 3409 if (s)
3404 3410 s++; /* skip ',', at lun */
3405 3411 else
3406 3412 s = addr; /* "lun" */
3407 3413
3408 3414 for (lun64 = 0, i = 0; *s && (i < 16); s++, i++) {
3409 3415 if (*s >= '0' && *s <= '9')
3410 3416 lun64 = (lun64 << 4) + (*s - '0');
3411 3417 else if (*s >= 'A' && *s <= 'F')
3412 3418 lun64 = (lun64 << 4) + 10 + (*s - 'A');
3413 3419 else if (*s >= 'a' && *s <= 'f')
3414 3420 lun64 = (lun64 << 4) + 10 + (*s - 'a');
3415 3421 else
3416 3422 break;
3417 3423 }
3418 3424 if (*s && (*s != ',')) /* [,sfunc] is OK */
3419 3425 lun64 = SCSI_LUN64_ILLEGAL;
3420 3426 } else
3421 3427 lun64 = SCSI_LUN64_ILLEGAL;
3422 3428
3423 3429 if (lun64 == SCSI_LUN64_ILLEGAL)
3424 3430 SCSI_HBA_LOG((_LOG(2), NULL, NULL,
3425 3431 "addr_to_lun64 %s lun %" PRIlun64,
3426 3432 addr ? addr : "NULL", lun64));
3427 3433 return (lun64);
3428 3434 }
3429 3435
3430 3436 /*
3431 3437 * Return the sfunc value from a address string: "addr,lun[,sfunc]". Either the
3432 3438 * sfunc is after the second ',' or the entire address string is the sfunc.
3433 3439 * Return -1 if there is only one ',' in the address string or the string is
3434 3440 * invalid. An sfunc is at most two hex digits long.
3435 3441 */
3436 3442 static int
3437 3443 scsi_addr_to_sfunc(char *addr)
3438 3444 {
3439 3445 int sfunc;
3440 3446 char *s;
3441 3447 int i;
3442 3448
3443 3449 if (addr) {
3444 3450 s = strchr(addr, ','); /* "addr,lun" */
3445 3451 if (s) {
3446 3452 s++; /* skip ',', at lun */
3447 3453 s = strchr(s, ','); /* "lun,sfunc" */
3448 3454 if (s == NULL)
3449 3455 return (-1); /* no ",sfunc" */
3450 3456 s++; /* skip ',', at sfunc */
3451 3457 } else
3452 3458 s = addr; /* "sfunc" */
3453 3459
3454 3460 for (sfunc = 0, i = 0; *s && (i < 2); s++, i++) {
3455 3461 if (*s >= '0' && *s <= '9')
3456 3462 sfunc = (sfunc << 4) + (*s - '0');
3457 3463 else if (*s >= 'A' && *s <= 'F')
3458 3464 sfunc = (sfunc << 4) + 10 + (*s - 'A');
3459 3465 else if (*s >= 'a' && *s <= 'f')
3460 3466 sfunc = (sfunc << 4) + 10 + (*s - 'a');
3461 3467 else
3462 3468 break;
3463 3469 }
3464 3470 if (*s)
3465 3471 sfunc = -1; /* illegal */
3466 3472 } else
3467 3473 sfunc = -1;
3468 3474 return (sfunc);
3469 3475 }
3470 3476
3471 3477 /*
3472 3478 * Convert scsi ascii string data to NULL terminated (semi) legal IEEE 1275
3473 3479 * "compatible" (name) property form.
3474 3480 *
3475 3481 * For ASCII INQUIRY data, a one-way conversion algorithm is needed to take
3476 3482 * SCSI_ASCII (20h - 7Eh) to a 1275-like compatible form. The 1275 spec allows
3477 3483 * letters, digits, one ",", and ". _ + -", all limited by a maximum 31
3478 3484 * character length. Since ", ." are used as separators in the compatible
3479 3485 * string itself, they are converted to "_". All SCSI_ASCII characters that
3480 3486 * are illegal in 1275, as well as any illegal SCSI_ASCII characters
3481 3487 * encountered, are converted to "_". To reduce length, trailing blanks are
3482 3488 * trimmed from SCSI_ASCII fields prior to conversion.
3483 3489 *
3484 3490 * Example: SCSI_ASCII "ST32550W SUN2.1G" -> "ST32550W_SUN2_1G"
3485 3491 *
3486 3492 * NOTE: the 1275 string form is always less than or equal to the scsi form.
3487 3493 */
3488 3494 static char *
3489 3495 string_scsi_to_1275(char *s_1275, char *s_scsi, int len)
3490 3496 {
3491 3497 (void) strncpy(s_1275, s_scsi, len);
3492 3498 s_1275[len--] = '\0';
3493 3499
3494 3500 while (len >= 0) {
3495 3501 if (s_1275[len] == ' ')
3496 3502 s_1275[len--] = '\0'; /* trim trailing " " */
3497 3503 else
3498 3504 break;
3499 3505 }
3500 3506
3501 3507 while (len >= 0) {
3502 3508 if (((s_1275[len] >= 'a') && (s_1275[len] <= 'z')) ||
3503 3509 ((s_1275[len] >= 'A') && (s_1275[len] <= 'Z')) ||
3504 3510 ((s_1275[len] >= '0') && (s_1275[len] <= '9')) ||
3505 3511 (s_1275[len] == '_') ||
3506 3512 (s_1275[len] == '+') ||
3507 3513 (s_1275[len] == '-'))
3508 3514 len--; /* legal 1275 */
3509 3515 else
3510 3516 s_1275[len--] = '_'; /* illegal SCSI_ASCII | 1275 */
3511 3517 }
3512 3518
3513 3519 return (s_1275);
3514 3520 }
3515 3521
3516 3522 /*
3517 3523 * Given the inquiry data, binding_set, and dtype_node for a scsi device,
3518 3524 * return the nodename and compatible property for the device. The "compatible"
3519 3525 * concept comes from IEEE-1275. The compatible information is returned is in
3520 3526 * the correct form for direct use defining the "compatible" string array
3521 3527 * property. Internally, "compatible" is also used to determine the nodename
3522 3528 * to return.
3523 3529 *
3524 3530 * This function is provided as a separate entry point for use by drivers that
3525 3531 * currently issue their own non-SCSA inquiry command and perform their own
3526 3532 * node creation based their own private compiled in tables. Converting these
3527 3533 * drivers to use this interface provides a quick easy way of obtaining
3528 3534 * consistency as well as the flexibility associated with the 1275 techniques.
3529 3535 *
3530 3536 * The dtype_node is passed as a separate argument (instead of having the
3531 3537 * implementation use inq_dtype). It indicates that information about
3532 3538 * a secondary function embedded service should be produced.
3533 3539 *
3534 3540 * Callers must always use scsi_hba_nodename_compatible_free, even if
3535 3541 * *nodenamep is null, to free the nodename and compatible information
3536 3542 * when done.
3537 3543 *
3538 3544 * If a nodename can't be determined then **compatiblep will point to a
3539 3545 * diagnostic string containing all the compatible forms.
3540 3546 *
3541 3547 * NOTE: some compatible strings may violate the 31 character restriction
3542 3548 * imposed by IEEE-1275. This is not a problem because Solaris does not care
3543 3549 * about this 31 character limit.
3544 3550 *
3545 3551 * Each compatible form belongs to a form-group. The form-groups currently
3546 3552 * defined are generic ("scsiclass"), binding-set ("scsa.b"), and failover
3547 3553 * ("scsa.f").
3548 3554 *
3549 3555 * The following compatible forms, in high to low precedence
3550 3556 * order, are defined for SCSI target device nodes.
3551 3557 *
3552 3558 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (1 *1&2)
3553 3559 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (2 *1)
3554 3560 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (3 *2)
3555 3561 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (4)
3556 3562 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (5 *1&2)
3557 3563 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP (6 *1)
3558 3564 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (7 *2)
3559 3565 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP (8)
3560 3566 * scsa,DD.bBBBBBBBB (8.5 *3)
3561 3567 * scsiclass,DDEEFFF (9 *1&2)
3562 3568 * scsiclass,DDEE (10 *1)
3563 3569 * scsiclass,DDFFF (11 *2)
3564 3570 * scsiclass,DD (12)
3565 3571 * scsa.fFFF (12.5 *4)
3566 3572 * scsiclass (13)
3567 3573 *
3568 3574 * *1 only produced on a secondary function node
3569 3575 * *2 only produced when generic form-group flags exist.
3570 3576 * *3 only produced when binding-set form-group legacy support is needed
3571 3577 * *4 only produced when failover form-group flags exist.
3572 3578 *
3573 3579 * where:
3574 3580 *
3575 3581 * v is the letter 'v'. Denotest the
3576 3582 * beginning of VVVVVVVV.
3577 3583 *
3578 3584 * VVVVVVVV Translated scsi_vendor.
3579 3585 *
3580 3586 * p is the letter 'p'. Denotes the
3581 3587 * beginning of PPPPPPPPPPPPPPPP.
3582 3588 *
3583 3589 * PPPPPPPPPPPPPPPP Translated scsi_product.
3584 3590 *
3585 3591 * r is the letter 'r'. Denotes the
3586 3592 * beginning of RRRR.
3587 3593 *
3588 3594 * RRRR Translated scsi_revision.
3589 3595 *
3590 3596 * DD is a two digit ASCII hexadecimal
3591 3597 * number. The value of the two digits is
3592 3598 * based one the SCSI "Peripheral device
3593 3599 * type" command set associated with the
3594 3600 * node. On a primary node this is the
3595 3601 * scsi_dtype of the primary command set,
3596 3602 * on a secondary node this is the
3597 3603 * scsi_dtype associated with the secondary
3598 3604 * function embedded command set.
3599 3605 *
3600 3606 * EE Same encoding used for DD. This form is
3601 3607 * only generated on secondary function
3602 3608 * nodes. The DD secondary function is embedded
3603 3609 * in an EE device.
3604 3610 *
3605 3611 * FFF Concatenation, in alphabetical order,
3606 3612 * of the flag characters within a form-group.
3607 3613 * For a given form-group, the following
3608 3614 * flags are defined.
3609 3615 *
3610 3616 * scsiclass: (generic form-group):
3611 3617 * R Removable_Media: Used when
3612 3618 * inq_rmb is set.
3613 3619 * S SAF-TE device: Used when
3614 3620 * inquiry information indicates
3615 3621 * SAF-TE devices.
3616 3622 *
3617 3623 * scsa.f: (failover form-group):
3618 3624 * E Explicit Target_Port_Group: Used
3619 3625 * when inq_tpgse is set and 'G' is
3620 3626 * alse present.
3621 3627 * G GUID: Used when a GUID can be
3622 3628 * generated for the device.
3623 3629 * I Implicit Target_Port_Group: Used
3624 3630 * when inq_tpgs is set and 'G' is
3625 3631 * also present.
3626 3632 *
3627 3633 * Forms using FFF are only be generated
3628 3634 * if there are applicable flag
3629 3635 * characters.
3630 3636 *
3631 3637 * b is the letter 'b'. Denotes the
3632 3638 * beginning of BBBBBBBB.
3633 3639 *
3634 3640 * BBBBBBBB Binding-set. Operating System Specific:
3635 3641 * scsi-binding-set property of HBA.
3636 3642 */
3637 3643 #define NCOMPAT (1 + (13 + 2) + 1)
3638 3644 #define COMPAT_LONGEST (strlen( \
3639 3645 "scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR" + 1))
3640 3646
3641 3647 /*
3642 3648 * Private version with extra device 'identity' arguments to allow code
3643 3649 * to determine GUID FFF support.
3644 3650 */
3645 3651 static void
3646 3652 scsi_hba_ident_nodename_compatible_get(struct scsi_inquiry *inq,
3647 3653 uchar_t *inq80, size_t inq80len, uchar_t *inq83, size_t inq83len,
3648 3654 char *binding_set, int dtype_node, char *compat0,
3649 3655 char **nodenamep, char **drivernamep,
3650 3656 char ***compatiblep, int *ncompatiblep)
3651 3657 {
3652 3658 char vid[sizeof (inq->inq_vid) + 1 ];
3653 3659 char pid[sizeof (inq->inq_pid) + 1];
3654 3660 char rev[sizeof (inq->inq_revision) + 1];
3655 3661 char gf[sizeof ("RS\0")];
3656 3662 char ff[sizeof ("EGI\0")];
3657 3663 int dtype_device;
3658 3664 int ncompat; /* number of compatible */
3659 3665 char **compatp; /* compatible ptrs */
3660 3666 int i;
3661 3667 char *nname; /* nodename */
3662 3668 char *dname; /* driver name */
3663 3669 char **csp;
3664 3670 char *p;
3665 3671 int tlen;
3666 3672 int len;
3667 3673 major_t major;
3668 3674 ddi_devid_t devid;
3669 3675 char *guid;
3670 3676 uchar_t *iqd = (uchar_t *)inq;
3671 3677
3672 3678 /*
3673 3679 * Nodename_aliases: This table was originally designed to be
3674 3680 * implemented via a new nodename_aliases file - a peer to the
3675 3681 * driver_aliases that selects a nodename based on compatible
3676 3682 * forms in much the same say driver_aliases is used to select
3677 3683 * driver bindings from compatible forms. Each compatible form
3678 3684 * is an 'alias'. Until a more general need for a
3679 3685 * nodename_aliases file exists, which may never occur, the
3680 3686 * scsi mappings are described here via a compiled in table.
3681 3687 *
3682 3688 * This table contains nodename mappings for self-identifying
3683 3689 * scsi devices enumerated by the Solaris kernel. For a given
3684 3690 * device, the highest precedence "compatible" form with a
3685 3691 * mapping is used to select the nodename for the device. This
3686 3692 * will typically be a generic nodename, however in some legacy
3687 3693 * compatibility cases a driver nodename mapping may be selected.
3688 3694 *
3689 3695 * Because of possible breakage associated with switching SCSI
3690 3696 * target devices from driver nodenames to generic nodenames,
3691 3697 * we are currently unable to support generic nodenames for all
3692 3698 * SCSI devices (binding-sets). Although /devices paths are
3693 3699 * defined as unstable, avoiding possible breakage is
3694 3700 * important. Some of the newer SCSI transports (USB) already
3695 3701 * use generic nodenames. All new SCSI transports and target
3696 3702 * devices should use generic nodenames. At times this decision
3697 3703 * may be architecture dependent (sparc .vs. intel) based on when
3698 3704 * a transport was supported on a particular architecture.
3699 3705 *
3700 3706 * We provide a base set of generic nodename mappings based on
3701 3707 * scsiclass dtype and higher-precedence driver nodename
3702 3708 * mappings based on scsa "binding-set" to cover legacy
3703 3709 * issues. The binding-set is typically associated with
3704 3710 * "scsi-binding-set" property value of the HBA. The legacy
3705 3711 * mappings are provided independent of whether the driver they
3706 3712 * refer to is installed. This allows a correctly named node
3707 3713 * be created at discovery time, and binding to occur when/if
3708 3714 * an add_drv of the legacy driver occurs.
3709 3715 *
3710 3716 * We also have mappings for legacy SUN hardware that
3711 3717 * misidentifies itself (enclosure services which identify
3712 3718 * themselves as processors). All future hardware should use
3713 3719 * the correct dtype.
3714 3720 *
3715 3721 * As SCSI HBAs are modified to use the SCSA interfaces for
3716 3722 * self-identifying SCSI target devices (PSARC/2004/116) the
3717 3723 * nodename_aliases table (PSARC/2004/420) should be augmented
3718 3724 * with legacy mappings in order to maintain compatibility with
3719 3725 * existing /devices paths, especially for devices that house
3720 3726 * an OS. Failure to do this may cause upgrade problems.
3721 3727 * Additions for new target devices or transports should not
3722 3728 * add scsa binding-set compatible mappings.
3723 3729 */
3724 3730 static struct nodename_aliases {
3725 3731 char *na_nodename; /* nodename */
3726 3732 char *na_alias; /* compatible form match */
3727 3733 } na[] = {
3728 3734 /* # mapping to generic nodenames based on scsi dtype */
3729 3735 {"disk", "scsiclass,00"},
3730 3736 {"tape", "scsiclass,01"},
3731 3737 {"printer", "scsiclass,02"},
3732 3738 {"processor", "scsiclass,03"},
3733 3739 {"worm", "scsiclass,04"},
3734 3740 {"cdrom", "scsiclass,05"},
3735 3741 {"scanner", "scsiclass,06"},
3736 3742 {"optical-disk", "scsiclass,07"},
3737 3743 {"medium-changer", "scsiclass,08"},
3738 3744 {"obsolete", "scsiclass,09"},
3739 3745 {"prepress-a", "scsiclass,0a"},
3740 3746 {"prepress-b", "scsiclass,0b"},
3741 3747 {"array-controller", "scsiclass,0c"},
3742 3748 {"enclosure", "scsiclass,0d"},
3743 3749 {"disk", "scsiclass,0e"},
3744 3750 {"card-reader", "scsiclass,0f"},
3745 3751 {"bridge", "scsiclass,10"},
3746 3752 {"object-store", "scsiclass,11"},
3747 3753 {"reserved", "scsiclass,12"},
3748 3754 {"reserved", "scsiclass,13"},
3749 3755 {"reserved", "scsiclass,14"},
3750 3756 {"reserved", "scsiclass,15"},
3751 3757 {"reserved", "scsiclass,16"},
3752 3758 {"reserved", "scsiclass,17"},
3753 3759 {"reserved", "scsiclass,18"},
3754 3760 {"reserved", "scsiclass,19"},
3755 3761 {"reserved", "scsiclass,1a"},
3756 3762 {"reserved", "scsiclass,1b"},
3757 3763 {"reserved", "scsiclass,1c"},
3758 3764 {"reserved", "scsiclass,1d"},
3759 3765 {"well-known-lun", "scsiclass,1e"},
3760 3766 {"unknown", "scsiclass,1f"},
3761 3767
3762 3768 #ifdef sparc
3763 3769 /* # legacy mapping to driver nodenames for fcp binding-set */
3764 3770 {"ssd", "scsa,00.bfcp"},
3765 3771 {"st", "scsa,01.bfcp"},
3766 3772 {"sgen", "scsa,08.bfcp"},
3767 3773 {"ses", "scsa,0d.bfcp"},
3768 3774
3769 3775 /* # legacy mapping to driver nodenames for vhci binding-set */
3770 3776 {"ssd", "scsa,00.bvhci"},
3771 3777 {"st", "scsa,01.bvhci"},
3772 3778 {"sgen", "scsa,08.bvhci"},
3773 3779 {"ses", "scsa,0d.bvhci"},
3774 3780 #else /* sparc */
3775 3781 /* # for x86 fcp and vhci use generic nodenames */
3776 3782 #endif /* sparc */
3777 3783
3778 3784 /* # legacy mapping to driver nodenames for spi binding-set */
3779 3785 {"sd", "scsa,00.bspi"},
3780 3786 {"sd", "scsa,05.bspi"},
3781 3787 {"sd", "scsa,07.bspi"},
3782 3788 {"st", "scsa,01.bspi"},
3783 3789 {"ses", "scsa,0d.bspi"},
3784 3790
3785 3791 /* # SUN misidentified spi hardware */
3786 3792 {"ses", "scsiclass,03.vSUN.pD2"},
3787 3793 {"ses", "scsiclass,03.vSYMBIOS.pD1000"},
3788 3794
3789 3795 /* # legacy mapping to driver nodenames for atapi binding-set */
3790 3796 {"sd", "scsa,00.batapi"},
3791 3797 {"sd", "scsa,05.batapi"},
3792 3798 {"sd", "scsa,07.batapi"},
3793 3799 {"st", "scsa,01.batapi"},
3794 3800 {"unknown", "scsa,0d.batapi"},
3795 3801
3796 3802 /* # legacy mapping to generic nodenames for usb binding-set */
3797 3803 {"disk", "scsa,05.busb"},
3798 3804 {"disk", "scsa,07.busb"},
3799 3805 {"changer", "scsa,08.busb"},
3800 3806 {"comm", "scsa,09.busb"},
3801 3807 {"array_ctlr", "scsa,0c.busb"},
3802 3808 {"esi", "scsa,0d.busb"},
3803 3809
3804 3810 /*
3805 3811 * mapping nodenames for mpt based on scsi dtype
3806 3812 * for being compatible with the original node names
3807 3813 * under mpt controller
3808 3814 */
3809 3815 {"sd", "scsa,00.bmpt"},
3810 3816 {"sd", "scsa,05.bmpt"},
3811 3817 {"sd", "scsa,07.bmpt"},
3812 3818 {"st", "scsa,01.bmpt"},
3813 3819 {"ses", "scsa,0d.bmpt"},
3814 3820 {"sgen", "scsa,08.bmpt"},
3815 3821 {NULL, NULL}
3816 3822 };
3817 3823 struct nodename_aliases *nap;
3818 3824
3819 3825 /* NOTE: drivernamep can be NULL */
3820 3826 ASSERT(nodenamep && compatiblep && ncompatiblep &&
3821 3827 (binding_set == NULL || (strlen(binding_set) <= 8)));
3822 3828 if ((nodenamep == NULL) || (compatiblep == NULL) ||
3823 3829 (ncompatiblep == NULL))
3824 3830 return;
3825 3831
3826 3832 /*
3827 3833 * In order to reduce runtime we allocate one block of memory that
3828 3834 * contains both the NULL terminated array of pointers to compatible
3829 3835 * forms and the individual compatible strings. This block is
3830 3836 * somewhat larger than needed, but is short lived - it only exists
3831 3837 * until the caller can transfer the information into the "compatible"
3832 3838 * string array property and call scsi_hba_nodename_compatible_free.
3833 3839 */
3834 3840 tlen = NCOMPAT * COMPAT_LONGEST;
3835 3841 compatp = kmem_alloc((NCOMPAT * sizeof (char *)) + tlen, KM_SLEEP);
3836 3842
3837 3843 /* convert inquiry data from SCSI ASCII to 1275 string */
3838 3844 (void) string_scsi_to_1275(vid, inq->inq_vid,
3839 3845 sizeof (inq->inq_vid));
3840 3846 (void) string_scsi_to_1275(pid, inq->inq_pid,
3841 3847 sizeof (inq->inq_pid));
3842 3848 (void) string_scsi_to_1275(rev, inq->inq_revision,
3843 3849 sizeof (inq->inq_revision));
3844 3850 ASSERT((strlen(vid) <= sizeof (inq->inq_vid)) &&
3845 3851 (strlen(pid) <= sizeof (inq->inq_pid)) &&
3846 3852 (strlen(rev) <= sizeof (inq->inq_revision)));
3847 3853
3848 3854 /*
3849 3855 * Form flags in ***ALPHABETICAL*** order within form-group:
3850 3856 *
3851 3857 * NOTE: When adding a new flag to an existing form-group, careful
3852 3858 * consideration must be given to not breaking existing bindings
3853 3859 * based on that form-group.
3854 3860 */
3855 3861
3856 3862 /*
3857 3863 * generic form-group flags
3858 3864 * R removable:
3859 3865 * Set when inq_rmb is set and for well known scsi dtypes. For a
3860 3866 * bus where the entire device is removable (like USB), we expect
3861 3867 * the HBA to intercept the inquiry data and set inq_rmb.
3862 3868 * Since OBP does not distinguish removable media in its generic
3863 3869 * name selection we avoid setting the 'R' flag if the root is not
3864 3870 * yet mounted.
3865 3871 * S SAF-TE device
3866 3872 * Set when the device type is SAT-TE.
3867 3873 */
3868 3874 i = 0;
3869 3875 dtype_device = inq->inq_dtype & DTYPE_MASK;
3870 3876 if (modrootloaded && (inq->inq_rmb ||
3871 3877 (dtype_device == DTYPE_WORM) ||
3872 3878 (dtype_device == DTYPE_RODIRECT) ||
3873 3879 (dtype_device == DTYPE_OPTICAL)))
3874 3880 gf[i++] = 'R'; /* removable */
3875 3881 gf[i] = '\0';
3876 3882
3877 3883 if (modrootloaded &&
3878 3884 (dtype_device == DTYPE_PROCESSOR) &&
3879 3885 (strncmp((char *)&iqd[44], "SAF-TE", 4) == 0))
3880 3886 gf[i++] = 'S';
3881 3887 gf[i] = '\0';
3882 3888
3883 3889 /*
3884 3890 * failover form-group flags
3885 3891 * E Explicit Target_Port_Group_Supported:
3886 3892 * Set for a device that has a GUID if inq_tpgse also set.
3887 3893 * G GUID:
3888 3894 * Set when we have identity information, can determine a devid
3889 3895 * from the identity information, and can generate a guid from
3890 3896 * that devid.
3891 3897 * I Implicit Target_Port_Group_Supported:
3892 3898 * Set for a device that has a GUID if inq_tpgs also set.
3893 3899 */
3894 3900 i = 0;
3895 3901 if ((inq80 || inq83) &&
3896 3902 (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST, NULL,
3897 3903 (uchar_t *)inq, sizeof (*inq), inq80, inq80len, inq83, inq83len,
3898 3904 &devid) == DDI_SUCCESS)) {
3899 3905 guid = ddi_devid_to_guid(devid);
3900 3906 ddi_devid_free(devid);
3901 3907 } else
3902 3908 guid = NULL;
3903 3909 if (guid && (inq->inq_tpgs & TPGS_FAILOVER_EXPLICIT))
3904 3910 ff[i++] = 'E'; /* EXPLICIT TPGS */
3905 3911 if (guid)
3906 3912 ff[i++] = 'G'; /* GUID */
3907 3913 if (guid && (inq->inq_tpgs & TPGS_FAILOVER_IMPLICIT))
3908 3914 ff[i++] = 'I'; /* IMPLICIT TPGS */
3909 3915 ff[i] = '\0';
3910 3916 if (guid)
3911 3917 ddi_devid_free_guid(guid);
3912 3918
3913 3919 /*
3914 3920 * Construct all applicable compatible forms. See comment at the
3915 3921 * head of the function for a description of the compatible forms.
3916 3922 */
3917 3923 csp = compatp;
3918 3924 p = (char *)(compatp + NCOMPAT);
3919 3925
3920 3926 /* ( 0) driver (optional, not documented in scsi(4)) */
3921 3927 if (compat0) {
3922 3928 *csp++ = p;
3923 3929 (void) snprintf(p, tlen, "%s", compat0);
3924 3930 len = strlen(p) + 1;
3925 3931 p += len;
3926 3932 tlen -= len;
3927 3933 }
3928 3934
3929 3935 /* ( 1) scsiclass,DDEEFFF.vV.pP.rR */
3930 3936 if ((dtype_device != dtype_node) && *gf && *vid && *pid && *rev) {
3931 3937 *csp++ = p;
3932 3938 (void) snprintf(p, tlen, "scsiclass,%02x%02x%s.v%s.p%s.r%s",
3933 3939 dtype_node, dtype_device, gf, vid, pid, rev);
3934 3940 len = strlen(p) + 1;
3935 3941 p += len;
3936 3942 tlen -= len;
3937 3943 }
3938 3944
3939 3945 /* ( 2) scsiclass,DDEE.vV.pP.rR */
3940 3946 if ((dtype_device != dtype_node) && *vid && *pid && *rev) {
3941 3947 *csp++ = p;
3942 3948 (void) snprintf(p, tlen, "scsiclass,%02x%02x.v%s.p%s.r%s",
3943 3949 dtype_node, dtype_device, vid, pid, rev);
3944 3950 len = strlen(p) + 1;
3945 3951 p += len;
3946 3952 tlen -= len;
3947 3953 }
3948 3954
3949 3955 /* ( 3) scsiclass,DDFFF.vV.pP.rR */
3950 3956 if (*gf && *vid && *pid && *rev) {
3951 3957 *csp++ = p;
3952 3958 (void) snprintf(p, tlen, "scsiclass,%02x%s.v%s.p%s.r%s",
3953 3959 dtype_node, gf, vid, pid, rev);
3954 3960 len = strlen(p) + 1;
3955 3961 p += len;
3956 3962 tlen -= len;
3957 3963 }
3958 3964
3959 3965 /* ( 4) scsiclass,DD.vV.pP.rR */
3960 3966 if (*vid && *pid && *rev) {
3961 3967 *csp++ = p;
3962 3968 (void) snprintf(p, tlen, "scsiclass,%02x.v%s.p%s.r%s",
3963 3969 dtype_node, vid, pid, rev);
3964 3970 len = strlen(p) + 1;
3965 3971 p += len;
3966 3972 tlen -= len;
3967 3973 }
3968 3974
3969 3975 /* ( 5) scsiclass,DDEEFFF.vV.pP */
3970 3976 if ((dtype_device != dtype_node) && *gf && *vid && *pid) {
3971 3977 *csp++ = p;
3972 3978 (void) snprintf(p, tlen, "scsiclass,%02x%02x%s.v%s.p%s",
3973 3979 dtype_node, dtype_device, gf, vid, pid);
3974 3980 len = strlen(p) + 1;
3975 3981 p += len;
3976 3982 tlen -= len;
3977 3983 }
3978 3984
3979 3985 /* ( 6) scsiclass,DDEE.vV.pP */
3980 3986 if ((dtype_device != dtype_node) && *vid && *pid) {
3981 3987 *csp++ = p;
3982 3988 (void) snprintf(p, tlen, "scsiclass,%02x%02x.v%s.p%s",
3983 3989 dtype_node, dtype_device, vid, pid);
3984 3990 len = strlen(p) + 1;
3985 3991 p += len;
3986 3992 tlen -= len;
3987 3993 }
3988 3994
3989 3995 /* ( 7) scsiclass,DDFFF.vV.pP */
3990 3996 if (*gf && *vid && *pid) {
3991 3997 *csp++ = p;
3992 3998 (void) snprintf(p, tlen, "scsiclass,%02x%s.v%s.p%s",
3993 3999 dtype_node, gf, vid, pid);
3994 4000 len = strlen(p) + 1;
3995 4001 p += len;
3996 4002 tlen -= len;
3997 4003 }
3998 4004
3999 4005 /* ( 8) scsiclass,DD.vV.pP */
4000 4006 if (*vid && *pid) {
4001 4007 *csp++ = p;
4002 4008 (void) snprintf(p, tlen, "scsiclass,%02x.v%s.p%s",
4003 4009 dtype_node, vid, pid);
4004 4010 len = strlen(p) + 1;
4005 4011 p += len;
4006 4012 tlen -= len;
4007 4013 }
4008 4014
4009 4015 /* (8.5) scsa,DD.bB (not documented in scsi(4)) */
4010 4016 if (binding_set) {
4011 4017 *csp++ = p;
4012 4018 (void) snprintf(p, tlen, "scsa,%02x.b%s",
4013 4019 dtype_node, binding_set);
4014 4020 len = strlen(p) + 1;
4015 4021 p += len;
4016 4022 tlen -= len;
4017 4023 }
4018 4024
4019 4025 /* ( 9) scsiclass,DDEEFFF */
4020 4026 if ((dtype_device != dtype_node) && *gf) {
4021 4027 *csp++ = p;
4022 4028 (void) snprintf(p, tlen, "scsiclass,%02x%02x%s",
4023 4029 dtype_node, dtype_device, gf);
4024 4030 len = strlen(p) + 1;
4025 4031 p += len;
4026 4032 tlen -= len;
4027 4033 }
4028 4034
4029 4035 /* (10) scsiclass,DDEE */
4030 4036 if (dtype_device != dtype_node) {
4031 4037 *csp++ = p;
4032 4038 (void) snprintf(p, tlen, "scsiclass,%02x%02x",
4033 4039 dtype_node, dtype_device);
4034 4040 len = strlen(p) + 1;
4035 4041 p += len;
4036 4042 tlen -= len;
4037 4043 }
4038 4044
4039 4045 /* (11) scsiclass,DDFFF */
4040 4046 if (*gf) {
4041 4047 *csp++ = p;
4042 4048 (void) snprintf(p, tlen, "scsiclass,%02x%s",
4043 4049 dtype_node, gf);
4044 4050 len = strlen(p) + 1;
4045 4051 p += len;
4046 4052 tlen -= len;
4047 4053 }
4048 4054
4049 4055 /* (12) scsiclass,DD */
4050 4056 *csp++ = p;
4051 4057 (void) snprintf(p, tlen, "scsiclass,%02x", dtype_node);
4052 4058 len = strlen(p) + 1;
4053 4059 p += len;
4054 4060 tlen -= len;
4055 4061
4056 4062 /* (12.5) scsa.fFFF */
4057 4063 if (*ff) {
4058 4064 *csp++ = p;
4059 4065 (void) snprintf(p, tlen, "scsa.f%s", ff);
4060 4066 len = strlen(p) + 1;
4061 4067 p += len;
4062 4068 tlen -= len;
4063 4069 }
4064 4070
4065 4071 /* (13) scsiclass */
4066 4072 *csp++ = p;
4067 4073 (void) snprintf(p, tlen, "scsiclass");
4068 4074 len = strlen(p) + 1;
4069 4075 p += len;
4070 4076 tlen -= len;
4071 4077 ASSERT(tlen >= 0);
4072 4078
4073 4079 *csp = NULL; /* NULL terminate array of pointers */
4074 4080 ncompat = csp - compatp;
4075 4081
4076 4082 /*
4077 4083 * When determining a nodename, a nodename_aliases specified
4078 4084 * mapping has precedence over using a driver_aliases specified
4079 4085 * driver binding as a nodename.
4080 4086 *
4081 4087 * See if any of the compatible forms have a nodename_aliases
4082 4088 * specified nodename. These mappings are described by
4083 4089 * nodename_aliases entries like:
4084 4090 *
4085 4091 * disk "scsiclass,00"
4086 4092 * enclosure "scsiclass,03.vSYMBIOS.pD1000"
4087 4093 * ssd "scsa,00.bfcp"
4088 4094 *
4089 4095 * All nodename_aliases mappings should idealy be to generic
4090 4096 * names, however a higher precedence legacy mapping to a
4091 4097 * driver name may exist. The highest precedence mapping
4092 4098 * provides the nodename, so legacy driver nodename mappings
4093 4099 * (if they exist) take precedence over generic nodename
4094 4100 * mappings.
4095 4101 */
4096 4102 for (nname = NULL, csp = compatp; (nname == NULL) && *csp; csp++) {
4097 4103 for (nap = na; nap->na_nodename; nap++) {
4098 4104 if (strcmp(*csp, nap->na_alias) == 0) {
4099 4105 nname = nap->na_nodename;
4100 4106 break;
4101 4107 }
4102 4108 }
4103 4109 }
4104 4110
4105 4111 /*
4106 4112 * Determine the driver name based on compatible (which may
4107 4113 * have the passed in compat0 as the first item). The driver_aliases
4108 4114 * file has entries like
4109 4115 *
4110 4116 * sd "scsiclass,00"
4111 4117 *
4112 4118 * that map compatible forms to specific drivers. These entries are
4113 4119 * established by add_drv/update_drv. We use the most specific
4114 4120 * driver binding as the nodename. This matches the eventual
4115 4121 * ddi_driver_compatible_major() binding that will be
4116 4122 * established by bind_node()
4117 4123 */
4118 4124 for (dname = NULL, csp = compatp; *csp; csp++) {
4119 4125 major = ddi_name_to_major(*csp);
4120 4126 if ((major == DDI_MAJOR_T_NONE) ||
4121 4127 (devnamesp[major].dn_flags & DN_DRIVER_REMOVED))
4122 4128 continue;
4123 4129 if (dname = ddi_major_to_name(major))
4124 4130 break;
4125 4131 }
4126 4132
4127 4133 /*
4128 4134 * If no nodename_aliases mapping exists then use the
4129 4135 * driver_aliases specified driver binding as a nodename.
4130 4136 */
4131 4137 if (nname == NULL)
4132 4138 nname = dname;
4133 4139
4134 4140 /* return results */
4135 4141 if (nname) {
4136 4142 *nodenamep = kmem_alloc(strlen(nname) + 1, KM_SLEEP);
4137 4143 (void) strcpy(*nodenamep, nname);
4138 4144 } else {
4139 4145 *nodenamep = NULL;
4140 4146
4141 4147 /*
4142 4148 * If no nodename could be determined return a special
4143 4149 * 'compatible' to be used for a diagnostic message. This
4144 4150 * compatible contains all compatible forms concatenated
4145 4151 * into a single string pointed to by the first element.
4146 4152 */
4147 4153 for (csp = compatp; *(csp + 1); csp++)
4148 4154 *((*csp) + strlen(*csp)) = ' ';
4149 4155 *(compatp + 1) = NULL;
4150 4156 ncompat = 1;
4151 4157
4152 4158 }
4153 4159 if (drivernamep) {
4154 4160 if (dname) {
4155 4161 *drivernamep = kmem_alloc(strlen(dname) + 1, KM_SLEEP);
4156 4162 (void) strcpy(*drivernamep, dname);
4157 4163 } else
4158 4164 *drivernamep = NULL;
4159 4165 }
4160 4166 *compatiblep = compatp;
4161 4167 *ncompatiblep = ncompat;
4162 4168 }
4163 4169
4164 4170 /*
4165 4171 * Free allocations associated with scsi_hba_ident_nodename_compatible_get.
4166 4172 */
4167 4173 static void
4168 4174 scsi_hba_ident_nodename_compatible_free(char *nodename, char *drivername,
4169 4175 char **compatible)
4170 4176 {
4171 4177 if (nodename)
4172 4178 kmem_free(nodename, strlen(nodename) + 1);
4173 4179 if (drivername)
4174 4180 kmem_free(drivername, strlen(drivername) + 1);
4175 4181 if (compatible)
4176 4182 kmem_free(compatible, (NCOMPAT * sizeof (char *)) +
4177 4183 (NCOMPAT * COMPAT_LONGEST));
4178 4184 }
4179 4185
4180 4186 void
4181 4187 scsi_hba_nodename_compatible_get(struct scsi_inquiry *inq,
4182 4188 char *binding_set, int dtype_node, char *compat0,
4183 4189 char **nodenamep, char ***compatiblep, int *ncompatiblep)
4184 4190 {
4185 4191 scsi_hba_ident_nodename_compatible_get(inq,
4186 4192 NULL, 0, NULL, 0, binding_set, dtype_node, compat0, nodenamep,
4187 4193 NULL, compatiblep, ncompatiblep);
4188 4194 }
4189 4195
4190 4196 void
4191 4197 scsi_hba_nodename_compatible_free(char *nodename, char **compatible)
4192 4198 {
4193 4199 scsi_hba_ident_nodename_compatible_free(nodename, NULL, compatible);
4194 4200 }
4195 4201
4196 4202 /* return the unit_address associated with a scsi_device */
4197 4203 char *
4198 4204 scsi_device_unit_address(struct scsi_device *sd)
4199 4205 {
4200 4206 mdi_pathinfo_t *pip;
4201 4207
4202 4208 ASSERT(sd && sd->sd_dev);
4203 4209 if ((sd == NULL) || (sd->sd_dev == NULL))
4204 4210 return (NULL);
4205 4211
4206 4212 pip = (mdi_pathinfo_t *)sd->sd_pathinfo;
4207 4213 if (pip)
4208 4214 return (mdi_pi_get_addr(pip));
4209 4215 else
4210 4216 return (ddi_get_name_addr(sd->sd_dev));
4211 4217 }
4212 4218
4213 4219 /* scsi_device property interfaces */
4214 4220 #define _TYPE_DEFINED(flags) \
4215 4221 (((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) || \
4216 4222 ((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_DEVICE))
4217 4223
4218 4224 #define _DEVICE_PIP(sd, flags) \
4219 4225 ((((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) && \
4220 4226 sd->sd_pathinfo) ? (mdi_pathinfo_t *)sd->sd_pathinfo : NULL)
4221 4227
4222 4228 int
4223 4229 scsi_device_prop_get_int(struct scsi_device *sd, uint_t flags,
4224 4230 char *name, int defval)
4225 4231 {
4226 4232 mdi_pathinfo_t *pip;
4227 4233 int v = defval;
4228 4234 int data;
4229 4235 int rv;
4230 4236
4231 4237 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4232 4238 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4233 4239 !_TYPE_DEFINED(flags))
4234 4240 return (v);
4235 4241
4236 4242 pip = _DEVICE_PIP(sd, flags);
4237 4243 if (pip) {
4238 4244 rv = mdi_prop_lookup_int(pip, name, &data);
4239 4245 if (rv == DDI_PROP_SUCCESS)
4240 4246 v = data;
4241 4247 } else
4242 4248 v = ddi_prop_get_int(DDI_DEV_T_ANY, sd->sd_dev,
4243 4249 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name, v);
4244 4250 return (v);
4245 4251 }
4246 4252
4247 4253
4248 4254 int64_t
4249 4255 scsi_device_prop_get_int64(struct scsi_device *sd, uint_t flags,
4250 4256 char *name, int64_t defval)
4251 4257 {
4252 4258 mdi_pathinfo_t *pip;
4253 4259 int64_t v = defval;
4254 4260 int64_t data;
4255 4261 int rv;
4256 4262
4257 4263 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4258 4264 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4259 4265 !_TYPE_DEFINED(flags))
4260 4266 return (v);
4261 4267
4262 4268 pip = _DEVICE_PIP(sd, flags);
4263 4269 if (pip) {
4264 4270 rv = mdi_prop_lookup_int64(pip, name, &data);
4265 4271 if (rv == DDI_PROP_SUCCESS)
4266 4272 v = data;
4267 4273 } else
4268 4274 v = ddi_prop_get_int64(DDI_DEV_T_ANY, sd->sd_dev,
4269 4275 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name, v);
4270 4276 return (v);
4271 4277 }
4272 4278
4273 4279 int
4274 4280 scsi_device_prop_lookup_byte_array(struct scsi_device *sd, uint_t flags,
4275 4281 char *name, uchar_t **data, uint_t *nelements)
4276 4282 {
4277 4283 mdi_pathinfo_t *pip;
4278 4284 int rv;
4279 4285
4280 4286 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4281 4287 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4282 4288 !_TYPE_DEFINED(flags))
4283 4289 return (DDI_PROP_INVAL_ARG);
4284 4290
4285 4291 pip = _DEVICE_PIP(sd, flags);
4286 4292 if (pip)
4287 4293 rv = mdi_prop_lookup_byte_array(pip, name, data, nelements);
4288 4294 else
4289 4295 rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, sd->sd_dev,
4290 4296 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4291 4297 name, data, nelements);
4292 4298 return (rv);
4293 4299 }
4294 4300
4295 4301 int
4296 4302 scsi_device_prop_lookup_int_array(struct scsi_device *sd, uint_t flags,
4297 4303 char *name, int **data, uint_t *nelements)
4298 4304 {
4299 4305 mdi_pathinfo_t *pip;
4300 4306 int rv;
4301 4307
4302 4308 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4303 4309 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4304 4310 !_TYPE_DEFINED(flags))
4305 4311 return (DDI_PROP_INVAL_ARG);
4306 4312
4307 4313 pip = _DEVICE_PIP(sd, flags);
4308 4314 if (pip)
4309 4315 rv = mdi_prop_lookup_int_array(pip, name, data, nelements);
4310 4316 else
4311 4317 rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
4312 4318 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4313 4319 name, data, nelements);
4314 4320 return (rv);
4315 4321 }
4316 4322
4317 4323
4318 4324 int
4319 4325 scsi_device_prop_lookup_string(struct scsi_device *sd, uint_t flags,
4320 4326 char *name, char **data)
4321 4327 {
4322 4328 mdi_pathinfo_t *pip;
4323 4329 int rv;
4324 4330
4325 4331 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4326 4332 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4327 4333 !_TYPE_DEFINED(flags))
4328 4334 return (DDI_PROP_INVAL_ARG);
4329 4335
4330 4336 pip = _DEVICE_PIP(sd, flags);
4331 4337 if (pip)
4332 4338 rv = mdi_prop_lookup_string(pip, name, data);
4333 4339 else
4334 4340 rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, sd->sd_dev,
4335 4341 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4336 4342 name, data);
4337 4343 return (rv);
4338 4344 }
4339 4345
4340 4346 int
4341 4347 scsi_device_prop_lookup_string_array(struct scsi_device *sd, uint_t flags,
4342 4348 char *name, char ***data, uint_t *nelements)
4343 4349 {
4344 4350 mdi_pathinfo_t *pip;
4345 4351 int rv;
4346 4352
4347 4353 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4348 4354 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4349 4355 !_TYPE_DEFINED(flags))
4350 4356 return (DDI_PROP_INVAL_ARG);
4351 4357
4352 4358 pip = _DEVICE_PIP(sd, flags);
4353 4359 if (pip)
4354 4360 rv = mdi_prop_lookup_string_array(pip, name, data, nelements);
4355 4361 else
4356 4362 rv = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, sd->sd_dev,
4357 4363 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4358 4364 name, data, nelements);
4359 4365 return (rv);
4360 4366 }
4361 4367
4362 4368 int
4363 4369 scsi_device_prop_update_byte_array(struct scsi_device *sd, uint_t flags,
4364 4370 char *name, uchar_t *data, uint_t nelements)
4365 4371 {
4366 4372 mdi_pathinfo_t *pip;
4367 4373 int rv;
4368 4374
4369 4375 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4370 4376 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4371 4377 !_TYPE_DEFINED(flags))
4372 4378 return (DDI_PROP_INVAL_ARG);
4373 4379
4374 4380 pip = _DEVICE_PIP(sd, flags);
4375 4381 if (pip)
4376 4382 rv = mdi_prop_update_byte_array(pip, name, data, nelements);
4377 4383 else
4378 4384 rv = ndi_prop_update_byte_array(DDI_DEV_T_NONE, sd->sd_dev,
4379 4385 name, data, nelements);
4380 4386 return (rv);
4381 4387 }
4382 4388
4383 4389 int
4384 4390 scsi_device_prop_update_int(struct scsi_device *sd, uint_t flags,
4385 4391 char *name, int data)
4386 4392 {
4387 4393 mdi_pathinfo_t *pip;
4388 4394 int rv;
4389 4395
4390 4396 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4391 4397 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4392 4398 !_TYPE_DEFINED(flags))
4393 4399 return (DDI_PROP_INVAL_ARG);
4394 4400
4395 4401 pip = _DEVICE_PIP(sd, flags);
4396 4402 if (pip)
4397 4403 rv = mdi_prop_update_int(pip, name, data);
4398 4404 else
4399 4405 rv = ndi_prop_update_int(DDI_DEV_T_NONE, sd->sd_dev,
4400 4406 name, data);
4401 4407 return (rv);
4402 4408 }
4403 4409
4404 4410 int
4405 4411 scsi_device_prop_update_int64(struct scsi_device *sd, uint_t flags,
4406 4412 char *name, int64_t data)
4407 4413 {
4408 4414 mdi_pathinfo_t *pip;
4409 4415 int rv;
4410 4416
4411 4417 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4412 4418 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4413 4419 !_TYPE_DEFINED(flags))
4414 4420 return (DDI_PROP_INVAL_ARG);
4415 4421
4416 4422 pip = _DEVICE_PIP(sd, flags);
4417 4423 if (pip)
4418 4424 rv = mdi_prop_update_int64(pip, name, data);
4419 4425 else
4420 4426 rv = ndi_prop_update_int64(DDI_DEV_T_NONE, sd->sd_dev,
4421 4427 name, data);
4422 4428 return (rv);
4423 4429 }
4424 4430
4425 4431 int
4426 4432 scsi_device_prop_update_int_array(struct scsi_device *sd, uint_t flags,
4427 4433 char *name, int *data, uint_t nelements)
4428 4434 {
4429 4435 mdi_pathinfo_t *pip;
4430 4436 int rv;
4431 4437
4432 4438 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4433 4439 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4434 4440 !_TYPE_DEFINED(flags))
4435 4441 return (DDI_PROP_INVAL_ARG);
4436 4442
4437 4443 pip = _DEVICE_PIP(sd, flags);
4438 4444 if (pip)
4439 4445 rv = mdi_prop_update_int_array(pip, name, data, nelements);
4440 4446 else
4441 4447 rv = ndi_prop_update_int_array(DDI_DEV_T_NONE, sd->sd_dev,
4442 4448 name, data, nelements);
4443 4449 return (rv);
4444 4450 }
4445 4451
4446 4452 int
4447 4453 scsi_device_prop_update_string(struct scsi_device *sd, uint_t flags,
4448 4454 char *name, char *data)
4449 4455 {
4450 4456 mdi_pathinfo_t *pip;
4451 4457 int rv;
4452 4458
4453 4459 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4454 4460 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4455 4461 !_TYPE_DEFINED(flags))
4456 4462 return (DDI_PROP_INVAL_ARG);
4457 4463
4458 4464 pip = _DEVICE_PIP(sd, flags);
4459 4465 if (pip)
4460 4466 rv = mdi_prop_update_string(pip, name, data);
4461 4467 else
4462 4468 rv = ndi_prop_update_string(DDI_DEV_T_NONE, sd->sd_dev,
4463 4469 name, data);
4464 4470 return (rv);
4465 4471 }
4466 4472
4467 4473 int
4468 4474 scsi_device_prop_update_string_array(struct scsi_device *sd, uint_t flags,
4469 4475 char *name, char **data, uint_t nelements)
4470 4476 {
4471 4477 mdi_pathinfo_t *pip;
4472 4478 int rv;
4473 4479
4474 4480 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4475 4481 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4476 4482 !_TYPE_DEFINED(flags))
4477 4483 return (DDI_PROP_INVAL_ARG);
4478 4484
4479 4485 pip = _DEVICE_PIP(sd, flags);
4480 4486 if (pip)
4481 4487 rv = mdi_prop_update_string_array(pip, name, data, nelements);
4482 4488 else
4483 4489 rv = ndi_prop_update_string_array(DDI_DEV_T_NONE, sd->sd_dev,
4484 4490 name, data, nelements);
4485 4491 return (rv);
4486 4492 }
4487 4493
4488 4494 int
4489 4495 scsi_device_prop_remove(struct scsi_device *sd, uint_t flags, char *name)
4490 4496 {
4491 4497 mdi_pathinfo_t *pip;
4492 4498 int rv;
4493 4499
4494 4500 ASSERT(sd && name && sd->sd_dev && _TYPE_DEFINED(flags));
4495 4501 if ((sd == NULL) || (name == NULL) || (sd->sd_dev == NULL) ||
4496 4502 !_TYPE_DEFINED(flags))
4497 4503 return (DDI_PROP_INVAL_ARG);
4498 4504
4499 4505 pip = _DEVICE_PIP(sd, flags);
4500 4506 if (pip)
4501 4507 rv = mdi_prop_remove(pip, name);
4502 4508 else
4503 4509 rv = ndi_prop_remove(DDI_DEV_T_NONE, sd->sd_dev, name);
4504 4510 return (rv);
4505 4511 }
4506 4512
4507 4513 void
4508 4514 scsi_device_prop_free(struct scsi_device *sd, uint_t flags, void *data)
4509 4515 {
4510 4516 mdi_pathinfo_t *pip;
4511 4517
4512 4518 ASSERT(sd && data && sd->sd_dev && _TYPE_DEFINED(flags));
4513 4519 if ((sd == NULL) || (data == NULL) || (sd->sd_dev == NULL) ||
4514 4520 !_TYPE_DEFINED(flags))
4515 4521 return;
4516 4522
4517 4523 pip = _DEVICE_PIP(sd, flags);
4518 4524 if (pip)
4519 4525 (void) mdi_prop_free(data);
4520 4526 else
4521 4527 ddi_prop_free(data);
4522 4528 }
4523 4529
4524 4530 /* SMP device property interfaces */
4525 4531 int
4526 4532 smp_device_prop_get_int(struct smp_device *smp_sd, char *name, int defval)
4527 4533 {
4528 4534 int v = defval;
4529 4535
4530 4536 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4531 4537 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4532 4538 return (v);
4533 4539
4534 4540 v = ddi_prop_get_int(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4535 4541 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name, v);
4536 4542 return (v);
4537 4543 }
4538 4544
4539 4545
4540 4546 int64_t
4541 4547 smp_device_prop_get_int64(struct smp_device *smp_sd, char *name, int64_t defval)
4542 4548 {
4543 4549 int64_t v = defval;
4544 4550
4545 4551 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4546 4552 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4547 4553 return (v);
4548 4554
4549 4555 v = ddi_prop_get_int64(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4550 4556 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, name, v);
4551 4557 return (v);
4552 4558 }
4553 4559
4554 4560 int
4555 4561 smp_device_prop_lookup_byte_array(struct smp_device *smp_sd, char *name,
4556 4562 uchar_t **data, uint_t *nelements)
4557 4563 {
4558 4564 int rv;
4559 4565
4560 4566 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4561 4567 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4562 4568 return (DDI_PROP_INVAL_ARG);
4563 4569
4564 4570 rv = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4565 4571 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4566 4572 name, data, nelements);
4567 4573 return (rv);
4568 4574 }
4569 4575
4570 4576 int
4571 4577 smp_device_prop_lookup_int_array(struct smp_device *smp_sd, char *name,
4572 4578 int **data, uint_t *nelements)
4573 4579 {
4574 4580 int rv;
4575 4581
4576 4582 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4577 4583 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4578 4584 return (DDI_PROP_INVAL_ARG);
4579 4585
4580 4586 rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4581 4587 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4582 4588 name, data, nelements);
4583 4589 return (rv);
4584 4590 }
4585 4591
4586 4592
4587 4593 int
4588 4594 smp_device_prop_lookup_string(struct smp_device *smp_sd, char *name,
4589 4595 char **data)
4590 4596 {
4591 4597 int rv;
4592 4598
4593 4599 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4594 4600 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4595 4601 return (DDI_PROP_INVAL_ARG);
4596 4602
4597 4603 rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4598 4604 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4599 4605 name, data);
4600 4606 return (rv);
4601 4607 }
4602 4608
4603 4609 int
4604 4610 smp_device_prop_lookup_string_array(struct smp_device *smp_sd, char *name,
4605 4611 char ***data, uint_t *nelements)
4606 4612 {
4607 4613 int rv;
4608 4614
4609 4615 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4610 4616 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4611 4617 return (DDI_PROP_INVAL_ARG);
4612 4618
4613 4619 rv = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, smp_sd->smp_sd_dev,
4614 4620 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4615 4621 name, data, nelements);
4616 4622 return (rv);
4617 4623 }
4618 4624
4619 4625 int
4620 4626 smp_device_prop_update_byte_array(struct smp_device *smp_sd, char *name,
4621 4627 uchar_t *data, uint_t nelements)
4622 4628 {
4623 4629 int rv;
4624 4630
4625 4631 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4626 4632 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4627 4633 return (DDI_PROP_INVAL_ARG);
4628 4634
4629 4635 rv = ndi_prop_update_byte_array(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4630 4636 name, data, nelements);
4631 4637 return (rv);
4632 4638 }
4633 4639
4634 4640 int
4635 4641 smp_device_prop_update_int(struct smp_device *smp_sd, char *name, int data)
4636 4642 {
4637 4643 int rv;
4638 4644
4639 4645 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4640 4646 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4641 4647 return (DDI_PROP_INVAL_ARG);
4642 4648
4643 4649 rv = ndi_prop_update_int(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4644 4650 name, data);
4645 4651 return (rv);
4646 4652 }
4647 4653
4648 4654 int
4649 4655 smp_device_prop_update_int64(struct smp_device *smp_sd, char *name,
4650 4656 int64_t data)
4651 4657 {
4652 4658 int rv;
4653 4659
4654 4660 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4655 4661 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4656 4662 return (DDI_PROP_INVAL_ARG);
4657 4663
4658 4664 rv = ndi_prop_update_int64(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4659 4665 name, data);
4660 4666 return (rv);
4661 4667 }
4662 4668
4663 4669 int
4664 4670 smp_device_prop_update_int_array(struct smp_device *smp_sd, char *name,
4665 4671 int *data, uint_t nelements)
4666 4672 {
4667 4673 int rv;
4668 4674
4669 4675 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4670 4676 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4671 4677 return (DDI_PROP_INVAL_ARG);
4672 4678
4673 4679 rv = ndi_prop_update_int_array(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4674 4680 name, data, nelements);
4675 4681 return (rv);
4676 4682 }
4677 4683
4678 4684 int
4679 4685 smp_device_prop_update_string(struct smp_device *smp_sd, char *name, char *data)
4680 4686 {
4681 4687 int rv;
4682 4688
4683 4689 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4684 4690 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4685 4691 return (DDI_PROP_INVAL_ARG);
4686 4692
4687 4693 rv = ndi_prop_update_string(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4688 4694 name, data);
4689 4695 return (rv);
4690 4696 }
4691 4697
4692 4698 int
4693 4699 smp_device_prop_update_string_array(struct smp_device *smp_sd, char *name,
4694 4700 char **data, uint_t nelements)
4695 4701 {
4696 4702 int rv;
4697 4703
4698 4704 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4699 4705 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4700 4706 return (DDI_PROP_INVAL_ARG);
4701 4707
4702 4708 rv = ndi_prop_update_string_array(DDI_DEV_T_NONE, smp_sd->smp_sd_dev,
4703 4709 name, data, nelements);
4704 4710 return (rv);
4705 4711 }
4706 4712
4707 4713 int
4708 4714 smp_device_prop_remove(struct smp_device *smp_sd, char *name)
4709 4715 {
4710 4716 int rv;
4711 4717
4712 4718 ASSERT(smp_sd && name && smp_sd->smp_sd_dev);
4713 4719 if ((smp_sd == NULL) || (name == NULL) || (smp_sd->smp_sd_dev == NULL))
4714 4720 return (DDI_PROP_INVAL_ARG);
4715 4721
4716 4722 rv = ndi_prop_remove(DDI_DEV_T_NONE, smp_sd->smp_sd_dev, name);
4717 4723 return (rv);
4718 4724 }
4719 4725
4720 4726 void
4721 4727 smp_device_prop_free(struct smp_device *smp_sd, void *data)
4722 4728 {
4723 4729 ASSERT(smp_sd && data && smp_sd->smp_sd_dev);
4724 4730 if ((smp_sd == NULL) || (data == NULL) || (smp_sd->smp_sd_dev == NULL))
4725 4731 return;
4726 4732
4727 4733 ddi_prop_free(data);
4728 4734 }
4729 4735
4730 4736 /*
4731 4737 * scsi_hba_ua_set: given "unit-address" string, set properties.
4732 4738 *
4733 4739 * Function to set the properties on a devinfo or pathinfo node from
4734 4740 * the "unit-address" part of a "name@unit-address" /devices path 'name'
4735 4741 * string.
4736 4742 *
4737 4743 * This function works in conjunction with scsi_ua_get()/scsi_hba_ua_get()
4738 4744 * (and possibly with an HBA driver's tran_tgt_init() implementation).
4739 4745 */
4740 4746 static int
4741 4747 scsi_hba_ua_set(char *ua, dev_info_t *dchild, mdi_pathinfo_t *pchild)
4742 4748 {
4743 4749 char *p;
4744 4750 int tgt;
4745 4751 char *tgt_port_end;
4746 4752 char *tgt_port;
4747 4753 int tgt_port_len;
4748 4754 int sfunc;
4749 4755 scsi_lun64_t lun64;
4750 4756
4751 4757 /* Caller must choose to decorate devinfo *or* pathinfo */
4752 4758 ASSERT((dchild != NULL) ^ (pchild != NULL));
4753 4759 if (dchild && pchild)
4754 4760 return (0);
4755 4761
4756 4762 /*
4757 4763 * generic implementation based on "tgt,lun[,sfunc]" address form.
4758 4764 * parse hex "tgt" part of "tgt,lun[,sfunc]"
4759 4765 */
4760 4766 p = ua;
4761 4767 tgt_port_end = NULL;
4762 4768 for (tgt = 0; *p && *p != ','; p++) {
4763 4769 if (*p >= '0' && *p <= '9')
4764 4770 tgt = (tgt << 4) + (*p - '0');
4765 4771 else if (*p >= 'a' && *p <= 'f')
4766 4772 tgt = (tgt << 4) + 10 + (*p - 'a');
4767 4773 else
4768 4774 tgt = -1; /* non-numeric */
4769 4775
4770 4776 /*
4771 4777 * if non-numeric or our of range set tgt to -1 and
4772 4778 * skip forward
4773 4779 */
4774 4780 if (tgt < 0) {
4775 4781 tgt = -1;
4776 4782 for (; *p && *p != ','; p++)
4777 4783 ;
4778 4784 break;
4779 4785 }
4780 4786 }
4781 4787 tgt_port_end = p;
4782 4788
4783 4789 /* parse hex ",lun" part of "tgt,lun[,sfunc]" */
4784 4790 if (*p)
4785 4791 p++;
4786 4792 for (lun64 = 0; *p && *p != ','; p++) {
4787 4793 if (*p >= '0' && *p <= '9')
4788 4794 lun64 = (lun64 << 4) + (*p - '0');
4789 4795 else if (*p >= 'a' && *p <= 'f')
4790 4796 lun64 = (lun64 << 4) + 10 + (*p - 'a');
4791 4797 else
4792 4798 return (0);
4793 4799 }
4794 4800
4795 4801 /* parse hex ",sfunc" part of "tgt,lun[,sfunc]" */
4796 4802 if (*p) {
4797 4803 p++;
4798 4804 for (sfunc = 0; *p; p++) {
4799 4805 if (*p >= '0' && *p <= '9')
4800 4806 sfunc = (sfunc << 4) + (*p - '0');
4801 4807 else if (*p >= 'a' && *p <= 'f')
4802 4808 sfunc = (sfunc << 4) + 10 + (*p - 'a');
4803 4809 else
4804 4810 return (0);
4805 4811 }
4806 4812 } else
4807 4813 sfunc = -1;
4808 4814
4809 4815 if (dchild) {
4810 4816 /*
4811 4817 * Decorate a devinfo node with unit address properties.
4812 4818 * This adds the the addressing properties needed to
4813 4819 * DDI_CTLOPS_UNINITCHILD the devinfo node (i.e. perform
4814 4820 * the reverse operation - form unit address from properties).
4815 4821 */
4816 4822 if ((tgt != -1) && (ndi_prop_update_int(DDI_DEV_T_NONE, dchild,
4817 4823 SCSI_ADDR_PROP_TARGET, tgt) != DDI_PROP_SUCCESS))
4818 4824 return (0);
4819 4825
4820 4826 if (tgt_port_end) {
4821 4827 tgt_port_len = tgt_port_end - ua + 1;
4822 4828 tgt_port = kmem_alloc(tgt_port_len, KM_SLEEP);
4823 4829 (void) strlcpy(tgt_port, ua, tgt_port_len);
4824 4830 if (ndi_prop_update_string(DDI_DEV_T_NONE, dchild,
4825 4831 SCSI_ADDR_PROP_TARGET_PORT, tgt_port) !=
4826 4832 DDI_PROP_SUCCESS) {
4827 4833 kmem_free(tgt_port, tgt_port_len);
4828 4834 return (0);
4829 4835 }
4830 4836 kmem_free(tgt_port, tgt_port_len);
4831 4837 }
4832 4838
4833 4839 /* Set the appropriate lun properties. */
4834 4840 if (lun64 < SCSI_32LUNS_PER_TARGET) {
4835 4841 if (ndi_prop_update_int(DDI_DEV_T_NONE, dchild,
4836 4842 SCSI_ADDR_PROP_LUN, (int)lun64) != DDI_PROP_SUCCESS)
4837 4843 return (0);
4838 4844 }
4839 4845 if (ndi_prop_update_int64(DDI_DEV_T_NONE, dchild,
4840 4846 SCSI_ADDR_PROP_LUN64, lun64) != DDI_PROP_SUCCESS)
4841 4847 return (0);
4842 4848
4843 4849 /* Set the sfunc property */
4844 4850 if ((sfunc != -1) &&
4845 4851 (ndi_prop_update_int(DDI_DEV_T_NONE, dchild,
4846 4852 SCSI_ADDR_PROP_SFUNC, (int)sfunc) != DDI_PROP_SUCCESS))
4847 4853 return (0);
4848 4854 } else if (pchild) {
4849 4855 /*
4850 4856 * Decorate a pathinfo node with unit address properties.
4851 4857 */
4852 4858 if ((tgt != -1) && (mdi_prop_update_int(pchild,
4853 4859 SCSI_ADDR_PROP_TARGET, tgt) != DDI_PROP_SUCCESS))
4854 4860 return (0);
4855 4861
4856 4862 if (tgt_port_end) {
4857 4863 tgt_port_len = tgt_port_end - ua + 1;
4858 4864 tgt_port = kmem_alloc(tgt_port_len, KM_SLEEP);
4859 4865 (void) strlcpy(tgt_port, ua, tgt_port_len);
4860 4866 if (mdi_prop_update_string(pchild,
4861 4867 SCSI_ADDR_PROP_TARGET_PORT, tgt_port) !=
4862 4868 DDI_PROP_SUCCESS) {
4863 4869 kmem_free(tgt_port, tgt_port_len);
4864 4870 return (0);
4865 4871 }
4866 4872 kmem_free(tgt_port, tgt_port_len);
4867 4873 }
4868 4874
4869 4875 /* Set the appropriate lun properties */
4870 4876 if (lun64 < SCSI_32LUNS_PER_TARGET) {
4871 4877 if (mdi_prop_update_int(pchild, SCSI_ADDR_PROP_LUN,
4872 4878 (int)lun64) != DDI_PROP_SUCCESS)
4873 4879 return (0);
4874 4880 }
4875 4881
4876 4882 if (mdi_prop_update_int64(pchild, SCSI_ADDR_PROP_LUN64,
4877 4883 lun64) != DDI_PROP_SUCCESS)
4878 4884 return (0);
4879 4885
4880 4886 /* Set the sfunc property */
4881 4887 if ((sfunc != -1) &&
4882 4888 (mdi_prop_update_int(pchild,
4883 4889 SCSI_ADDR_PROP_SFUNC, (int)sfunc) != DDI_PROP_SUCCESS))
4884 4890 return (0);
4885 4891 }
4886 4892 return (1);
4887 4893 }
4888 4894
4889 4895 /*
4890 4896 * Private ndi_devi_find/mdi_pi_find implementation - find the child
4891 4897 * dev_info/path_info of self whose phci name matches "name@caddr".
4892 4898 * We have our own implementation because we need to search with both
4893 4899 * forms of sibling lists (dev_info and path_info) and we need to be able
4894 4900 * to search with a NULL name in order to find siblings already associated
4895 4901 * with a given unit-address (same @addr). NOTE: NULL name search will never
4896 4902 * return probe node.
4897 4903 *
4898 4904 * If pchildp is NULL and we find a pathinfo child, we return the client
4899 4905 * devinfo node in *dchildp.
4900 4906 *
4901 4907 * The init flag argument should be clear when called from places where
4902 4908 * recursion could occur (like scsi_busctl_initchild) and when the caller
4903 4909 * has already performed a search for name@addr with init set (performance).
4904 4910 *
4905 4911 * Future: Integrate ndi_devi_findchild_by_callback into scsi_findchild.
4906 4912 */
4907 4913 static int
4908 4914 scsi_findchild(dev_info_t *self, char *name, char *addr, int init,
4909 4915 dev_info_t **dchildp, mdi_pathinfo_t **pchildp, int *ppi)
4910 4916 {
4911 4917 dev_info_t *dchild; /* devinfo child */
4912 4918 mdi_pathinfo_t *pchild; /* pathinfo child */
4913 4919 int found = CHILD_TYPE_NONE;
4914 4920 char *daddr;
4915 4921
4916 4922 ASSERT(self && DEVI_BUSY_OWNED(self));
4917 4923 ASSERT(addr && dchildp);
4918 4924 if ((self == NULL) || (addr == NULL) || (dchildp == NULL))
4919 4925 return (CHILD_TYPE_NONE);
4920 4926
4921 4927 *dchildp = NULL;
4922 4928 if (pchildp)
4923 4929 *pchildp = NULL;
4924 4930 if (ppi)
4925 4931 *ppi = 0;
4926 4932
4927 4933 /* Walk devinfo child list to find a match */
4928 4934 for (dchild = ddi_get_child(self); dchild;
4929 4935 dchild = ddi_get_next_sibling(dchild)) {
4930 4936 if (i_ddi_node_state(dchild) < DS_INITIALIZED)
4931 4937 continue;
4932 4938
4933 4939 daddr = ddi_get_name_addr(dchild);
4934 4940 if (daddr && (strcmp(addr, daddr) == 0) &&
4935 4941 ((name == NULL) ||
4936 4942 (strcmp(name, DEVI(dchild)->devi_node_name) == 0))) {
4937 4943 /*
4938 4944 * If we are asked to find "anything" at a given
4939 4945 * unit-address (name == NULL), we don't realy want
4940 4946 * to find the 'probe' node. The existance of
4941 4947 * a probe node on a 'name == NULL' search should
4942 4948 * fail. This will trigger slow-path code where
4943 4949 * we explicity look for, and synchronize against,
4944 4950 * a node named "probe" at the unit-address.
4945 4951 */
4946 4952 if ((name == NULL) &&
4947 4953 scsi_hba_devi_is_barrier(dchild)) {
4948 4954 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
4949 4955 "%s@%s 'probe' devinfo found, skip",
4950 4956 name ? name : "", addr));
4951 4957 continue;
4952 4958 }
4953 4959
4954 4960 /* We have found a match. */
4955 4961 found |= CHILD_TYPE_DEVINFO;
4956 4962 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
4957 4963 "%s@%s devinfo found", name ? name : "", addr));
4958 4964 *dchildp = dchild; /* devinfo found */
4959 4965 break;
4960 4966 }
4961 4967 }
4962 4968
4963 4969 /*
4964 4970 * Walk pathinfo child list to find a match.
4965 4971 *
4966 4972 * NOTE: Unlike devinfo nodes, pathinfo nodes have a string searchable
4967 4973 * unit-address from creation - so there is no need for an 'init'
4968 4974 * search block of code for pathinfo nodes below.
4969 4975 */
4970 4976 pchild = mdi_pi_find(self, NULL, addr);
4971 4977 if (pchild) {
4972 4978 /*
4973 4979 * NOTE: If name specified and we match a pathinfo unit
4974 4980 * address, we don't check the client node name.
4975 4981 */
4976 4982 if (ppi)
4977 4983 *ppi = mdi_pi_get_path_instance(pchild);
4978 4984 found |= CHILD_TYPE_PATHINFO;
4979 4985
4980 4986 if (pchildp) {
4981 4987 SCSI_HBA_LOG((_LOG(4), self, NULL,
4982 4988 "%s pathinfo found", mdi_pi_spathname(pchild)));
4983 4989 *pchildp = pchild; /* pathinfo found */
4984 4990 } else if (*dchildp == NULL) {
4985 4991 /*
4986 4992 * Did not find a devinfo node, found a pathinfo node,
4987 4993 * but caller did not ask us to return a pathinfo node:
4988 4994 * we return the 'client' devinfo node instead (but
4989 4995 * with CHILD_TYPE_PATHINFO 'found' return value).
4990 4996 */
4991 4997 dchild = mdi_pi_get_client(pchild);
4992 4998 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
4993 4999 "%s pathinfo found, client switch",
4994 5000 mdi_pi_spathname(pchild)));
4995 5001
4996 5002 /*
4997 5003 * A pathinfo node always has a 'client' devinfo node,
4998 5004 * but we need to ensure that the 'client' is
4999 5005 * initialized and has a scsi_device structure too.
5000 5006 */
5001 5007 ASSERT(dchild);
5002 5008 if (i_ddi_node_state(dchild) < DS_INITIALIZED) {
5003 5009 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
5004 5010 "%s found client, initchild",
5005 5011 mdi_pi_spathname(pchild)));
5006 5012 (void) ddi_initchild(ddi_get_parent(dchild),
5007 5013 dchild);
5008 5014 }
5009 5015 if (i_ddi_node_state(dchild) >= DS_INITIALIZED) {
5010 5016 /* client found and initialized */
5011 5017 *dchildp = dchild;
5012 5018 } else {
5013 5019 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
5014 5020 "%s found client, but failed initchild",
5015 5021 mdi_pi_spathname(pchild)));
5016 5022 }
5017 5023 }
5018 5024 }
5019 5025
5020 5026 /* Try devinfo again with initchild of uninitialized nodes */
5021 5027 if ((found == CHILD_TYPE_NONE) && init) {
5022 5028 for (dchild = ddi_get_child(self); dchild;
5023 5029 dchild = ddi_get_next_sibling(dchild)) {
5024 5030 /* skip if checked above */
5025 5031 if (i_ddi_node_state(dchild) >= DS_INITIALIZED)
5026 5032 continue;
5027 5033 /* attempt initchild to establish unit-address */
5028 5034 (void) ddi_initchild(self, dchild);
5029 5035 if (i_ddi_node_state(dchild) < DS_INITIALIZED)
5030 5036 continue;
5031 5037 daddr = ddi_get_name_addr(dchild);
5032 5038 if (daddr &&
5033 5039 ((name == NULL) || (strcmp(name,
5034 5040 DEVI(dchild)->devi_node_name) == 0)) &&
5035 5041 (strcmp(addr, daddr) == 0)) {
5036 5042 found |= CHILD_TYPE_DEVINFO;
5037 5043 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
5038 5044 "%s@%s devinfo found post initchild",
5039 5045 name ? name : "", addr));
5040 5046 *dchildp = dchild; /* devinfo found */
5041 5047 break; /* node found */
5042 5048 }
5043 5049 }
5044 5050 }
5045 5051
5046 5052 /*
5047 5053 * We should never find devinfo and pathinfo at the same
5048 5054 * unit-address.
5049 5055 */
5050 5056 ASSERT(found != (CHILD_TYPE_DEVINFO | CHILD_TYPE_PATHINFO));
5051 5057 if (found == (CHILD_TYPE_DEVINFO | CHILD_TYPE_PATHINFO)) {
5052 5058 found = CHILD_TYPE_NONE;
5053 5059 *dchildp = NULL;
5054 5060 *pchildp = NULL;
5055 5061 }
5056 5062 return (found);
5057 5063 }
5058 5064
5059 5065 /*
5060 5066 * Given information about a child device (contained on probe node) construct
5061 5067 * and return a pointer to the dynamic SID devinfo node associated with the
5062 5068 * device. In the creation of this SID node a compatible property for the
5063 5069 * device is formed and used to establish a nodename (via
5064 5070 * /etc/nodename_aliases) and to bind a driver (via /etc/driver_aliases).
5065 5071 *
5066 5072 * If this routine is called then we got a response from a device and
5067 5073 * obtained the inquiry data from the device. Some inquiry results indicate
5068 5074 * that the specific LUN we addressed does not exist, and we don't want to
5069 5075 * bind a standard target driver to the node we create. Even though the
5070 5076 * specific LUN is not usable, the framework may still want to bind a
5071 5077 * target driver to the device for internal communication with the device -
5072 5078 * an example would be issuing a report_lun to enumerate other LUNs under a
5073 5079 * DPQ_NEVER LUN0. Another example would be wanting to known that the
5074 5080 * DPQ_NEVER LUN0 device exists in BUS_CONFIG_ONE for non-existent LUN
5075 5081 * caching optimizations. To support this we let the caller specify a
5076 5082 * compatible property (or driver). If LUN0 inquiry data indicates that the
5077 5083 * LUN does not exist then we establish compat0 as the highest precedence(0)
5078 5084 * compatible form. If used, this compat0 driver will never be called on to
5079 5085 * issue external commands to the device.
5080 5086 *
5081 5087 * If no driver binds to the device using driver_alias we establish the driver
5082 5088 * passed in as the node name.
5083 5089 */
5084 5090
5085 5091 extern int e_devid_cache_pathinfo(mdi_pathinfo_t *, ddi_devid_t);
5086 5092
5087 5093 static int
5088 5094 scsi_device_createchild(dev_info_t *self, char *addr, scsi_enum_t se,
5089 5095 struct scsi_device *sdprobe, dev_info_t **dchildp, mdi_pathinfo_t **pchildp)
5090 5096 {
5091 5097 scsi_lun64_t lun64;
5092 5098 int dtype;
5093 5099 int dpq;
5094 5100 int dpq_vu;
5095 5101 int dtype_node;
5096 5102 int lunexists;
5097 5103 char *compat0;
5098 5104 char *nname;
5099 5105 char **compat = NULL;
5100 5106 int ncompat;
5101 5107 dev_info_t *dchild = NULL;
5102 5108 mdi_pathinfo_t *pchild = NULL;
5103 5109 dev_info_t *probe = sdprobe->sd_dev;
5104 5110 struct scsi_inquiry *inq = sdprobe->sd_inq;
5105 5111 uchar_t *inq80 = NULL;
5106 5112 uchar_t *inq83 = NULL;
5107 5113 uint_t inq80len, inq83len;
5108 5114 char *binding_set = NULL;
5109 5115 char *dname = NULL;
5110 5116 ddi_devid_t devid;
5111 5117 int have_devid = 0;
5112 5118 ddi_devid_t cdevid;
5113 5119 int have_cdevid = 0;
5114 5120 char *devid_str;
5115 5121 char *guid = NULL;
5116 5122
5117 5123 ASSERT(self && addr && *addr && DEVI_BUSY_OWNED(self));
5118 5124 ASSERT(dchildp && pchildp);
5119 5125
5120 5126 /*
5121 5127 * Determine the lun and whether the lun exists. We may need to create
5122 5128 * a node for LUN0 (with compat0 driver binding) even if the lun does
5123 5129 * not exist - so we can run report_lun to find additional LUNs.
5124 5130 */
5125 5131 lun64 = scsi_addr_to_lun64(addr);
5126 5132 dtype = inq->inq_dtype & DTYPE_MASK; /* device */
5127 5133 dpq = inq->inq_dtype & DPQ_MASK;
5128 5134 dpq_vu = inq->inq_dtype & DPQ_VUNIQ ? 1 : 0;
5129 5135
5130 5136 dtype_node = scsi_addr_to_sfunc(addr); /* secondary function */
5131 5137 if (dtype_node == -1)
5132 5138 dtype_node = dtype; /* node for device */
5133 5139
5134 5140 lunexists = (dtype != dtype_node) || /* override */
5135 5141 ((dpq_vu == 0) && (dpq == DPQ_POSSIBLE)) || /* ANSII */
5136 5142 (dpq_vu && (lun64 == 0)); /* VU LUN0 */
5137 5143 if (dtype == DTYPE_UNKNOWN)
5138 5144 lunexists = 0;
5139 5145
5140 5146 SCSI_HBA_LOG((_LOG(4), self, NULL,
5141 5147 "@%s dtype %x %x dpq_vu %d dpq %x: %d",
5142 5148 addr, dtype, dtype_node, dpq_vu, dpq, lunexists));
5143 5149
5144 5150 /* A non-existent LUN0 uses compatible_nodev. */
5145 5151 if (lunexists) {
5146 5152 compat0 = NULL; /* compat0 not needed */
5147 5153 } else if (lun64 == 0) {
5148 5154 compat0 = compatible_nodev;
5149 5155 SCSI_HBA_LOG((_LOG(2), self, NULL,
5150 5156 "@%s lun 0 with compat0 %s", addr, compat0));
5151 5157 } else
5152 5158 goto out; /* no node created */
5153 5159
5154 5160 /* Obtain identity information from probe node. */
5155 5161 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, probe,
5156 5162 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "inquiry-page-80",
5157 5163 &inq80, &inq80len) != DDI_PROP_SUCCESS)
5158 5164 inq80 = NULL;
5159 5165 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, probe,
5160 5166 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "inquiry-page-83",
5161 5167 &inq83, &inq83len) != DDI_PROP_SUCCESS)
5162 5168 inq83 = NULL;
5163 5169
5164 5170 /* Get "scsi-binding-set" property (if there is one). */
5165 5171 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, self,
5166 5172 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
5167 5173 "scsi-binding-set", &binding_set) == DDI_PROP_SUCCESS)
5168 5174 SCSI_HBA_LOG((_LOG(2), NULL, probe,
5169 5175 "binding_set '%s'", binding_set));
5170 5176
5171 5177 /* determine the node name and compatible information */
5172 5178 scsi_hba_ident_nodename_compatible_get(inq,
5173 5179 inq80, inq80len, inq83, inq83len, binding_set, dtype_node,
5174 5180 compat0, &nname, &dname, &compat, &ncompat);
5175 5181
5176 5182 if (nname == NULL) {
5177 5183 /*
5178 5184 * We will not be able to create a node because we could not
5179 5185 * determine a node name. Print out a NODRIVER level warning
5180 5186 * message with the compatible forms for the device. Note that
5181 5187 * there may be a driver.conf node that attaches to the device,
5182 5188 * which is why we only produce this warning message for debug
5183 5189 * kernels.
5184 5190 */
5185 5191 SCSI_HBA_LOG((_LOG(1), NULL, self,
5186 5192 "no node_name for device @%s:\n compatible: %s",
5187 5193 addr, *compat));
5188 5194 goto out;
5189 5195 }
5190 5196
5191 5197 /*
5192 5198 * FUTURE: some day we may want an accurate "compatible" on the probe
5193 5199 * node so that vhci_is_dev_supported() in scsi_vhci could, at
5194 5200 * least in part, determine/configure based on "compatible".
5195 5201 *
5196 5202 * if (ndi_prop_update_string_array(DDI_DEV_T_NONE, probe,
5197 5203 * "compatible", compat, ncompat) != DDI_PROP_SUCCESS) {
5198 5204 * SCSI_HBA_LOG((_LOG(3), self, NULL,
5199 5205 * "%s@%s failed probe compatible decoration",
5200 5206 * nname, addr));
5201 5207 * goto out;
5202 5208 * }
5203 5209 */
5204 5210
5205 5211 /* Encode devid from identity information. */
5206 5212 if (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST, dname,
5207 5213 (uchar_t *)inq, sizeof (*inq), inq80, inq80len, inq83, inq83len,
5208 5214 &devid) == DDI_SUCCESS) {
5209 5215 have_devid = 1;
5210 5216
5211 5217 /* Attempt to form guid from devid. */
5212 5218 guid = ddi_devid_to_guid(devid);
5213 5219
5214 5220 /* Produce string devid for debug. */
5215 5221 devid_str = ddi_devid_str_encode(devid, NULL);
5216 5222 SCSI_HBA_LOG((_LOG(3), self, probe, "devid '%s' guid '%s'",
5217 5223 devid_str ? devid_str : "NULL", guid ? guid : "NULL"));
5218 5224 ddi_devid_str_free(devid_str);
5219 5225 }
5220 5226
5221 5227
5222 5228 /*
5223 5229 * Determine if the device should be enumerated as under the vHCI
5224 5230 * (client node) or under the pHCI. By convention scsi_vhci expects
5225 5231 * the "cinfo" argument identity information to be represented as a
5226 5232 * devinfo node with the needed information (i.e. the pHCI probe node).
5227 5233 */
5228 5234 if ((guid == NULL) ||
5229 5235 (mdi_is_dev_supported(MDI_HCI_CLASS_SCSI, self, sdprobe) !=
5230 5236 MDI_SUCCESS)) {
5231 5237 SCSI_HBA_LOG((_LOG(3), self, probe, "==> devinfo"));
5232 5238
5233 5239 /*
5234 5240 * Enumerate under pHCI:
5235 5241 *
5236 5242 * Create dynamic SID dchild node. No attempt is made to
5237 5243 * transfer information (except the addressing and identity
5238 5244 * information) from the probe node to the dynamic node since
5239 5245 * there may be HBA specific side effects that the framework
5240 5246 * does not known how to transfer.
5241 5247 */
5242 5248 ndi_devi_alloc_sleep(self, nname,
5243 5249 (se == SE_HP) ? DEVI_SID_HP_NODEID : DEVI_SID_NODEID,
5244 5250 &dchild);
5245 5251 ASSERT(dchild);
5246 5252 ndi_flavor_set(dchild, SCSA_FLAVOR_SCSI_DEVICE);
5247 5253
5248 5254 /*
5249 5255 * Decorate new node with addressing properties (via
5250 5256 * scsi_hba_ua_set()), compatible, identity information, and
5251 5257 * class.
5252 5258 */
5253 5259 if ((scsi_hba_ua_set(addr, dchild, NULL) == 0) ||
5254 5260 (ndi_prop_update_string_array(DDI_DEV_T_NONE, dchild,
5255 5261 "compatible", compat, ncompat) != DDI_PROP_SUCCESS) ||
5256 5262 (inq80 && (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
5257 5263 dchild, "inquiry-page-80", inq80, inq80len) !=
5258 5264 DDI_PROP_SUCCESS)) ||
5259 5265 (inq83 && (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
5260 5266 dchild, "inquiry-page-83", inq83, inq83len) !=
5261 5267 DDI_PROP_SUCCESS)) ||
5262 5268 (ndi_prop_update_string(DDI_DEV_T_NONE, dchild,
5263 5269 "class", "scsi") != DDI_PROP_SUCCESS)) {
5264 5270 SCSI_HBA_LOG((_LOG(2), self, NULL,
5265 5271 "devinfo @%s failed decoration", addr));
5266 5272 (void) scsi_hba_remove_node(dchild);
5267 5273 dchild = NULL;
5268 5274 goto out;
5269 5275 }
5270 5276
5271 5277 /* Bind the driver */
5272 5278 if (ndi_devi_bind_driver(dchild, 0) != NDI_SUCCESS) {
5273 5279 /* need to bind in order to register a devid */
5274 5280 SCSI_HBA_LOG((_LOGCFG, NULL, dchild,
5275 5281 "devinfo @%s created, no driver-> "
5276 5282 "no devid_register", addr));
5277 5283 goto out;
5278 5284 }
5279 5285
5280 5286 /* Register devid */
5281 5287 if (have_devid) {
5282 5288 if (ddi_devid_register(dchild, devid) == DDI_FAILURE)
5283 5289 SCSI_HBA_LOG((_LOG(1), NULL, dchild,
5284 5290 "devinfo @%s created, "
5285 5291 "devid register failed", addr));
5286 5292 else
5287 5293 SCSI_HBA_LOG((_LOG(2), NULL, dchild,
5288 5294 "devinfo @%s created with devid", addr));
5289 5295 } else
5290 5296 SCSI_HBA_LOG((_LOG(2), NULL, dchild,
5291 5297 "devinfo @%s created, no devid", addr));
5292 5298 } else {
5293 5299 /*
5294 5300 * Enumerate under vHCI:
5295 5301 *
5296 5302 * Create a pathinfo pchild node.
5297 5303 */
5298 5304 SCSI_HBA_LOG((_LOG(3), self, probe, "==>pathinfo"));
5299 5305
5300 5306 if (mdi_pi_alloc_compatible(self, nname, guid, addr, compat,
5301 5307 ncompat, 0, &pchild) != MDI_SUCCESS) {
5302 5308 SCSI_HBA_LOG((_LOG(2), self, probe,
5303 5309 "pathinfo alloc failed"));
5304 5310 goto out;
5305 5311 }
5306 5312
5307 5313 ASSERT(pchild);
5308 5314 dchild = mdi_pi_get_client(pchild);
5309 5315 ASSERT(dchild);
5310 5316 ndi_flavor_set(dchild, SCSA_FLAVOR_SCSI_DEVICE);
5311 5317
5312 5318 /*
5313 5319 * Decorate new node with addressing properties via
5314 5320 * scsi_hba_ua_set().
5315 5321 */
5316 5322 if (scsi_hba_ua_set(addr, NULL, pchild) == 0) {
5317 5323 SCSI_HBA_LOG((_LOG(1), self, NULL,
5318 5324 "pathinfo %s decoration failed",
5319 5325 mdi_pi_spathname(pchild)));
5320 5326 (void) mdi_pi_free(pchild, 0);
5321 5327 pchild = NULL;
5322 5328 goto out;
5323 5329 }
5324 5330
5325 5331 /* Bind the driver */
5326 5332 if (ndi_devi_bind_driver(dchild, 0) != NDI_SUCCESS) {
5327 5333 /* need to bind in order to register a devid */
5328 5334 SCSI_HBA_LOG((_LOGCFG, self, NULL,
5329 5335 "pathinfo %s created, no client driver-> "
5330 5336 "no devid_register", mdi_pi_spathname(pchild)));
5331 5337 goto out;
5332 5338 }
5333 5339
5334 5340 /* Watch out for inconsistancies in devids. */
5335 5341 if (ddi_devid_get(dchild, &cdevid) == DDI_SUCCESS)
5336 5342 have_cdevid = 1;
5337 5343
5338 5344 if (have_devid && !have_cdevid) {
5339 5345 /* Client does not yet have devid, register ours. */
5340 5346 if (ddi_devid_register(dchild, devid) == DDI_FAILURE)
5341 5347 SCSI_HBA_LOG((_LOG(1), self, NULL,
5342 5348 "pathinfo %s created, "
5343 5349 "devid register failed",
5344 5350 mdi_pi_spathname(pchild)));
5345 5351 else
5346 5352 SCSI_HBA_LOG((_LOG(2), self, NULL,
5347 5353 "pathinfo %s created with devid",
5348 5354 mdi_pi_spathname(pchild)));
5349 5355 } else if (have_devid && have_cdevid) {
5350 5356 /*
5351 5357 * We have devid and client already has devid:
5352 5358 * they must be the same.
5353 5359 */
5354 5360 if (ddi_devid_compare(cdevid, devid) != 0) {
5355 5361 SCSI_HBA_LOG((_LOG(WARN), NULL, dchild,
5356 5362 "mismatched devid on path %s",
5357 5363 mdi_pi_spathname(pchild)));
5358 5364 }
5359 5365 } else if (!have_devid && have_cdevid) {
5360 5366 /*
5361 5367 * Client already has a devid, but we don't:
5362 5368 * we should not have missing devids.
5363 5369 */
5364 5370 SCSI_HBA_LOG((_LOG(WARN), NULL, dchild,
5365 5371 "missing devid on path %s",
5366 5372 mdi_pi_spathname(pchild)));
5367 5373 } else if (!have_cdevid && !have_devid) {
5368 5374 /* devid not supported */
5369 5375 SCSI_HBA_LOG((_LOG(2), self, NULL,
5370 5376 "pathinfo %s created, no devid",
5371 5377 mdi_pi_spathname(pchild)));
5372 5378 }
5373 5379
5374 5380 /*
5375 5381 * The above has registered devid for the device under
5376 5382 * the client node. Now register it under the full pHCI
5377 5383 * path to the device. We'll get an entry equivalent to
5378 5384 * booting with mpxio disabled. This is needed for
5379 5385 * telemetry during enumeration.
5380 5386 */
5381 5387 if (e_devid_cache_pathinfo(pchild, devid) == DDI_SUCCESS) {
5382 5388 SCSI_HBA_LOG((_LOG(2), NULL, dchild,
5383 5389 "pathinfo @%s created with devid", addr));
5384 5390 } else {
5385 5391 SCSI_HBA_LOG((_LOG(1), NULL, dchild,
5386 5392 "pathinfo @%s devid cache failed", addr));
5387 5393 }
5388 5394 }
5389 5395
5390 5396 /* free the node name and compatible information */
5391 5397 out: if (have_devid)
5392 5398 ddi_devid_free(devid);
5393 5399 if (have_cdevid)
5394 5400 ddi_devid_free(cdevid);
5395 5401 if (guid)
5396 5402 ddi_devid_free_guid(guid);
5397 5403 if (compat)
5398 5404 scsi_hba_ident_nodename_compatible_free(nname, dname, compat);
5399 5405 if (inq80)
5400 5406 ddi_prop_free(inq80);
5401 5407 if (inq83)
5402 5408 ddi_prop_free(inq83);
5403 5409 if (binding_set)
5404 5410 ddi_prop_free(binding_set);
5405 5411
5406 5412 /* return child_type results */
5407 5413 if (pchild) {
5408 5414 *dchildp = NULL;
5409 5415 *pchildp = pchild;
5410 5416 return (CHILD_TYPE_PATHINFO);
5411 5417 } else if (dchild) {
5412 5418 *dchildp = dchild;
5413 5419 *pchildp = NULL;
5414 5420 return (CHILD_TYPE_DEVINFO);
5415 5421 }
5416 5422
5417 5423 return (CHILD_TYPE_NONE);
5418 5424 }
5419 5425
5420 5426 /*
5421 5427 * Call scsi_device_createchild and then initchild the new node.
5422 5428 */
5423 5429 static dev_info_t *
5424 5430 scsi_device_configchild(dev_info_t *self, char *addr, scsi_enum_t se,
5425 5431 struct scsi_device *sdprobe, int *circp, int *ppi)
5426 5432 {
5427 5433 int child_type;
5428 5434 dev_info_t *dchild;
5429 5435 mdi_pathinfo_t *pchild;
5430 5436 dev_info_t *child;
5431 5437 int rval;
5432 5438
5433 5439 ASSERT(self && addr && *addr && DEVI_BUSY_OWNED(self));
5434 5440 if (ppi)
5435 5441 *ppi = 0;
5436 5442
5437 5443 child_type = scsi_device_createchild(self, addr, se, sdprobe,
5438 5444 &dchild, &pchild);
5439 5445
5440 5446 /*
5441 5447 * Prevent multiple initialized (tran_tgt_init) nodes associated with
5442 5448 * the same @addr at the same time by calling tran_tgt_free() on the
5443 5449 * probe node prior to promotion of the 'real' node. After the call
5444 5450 * to scsi_hba_barrier_tran_tgt_free(), the HBA no longer has any
5445 5451 * probe node context.
5446 5452 */
5447 5453 scsi_hba_barrier_tran_tgt_free(sdprobe->sd_dev);
5448 5454
5449 5455 switch (child_type) {
5450 5456 case CHILD_TYPE_NONE:
5451 5457 child = NULL;
5452 5458 break;
5453 5459
5454 5460 case CHILD_TYPE_PATHINFO:
5455 5461 /*
5456 5462 * Online pathinfo: Hold the path and exit the pHCI while
5457 5463 * calling mdi_pi_online() to avoid deadlock with power
5458 5464 * management of pHCI.
5459 5465 */
5460 5466 ASSERT(MDI_PHCI(self));
5461 5467 mdi_hold_path(pchild);
5462 5468 scsi_hba_devi_exit_phci(self, *circp);
5463 5469
5464 5470 rval = mdi_pi_online(pchild, 0);
5465 5471
5466 5472 scsi_hba_devi_enter_phci(self, circp);
5467 5473 mdi_rele_path(pchild);
5468 5474
5469 5475 if (rval != MDI_SUCCESS) {
5470 5476 /* pathinfo form of "failed during tran_tgt_init" */
5471 5477 scsi_enumeration_failed(NULL, se,
5472 5478 mdi_pi_spathname(pchild), "path online");
5473 5479 (void) mdi_pi_free(pchild, 0);
5474 5480 return (NULL);
5475 5481 }
5476 5482
5477 5483 /*
5478 5484 * Return the path_instance of the pathinfo node.
5479 5485 *
5480 5486 * NOTE: We assume that sd_inq is not path-specific.
5481 5487 */
5482 5488 if (ppi)
5483 5489 *ppi = mdi_pi_get_path_instance(pchild);
5484 5490
5485 5491
5486 5492 /*
5487 5493 * Fallthrough into CHILD_TYPE_DEVINFO code to promote
5488 5494 * the 'client' devinfo node as a dchild.
5489 5495 */
5490 5496 dchild = mdi_pi_get_client(pchild);
5491 5497 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
5492 5498 "pathinfo online successful"));
5493 5499 /* FALLTHROUGH */
5494 5500
5495 5501 case CHILD_TYPE_DEVINFO:
5496 5502 /*
5497 5503 * For now, we ndi_devi_online() the child because some other
5498 5504 * parts of the IO framework, like degenerate devid code,
5499 5505 * depend on bus_config driving nodes to DS_ATTACHED. At some
5500 5506 * point in the future, to keep things light-weight, we would
5501 5507 * like to change the ndi_devi_online call below to be
5502 5508 *
5503 5509 * if (ddi_initchild(self, dchild) != DDI_SUCCESS)
5504 5510 *
5505 5511 * This would promote the node so that framework code could
5506 5512 * find the child with an @addr search, but does not incur
5507 5513 * attach(9E) overhead for BUS_CONFIG_ALL cases where the
5508 5514 * framework is not interested in attach of the node.
5509 5515 *
5510 5516 * NOTE: If the addr specified has incorrect syntax (busconfig
5511 5517 * one of bogus /devices path) then call below can fail.
5512 5518 */
5513 5519 if (ndi_devi_online(dchild, 0) != NDI_SUCCESS) {
5514 5520 SCSI_HBA_LOG((_LOG(2), NULL, dchild,
5515 5521 "devinfo online failed"));
5516 5522
5517 5523 /* failed online does not remove the node */
5518 5524 (void) scsi_hba_remove_node(dchild);
5519 5525 return (NULL);
5520 5526 }
5521 5527 SCSI_HBA_LOG((_LOG(4), NULL, dchild,
5522 5528 "devinfo initchild successful"));
5523 5529 child = dchild;
5524 5530 break;
5525 5531 }
5526 5532 return (child);
5527 5533 }
5528 5534
5529 5535 void
5530 5536 scsi_hba_pkt_comp(struct scsi_pkt *pkt)
5531 5537 {
5532 5538 scsi_hba_tran_t *tran;
5533 5539 uint8_t *sensep;
5534 5540
5535 5541 ASSERT(pkt);
5536 5542
5537 5543 /*
5538 5544 * Catch second call on the same packet before doing anything else.
5539 5545 */
5540 5546 if (pkt->pkt_flags & FLAG_PKT_COMP_CALLED) {
5541 5547 cmn_err(
5542 5548 #ifdef DEBUG
5543 5549 CE_PANIC,
5544 5550 #else
5545 5551 CE_WARN,
5546 5552 #endif
5547 5553 "%s duplicate scsi_hba_pkt_comp(9F) on same scsi_pkt(9S)",
5548 5554 mod_containing_pc(caller()));
5549 5555 }
5550 5556
5551 5557 pkt->pkt_flags |= FLAG_PKT_COMP_CALLED;
5552 5558
5553 5559 if (pkt->pkt_comp == NULL)
5554 5560 return;
5555 5561
5556 5562 /*
5557 5563 * For HBA drivers that implement tran_setup_pkt(9E), if we are
5558 5564 * completing a 'consistent' mode DMA operation then we must
5559 5565 * perform dma_sync prior to calling pkt_comp to ensure that
5560 5566 * the target driver sees the correct data in memory.
5561 5567 */
5562 5568 ASSERT((pkt->pkt_flags & FLAG_NOINTR) == 0);
5563 5569 if (((pkt->pkt_dma_flags & DDI_DMA_CONSISTENT) &&
5564 5570 (pkt->pkt_dma_flags & DDI_DMA_READ)) &&
5565 5571 ((P_TO_TRAN(pkt)->tran_setup_pkt) != NULL)) {
5566 5572 scsi_sync_pkt(pkt);
5567 5573 }
5568 5574
5569 5575 /*
5570 5576 * If the HBA driver is using SCSAv3 scsi_hba_tgtmap_create enumeration
5571 5577 * then we detect the special ASC/ASCQ completion codes that indicate
5572 5578 * that the lun configuration of a target has changed. Since we need to
5573 5579 * be determine scsi_device given scsi_address enbedded in
5574 5580 * scsi_pkt (via scsi_address_device(9F)), we also require use of
5575 5581 * SCSI_HBA_ADDR_COMPLEX.
5576 5582 */
5577 5583 tran = pkt->pkt_address.a_hba_tran;
5578 5584 ASSERT(tran);
5579 5585 if ((tran->tran_tgtmap == NULL) ||
5580 5586 !(tran->tran_hba_flags & SCSI_HBA_ADDR_COMPLEX))
5581 5587 goto comp; /* not using tgtmap */
5582 5588
5583 5589 /*
5584 5590 * Check for lun-change notification and queue the scsi_pkt for
5585 5591 * lunchg1 processing. The 'pkt_comp' call to the target driver
5586 5592 * is part of lunchg1 processing.
5587 5593 */
5588 5594 if ((pkt->pkt_reason == CMD_CMPLT) &&
5589 5595 (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_CHECK) &&
5590 5596 (pkt->pkt_state & STATE_ARQ_DONE)) {
5591 5597 sensep = (uint8_t *)&(((struct scsi_arq_status *)(uintptr_t)
5592 5598 (pkt->pkt_scbp))->sts_sensedata);
5593 5599 if (((scsi_sense_key(sensep) == KEY_UNIT_ATTENTION) &&
5594 5600 (scsi_sense_asc(sensep) == 0x3f) &&
5595 5601 (scsi_sense_ascq(sensep) == 0x0e)) ||
5596 5602
5597 5603 ((scsi_sense_key(sensep) == KEY_UNIT_ATTENTION) &&
5598 5604 (scsi_sense_asc(sensep) == 0x25) &&
5599 5605 (scsi_sense_ascq(sensep) == 0x00))) {
5600 5606 /*
5601 5607 * The host adaptor is done with the packet, we use
5602 5608 * pkt_stmp stage-temporary to link the packet for
5603 5609 * lunchg1 processing.
5604 5610 *
5605 5611 * NOTE: pkt_ha_private is not available since its use
5606 5612 * extends to tran_teardown_pkt.
5607 5613 */
5608 5614 mutex_enter(&scsi_lunchg1_mutex);
5609 5615 pkt->pkt_stmp = scsi_lunchg1_list;
5610 5616 scsi_lunchg1_list = pkt;
5611 5617 if (pkt->pkt_stmp == NULL)
5612 5618 (void) cv_signal(&scsi_lunchg1_cv);
5613 5619 mutex_exit(&scsi_lunchg1_mutex);
5614 5620 return;
5615 5621 }
5616 5622 }
5617 5623
5618 5624 comp: (*pkt->pkt_comp)(pkt);
5619 5625 }
5620 5626
5621 5627 /*
5622 5628 * return 1 if the specified node is a barrier/probe node
5623 5629 */
5624 5630 static int
5625 5631 scsi_hba_devi_is_barrier(dev_info_t *probe)
5626 5632 {
5627 5633 if (probe && (strcmp(ddi_node_name(probe), "probe") == 0))
5628 5634 return (1);
5629 5635 return (0);
5630 5636 }
5631 5637
5632 5638 /*
5633 5639 * A host adapter driver is easier to write if we prevent multiple initialized
5634 5640 * (tran_tgt_init) scsi_device structures to the same unit-address at the same
5635 5641 * time. We prevent this from occurring all the time during the barrier/probe
5636 5642 * node to real child hand-off by calling scsi_hba_barrier_tran_tgt_free
5637 5643 * on the probe node prior to ddi_inichild of the 'real' node. As part of
5638 5644 * this early tran_tgt_free implementation, we must also call this function
5639 5645 * as we put a probe node on the scsi_hba_barrier_list.
5640 5646 */
5641 5647 static void
5642 5648 scsi_hba_barrier_tran_tgt_free(dev_info_t *probe)
5643 5649 {
5644 5650 struct scsi_device *sdprobe;
5645 5651 dev_info_t *self;
5646 5652 scsi_hba_tran_t *tran;
5647 5653
5648 5654 ASSERT(probe && scsi_hba_devi_is_barrier(probe));
5649 5655
5650 5656 /* Return if we never called tran_tgt_init(9E). */
5651 5657 if (i_ddi_node_state(probe) < DS_INITIALIZED)
5652 5658 return;
5653 5659
5654 5660 sdprobe = ddi_get_driver_private(probe);
5655 5661 self = ddi_get_parent(probe);
5656 5662 ASSERT(sdprobe && self);
5657 5663 tran = ddi_get_driver_private(self);
5658 5664 ASSERT(tran);
5659 5665
5660 5666 if (tran->tran_tgt_free) {
5661 5667 /*
5662 5668 * To correctly support TRAN_CLONE, we need to use the same
5663 5669 * cloned scsi_hba_tran(9S) structure for both tran_tgt_init(9E)
5664 5670 * and tran_tgt_free(9E).
5665 5671 */
5666 5672 if (tran->tran_hba_flags & SCSI_HBA_TRAN_CLONE)
5667 5673 tran = sdprobe->sd_address.a_hba_tran;
5668 5674
5669 5675 if (!sdprobe->sd_tran_tgt_free_done) {
5670 5676 SCSI_HBA_LOG((_LOG(4), NULL, probe,
5671 5677 "tran_tgt_free EARLY"));
5672 5678 (*tran->tran_tgt_free) (self, probe, tran, sdprobe);
5673 5679 sdprobe->sd_tran_tgt_free_done = 1;
5674 5680 } else {
5675 5681 SCSI_HBA_LOG((_LOG(4), NULL, probe,
5676 5682 "tran_tgt_free EARLY already done"));
5677 5683 }
5678 5684 }
5679 5685 }
5680 5686
5681 5687 /*
5682 5688 * Add an entry to the list of barrier nodes to be asynchronously deleted by
5683 5689 * the scsi_hba_barrier_daemon after the specified timeout. Nodes on
5684 5690 * the barrier list are used to implement the bus_config probe cache
5685 5691 * of non-existent devices. The nodes are at DS_INITIALIZED, so their
5686 5692 * @addr is established for searching. Since devi_ref of a DS_INITIALIZED
5687 5693 * node will *not* prevent demotion, demotion is prevented by setting
5688 5694 * sd_uninit_prevent. Devinfo snapshots attempt to attach probe cache
5689 5695 * nodes, and on failure attempt to demote the node (without the participation
5690 5696 * of bus_unconfig) to DS_BOUND - this demotion is prevented via
5691 5697 * sd_uninit_prevent causing any attempted DDI_CTLOPS_UNINITCHILD to fail.
5692 5698 * Probe nodes are bound to nulldriver. The list is sorted by
5693 5699 * expiration time.
5694 5700 *
5695 5701 * NOTE: If we drove a probe node to DS_ATTACHED, we could use ndi_hold_devi()
5696 5702 * to prevent demotion (instead of sd_uninit_prevent).
5697 5703 */
5698 5704 static void
5699 5705 scsi_hba_barrier_add(dev_info_t *probe, int seconds)
5700 5706 {
5701 5707 struct scsi_hba_barrier *nb;
5702 5708 struct scsi_hba_barrier *b;
5703 5709 struct scsi_hba_barrier **bp;
5704 5710 clock_t endtime;
5705 5711
5706 5712 ASSERT(scsi_hba_devi_is_barrier(probe));
5707 5713
5708 5714 /* HBA is no longer responsible for nodes on the barrier list. */
5709 5715 scsi_hba_barrier_tran_tgt_free(probe);
5710 5716 nb = kmem_alloc(sizeof (struct scsi_hba_barrier), KM_SLEEP);
5711 5717 mutex_enter(&scsi_hba_barrier_mutex);
5712 5718 endtime = ddi_get_lbolt() + drv_usectohz(seconds * MICROSEC);
5713 5719 for (bp = &scsi_hba_barrier_list; (b = *bp) != NULL;
5714 5720 bp = &b->barrier_next)
5715 5721 if (b->barrier_endtime > endtime)
5716 5722 break;
5717 5723 nb->barrier_next = *bp;
5718 5724 nb->barrier_endtime = endtime;
5719 5725 nb->barrier_probe = probe;
5720 5726 *bp = nb;
5721 5727 if (bp == &scsi_hba_barrier_list)
5722 5728 (void) cv_signal(&scsi_hba_barrier_cv);
5723 5729 mutex_exit(&scsi_hba_barrier_mutex);
5724 5730 }
5725 5731
5726 5732 /*
5727 5733 * Attempt to remove devinfo node node, return 1 if removed. We
5728 5734 * don't try to remove barrier nodes that have sd_uninit_prevent set
5729 5735 * (even though they should fail device_uninitchild).
5730 5736 */
5731 5737 static int
5732 5738 scsi_hba_remove_node(dev_info_t *child)
5733 5739 {
5734 5740 dev_info_t *self = ddi_get_parent(child);
5735 5741 struct scsi_device *sd;
5736 5742 int circ;
5737 5743 int remove = 1;
5738 5744 int ret = 0;
5739 5745 char na[SCSI_MAXNAMELEN];
5740 5746
5741 5747 scsi_hba_devi_enter(self, &circ);
5742 5748
5743 5749 /* Honor sd_uninit_prevent on barrier nodes */
5744 5750 if (scsi_hba_devi_is_barrier(child)) {
5745 5751 sd = ddi_get_driver_private(child);
5746 5752 if (sd && sd->sd_uninit_prevent)
5747 5753 remove = 0;
5748 5754 }
5749 5755
5750 5756 if (remove) {
5751 5757 (void) ddi_deviname(child, na);
5752 5758 if (ddi_remove_child(child, 0) != DDI_SUCCESS) {
5753 5759 SCSI_HBA_LOG((_LOG(2), NULL, child,
5754 5760 "remove_node failed"));
5755 5761 } else {
5756 5762 child = NULL; /* child is gone */
5757 5763 SCSI_HBA_LOG((_LOG(4), self, NULL,
5758 5764 "remove_node removed %s", *na ? &na[1] : na));
5759 5765 ret = 1;
5760 5766 }
5761 5767 } else {
5762 5768 SCSI_HBA_LOG((_LOG(4), NULL, child, "remove_node prevented"));
5763 5769 }
5764 5770 scsi_hba_devi_exit(self, circ);
5765 5771 return (ret);
5766 5772 }
5767 5773
5768 5774 /*
5769 5775 * The asynchronous barrier deletion daemon. Waits for a barrier timeout
5770 5776 * to expire, then deletes the barrier (removes it as a child).
5771 5777 */
5772 5778 /*ARGSUSED*/
5773 5779 static void
5774 5780 scsi_hba_barrier_daemon(void *arg)
5775 5781 {
5776 5782 struct scsi_hba_barrier *b;
5777 5783 dev_info_t *probe;
5778 5784 callb_cpr_t cprinfo;
5779 5785 int circ;
5780 5786 dev_info_t *self;
5781 5787
5782 5788 CALLB_CPR_INIT(&cprinfo, &scsi_hba_barrier_mutex,
5783 5789 callb_generic_cpr, "scsi_hba_barrier_daemon");
5784 5790 again: mutex_enter(&scsi_hba_barrier_mutex);
5785 5791 for (;;) {
5786 5792 b = scsi_hba_barrier_list;
5787 5793 if (b == NULL) {
5788 5794 /* all barriers expired, wait for barrier_add */
5789 5795 CALLB_CPR_SAFE_BEGIN(&cprinfo);
5790 5796 (void) cv_wait(&scsi_hba_barrier_cv,
5791 5797 &scsi_hba_barrier_mutex);
5792 5798 CALLB_CPR_SAFE_END(&cprinfo, &scsi_hba_barrier_mutex);
5793 5799 } else {
5794 5800 if (ddi_get_lbolt() >= b->barrier_endtime) {
5795 5801 /*
5796 5802 * Drop and retry if ordering issue. Do this
5797 5803 * before calling scsi_hba_remove_node() and
5798 5804 * deadlocking.
5799 5805 */
5800 5806 probe = b->barrier_probe;
5801 5807 self = ddi_get_parent(probe);
5802 5808 if (scsi_hba_devi_tryenter(self, &circ) == 0) {
5803 5809 delay: mutex_exit(&scsi_hba_barrier_mutex);
5804 5810 delay_random(5);
5805 5811 goto again;
5806 5812 }
5807 5813
5808 5814 /* process expired barrier */
5809 5815 if (!scsi_hba_remove_node(probe)) {
5810 5816 /* remove failed, delay and retry */
5811 5817 SCSI_HBA_LOG((_LOG(4), NULL, probe,
5812 5818 "delay expire"));
5813 5819 scsi_hba_devi_exit(self, circ);
5814 5820 goto delay;
5815 5821 }
5816 5822 scsi_hba_barrier_list = b->barrier_next;
5817 5823 kmem_free(b, sizeof (struct scsi_hba_barrier));
5818 5824 scsi_hba_devi_exit(self, circ);
5819 5825 } else {
5820 5826 /* establish timeout for next barrier expire */
5821 5827 (void) cv_timedwait(&scsi_hba_barrier_cv,
5822 5828 &scsi_hba_barrier_mutex,
5823 5829 b->barrier_endtime);
5824 5830 }
5825 5831 }
5826 5832 }
5827 5833 }
5828 5834
5829 5835 /*
5830 5836 * Remove all barriers associated with the specified HBA. This is called
5831 5837 * from from the bus_unconfig implementation to remove probe nodes associated
5832 5838 * with the specified HBA (self) so that probe nodes that have not expired
5833 5839 * will not prevent DR of the HBA.
5834 5840 */
5835 5841 static void
5836 5842 scsi_hba_barrier_purge(dev_info_t *self)
5837 5843 {
5838 5844 struct scsi_hba_barrier **bp;
5839 5845 struct scsi_hba_barrier *b;
5840 5846
5841 5847 mutex_enter(&scsi_hba_barrier_mutex);
5842 5848 for (bp = &scsi_hba_barrier_list; (b = *bp) != NULL; ) {
5843 5849 if (ddi_get_parent(b->barrier_probe) == self) {
5844 5850 if (scsi_hba_remove_node(b->barrier_probe)) {
5845 5851 *bp = b->barrier_next;
5846 5852 kmem_free(b, sizeof (struct scsi_hba_barrier));
5847 5853 } else {
5848 5854 SCSI_HBA_LOG((_LOG(4), NULL, b->barrier_probe,
5849 5855 "skip purge"));
5850 5856 }
5851 5857 } else
5852 5858 bp = &b->barrier_next;
5853 5859 }
5854 5860
5855 5861 mutex_exit(&scsi_hba_barrier_mutex);
5856 5862 }
5857 5863
5858 5864 /*
5859 5865 * LUN-change processing daemons: processing occurs in two stages:
5860 5866 *
5861 5867 * Stage 1: Daemon waits for a lunchg1 queued scsi_pkt, dequeues the pkt,
5862 5868 * forms the path, completes the scsi_pkt (pkt_comp), and
5863 5869 * queues the path for stage 2 processing. The use of stage 1
5864 5870 * avoids issues related to memory allocation in interrupt context
5865 5871 * (scsi_hba_pkt_comp()). We delay the pkt_comp completion until
5866 5872 * after lunchg1 processing forms the path for stage 2 - this is
5867 5873 * done to prevent the target driver from detaching until the
5868 5874 * path formation is complete (driver with outstanding commands
5869 5875 * should not detach).
5870 5876 *
5871 5877 * Stage 2: Daemon waits for a lunchg2 queued request, dequeues the
5872 5878 * request, and opens the path using ldi_open_by_name(). The
5873 5879 * path opened uses a special "@taddr,*" unit address that will
5874 5880 * trigger lun enumeration in scsi_hba_bus_configone(). We
5875 5881 * trigger lun enumeration in stage 2 to avoid problems when
5876 5882 * initial ASC/ASCQ trigger occurs during discovery.
5877 5883 */
5878 5884 /*ARGSUSED*/
5879 5885 static void
5880 5886 scsi_lunchg1_daemon(void *arg)
5881 5887 {
5882 5888 callb_cpr_t cprinfo;
5883 5889 struct scsi_pkt *pkt;
5884 5890 scsi_hba_tran_t *tran;
5885 5891 dev_info_t *self;
5886 5892 struct scsi_device *sd;
5887 5893 char *ua, *p;
5888 5894 char taddr[SCSI_MAXNAMELEN];
5889 5895 char path[MAXPATHLEN];
5890 5896 struct scsi_lunchg2 *lunchg2;
5891 5897
5892 5898 CALLB_CPR_INIT(&cprinfo, &scsi_lunchg1_mutex,
5893 5899 callb_generic_cpr, "scsi_lunchg1_daemon");
5894 5900 mutex_enter(&scsi_lunchg1_mutex);
5895 5901 for (;;) {
5896 5902 pkt = scsi_lunchg1_list;
5897 5903 if (pkt == NULL) {
5898 5904 /* All lunchg1 processing requests serviced, wait. */
5899 5905 CALLB_CPR_SAFE_BEGIN(&cprinfo);
5900 5906 (void) cv_wait(&scsi_lunchg1_cv,
5901 5907 &scsi_lunchg1_mutex);
5902 5908 CALLB_CPR_SAFE_END(&cprinfo, &scsi_lunchg1_mutex);
5903 5909 continue;
5904 5910 }
5905 5911
5906 5912 /* Unlink and perform lunchg1 processing on pkt. */
5907 5913 scsi_lunchg1_list = pkt->pkt_stmp;
5908 5914
5909 5915 /* Determine initiator port (self) from the pkt_address. */
5910 5916 tran = pkt->pkt_address.a_hba_tran;
5911 5917 ASSERT(tran && tran->tran_tgtmap && tran->tran_iport_dip);
5912 5918 self = tran->tran_iport_dip;
5913 5919
5914 5920 /*
5915 5921 * Determine scsi_devie from pkt_address (depends on
5916 5922 * SCSI_HBA_ADDR_COMPLEX).
5917 5923 */
5918 5924 sd = scsi_address_device(&(pkt->pkt_address));
5919 5925 ASSERT(sd);
5920 5926 if (sd == NULL) {
5921 5927 (*pkt->pkt_comp)(pkt);
5922 5928 continue;
5923 5929 }
5924 5930
5925 5931 /* Determine unit-address from scsi_device. */
5926 5932 ua = scsi_device_unit_address(sd);
5927 5933
5928 5934 /* Extract taddr from the unit-address. */
5929 5935 for (p = taddr; (*ua != ',') && (*ua != '\0'); )
5930 5936 *p++ = *ua++;
5931 5937 *p = '\0'; /* NULL terminate taddr */
5932 5938
5933 5939 /*
5934 5940 * Form path using special "@taddr,*" notation to trigger
5935 5941 * lun enumeration.
5936 5942 */
5937 5943 (void) ddi_pathname(self, path);
5938 5944 (void) strcat(path, "/luns@");
5939 5945 (void) strcat(path, taddr);
5940 5946 (void) strcat(path, ",*");
5941 5947
5942 5948 /*
5943 5949 * Now that we have the path, complete the pkt that
5944 5950 * triggered lunchg1 processing.
5945 5951 */
5946 5952 (*pkt->pkt_comp)(pkt);
5947 5953
5948 5954 /* Allocate element for stage2 processing queue. */
5949 5955 lunchg2 = kmem_alloc(sizeof (*lunchg2), KM_SLEEP);
5950 5956 lunchg2->lunchg2_path = strdup(path);
5951 5957
5952 5958 /* Queue and dispatch to stage 2. */
5953 5959 SCSI_HBA_LOG((_LOG(2), self, NULL,
5954 5960 "lunchg stage1: queue %s", lunchg2->lunchg2_path));
5955 5961 mutex_enter(&scsi_lunchg2_mutex);
5956 5962 lunchg2->lunchg2_next = scsi_lunchg2_list;
5957 5963 scsi_lunchg2_list = lunchg2;
5958 5964 if (lunchg2->lunchg2_next == NULL)
5959 5965 (void) cv_signal(&scsi_lunchg2_cv);
5960 5966 mutex_exit(&scsi_lunchg2_mutex);
5961 5967 }
5962 5968 }
5963 5969
5964 5970 /*ARGSUSED*/
5965 5971 static void
5966 5972 scsi_lunchg2_daemon(void *arg)
5967 5973 {
5968 5974 callb_cpr_t cprinfo;
5969 5975 struct scsi_lunchg2 *lunchg2;
5970 5976 ldi_ident_t li;
5971 5977 ldi_handle_t lh;
5972 5978
5973 5979 CALLB_CPR_INIT(&cprinfo, &scsi_lunchg2_mutex,
5974 5980 callb_generic_cpr, "scsi_lunchg2_daemon");
5975 5981
5976 5982 li = ldi_ident_from_anon();
5977 5983 mutex_enter(&scsi_lunchg2_mutex);
5978 5984 for (;;) {
5979 5985 lunchg2 = scsi_lunchg2_list;
5980 5986 if (lunchg2 == NULL) {
5981 5987 /* All lunchg2 processing requests serviced, wait. */
5982 5988 CALLB_CPR_SAFE_BEGIN(&cprinfo);
5983 5989 (void) cv_wait(&scsi_lunchg2_cv,
5984 5990 &scsi_lunchg2_mutex);
5985 5991 CALLB_CPR_SAFE_END(&cprinfo, &scsi_lunchg2_mutex);
5986 5992 continue;
5987 5993 }
5988 5994
5989 5995 /* Unlink and perform lunchg2 processing on pkt. */
5990 5996 scsi_lunchg2_list = lunchg2->lunchg2_next;
5991 5997
5992 5998 /*
5993 5999 * Open and close the path to trigger lun enumeration. We
5994 6000 * don't expect the open to succeed, but we do expect code in
5995 6001 * scsi_hba_bus_configone() to trigger lun enumeration.
5996 6002 */
5997 6003 SCSI_HBA_LOG((_LOG(2), NULL, NULL,
5998 6004 "lunchg stage2: open %s", lunchg2->lunchg2_path));
5999 6005 if (ldi_open_by_name(lunchg2->lunchg2_path,
6000 6006 FREAD, kcred, &lh, li) == 0)
6001 6007 (void) ldi_close(lh, FREAD, kcred);
6002 6008
6003 6009 /* Free path and linked element. */
6004 6010 strfree(lunchg2->lunchg2_path);
6005 6011 kmem_free(lunchg2, sizeof (*lunchg2));
6006 6012 }
6007 6013 }
6008 6014
6009 6015 /*
6010 6016 * Enumerate a child at the specified @addr. If a device exists @addr then
6011 6017 * ensure that we have the appropriately named devinfo node for it. Name is
6012 6018 * NULL in the bus_config_all case. This routine has no knowledge of the
6013 6019 * format of an @addr string or associated addressing properties.
6014 6020 *
6015 6021 * The caller must guarantee that there is an open scsi_hba_devi_enter on the
6016 6022 * parent. We return the scsi_device structure for the child device. This
6017 6023 * scsi_device structure is valid until the caller scsi_hba_devi_exit the
6018 6024 * parent. The caller can add do ndi_hold_devi of the child prior to the
6019 6025 * scsi_hba_devi_exit to extend the validity of the child.
6020 6026 *
6021 6027 * In some cases the returned scsi_device structure may be used to drive
6022 6028 * additional SCMD_REPORT_LUNS operations by bus_config_all callers.
6023 6029 *
6024 6030 * The first operation performed is to see if there is a dynamic SID nodes
6025 6031 * already attached at the specified "name@addr". This is the fastpath
6026 6032 * case for resolving a reference to a node that has already been created.
6027 6033 * All other references are serialized for a given @addr prior to probing
6028 6034 * to determine the type of device, if any, at the specified @addr.
6029 6035 * If no device is present then NDI_FAILURE is returned. The fact that a
6030 6036 * device does not exist may be determined via the barrier/probe cache,
6031 6037 * minimizing the probes of non-existent devices.
6032 6038 *
6033 6039 * When there is a device present the dynamic SID node is created based on
6034 6040 * the device found. If a driver.conf node exists for the same @addr it
6035 6041 * will either merge into the dynamic SID node (if the SID node bound to
6036 6042 * that driver), or exist independently. To prevent the actions of one driver
6037 6043 * causing side effects in another, code prevents multiple SID nodes from
6038 6044 * binding to the same "@addr" at the same time. There is autodetach code
6039 6045 * to allow one device to be replaced with another at the same @addr for
6040 6046 * slot addressed SCSI bus implementations (SPI). For compatibility with
6041 6047 * legacy driver.conf behavior, the code does not prevent multiple driver.conf
6042 6048 * nodes from attaching to the same @addr at the same time.
6043 6049 *
6044 6050 * This routine may have the side effect of creating nodes for devices other
6045 6051 * than the one being sought. It is possible that there is a different type of
6046 6052 * target device at that target/lun address than we were asking for. In that
6047 6053 * It is the caller's responsibility to determine whether the device we found,
6048 6054 * if any, at the specified address, is the one it really wanted.
6049 6055 */
6050 6056 static struct scsi_device *
6051 6057 scsi_device_config(dev_info_t *self, char *name, char *addr, scsi_enum_t se,
6052 6058 int *circp, int *ppi)
6053 6059 {
6054 6060 dev_info_t *child = NULL;
6055 6061 dev_info_t *probe = NULL;
6056 6062 struct scsi_device *sdchild;
6057 6063 struct scsi_device *sdprobe;
6058 6064 dev_info_t *dsearch;
6059 6065 mdi_pathinfo_t *psearch;
6060 6066 major_t major;
6061 6067 int sp;
6062 6068 int pi = 0;
6063 6069 int wait_msg = scsi_hba_wait_msg;
6064 6070 int chg;
6065 6071
6066 6072 ASSERT(self && addr && DEVI_BUSY_OWNED(self));
6067 6073
6068 6074 SCSI_HBA_LOG((_LOG(4), self, NULL, "%s@%s wanted",
6069 6075 name ? name : "", addr));
6070 6076
6071 6077 /* playing with "probe" node name is dangerous */
6072 6078 if (name && (strcmp(name, "probe") == 0))
6073 6079 return (NULL);
6074 6080
6075 6081 /*
6076 6082 * NOTE: use 'goto done;' or 'goto fail;'. There should only be one
6077 6083 * 'return' statement from here to the end of the function - the one
6078 6084 * on the last line of the function.
6079 6085 */
6080 6086
6081 6087 /*
6082 6088 * Fastpath: search to see if we are requesting a named SID node that
6083 6089 * already exists (we already created) - probe node does not count.
6084 6090 * scsi_findchild() does not hold the returned devinfo node, but
6085 6091 * this is OK since the caller has a scsi_hba_devi_enter on the
6086 6092 * attached parent HBA (self). The caller is responsible for attaching
6087 6093 * and placing a hold on the child (directly via ndi_hold_devi or
6088 6094 * indirectly via ndi_busop_bus_config) before doing an
6089 6095 * scsi_hba_devi_exit on the parent.
6090 6096 *
6091 6097 * NOTE: This fastpath prevents detecting a driver binding change
6092 6098 * (autodetach) if the same nodename is used for old and new binding.
6093 6099 */
6094 6100 /* first call is with init set */
6095 6101 (void) scsi_findchild(self, name, addr, 1, &dsearch, NULL, &pi);
6096 6102 if (dsearch && scsi_hba_dev_is_sid(dsearch) &&
6097 6103 !scsi_hba_devi_is_barrier(dsearch)) {
6098 6104 SCSI_HBA_LOG((_LOG(4), NULL, dsearch,
6099 6105 "%s@%s devinfo fastpath", name ? name : "", addr));
6100 6106 child = dsearch;
6101 6107 goto done;
6102 6108 }
6103 6109
6104 6110 /*
6105 6111 * Create a barrier devinfo node used to "probe" the device with. We
6106 6112 * need to drive this node to DS_INITIALIZED so that the
6107 6113 * DDI_CTLOPS_INITCHILD has occurred, bringing the SCSA transport to
6108 6114 * a state useable state for issuing our "probe" commands. We establish
6109 6115 * this barrier node with a node name of "probe" and compatible
6110 6116 * property of "scsiprobe". The compatible property must be associated
6111 6117 * in /etc/driver_aliases with a scsi target driver available in the
6112 6118 * root file system (sd).
6113 6119 *
6114 6120 * The "probe" that we perform on the barrier node, after it is
6115 6121 * DS_INITIALIZED, is used to find the information needed to create a
6116 6122 * dynamic devinfo (SID) node. This "probe" is separate from the
6117 6123 * probe(9E) call associated with the transition of a node from
6118 6124 * DS_INITIALIZED to DS_PROBED. The probe(9E) call that eventually
6119 6125 * occurs against the created SID node should find ddi_dev_is_sid and
6120 6126 * just return DDI_PROBE_DONTCARE.
6121 6127 *
6122 6128 * Trying to avoid the use of a barrier node is not a good idea
6123 6129 * because we may have an HBA driver that uses generic bus_config
6124 6130 * (this code) but implements its own DDI_CTLOPS_INITCHILD with side
6125 6131 * effects that we can't duplicate (such as the ATA nexus driver).
6126 6132 *
6127 6133 * The probe/barrier node plays an integral part of the locking scheme.
6128 6134 * The objective is to single thread probes of the same device (same
6129 6135 * @addr) while allowing parallelism for probes of different devices
6130 6136 * with the same parent. At this point we are serialized on our self.
6131 6137 * For parallelism we will need to release our self. Prior to release
6132 6138 * we construct a barrier for probes of the same device to serialize
6133 6139 * against. The "probe@addr" node acts as this barrier. An entering
6134 6140 * thread must wait until the probe node does not exist - it can then
6135 6141 * create and link the probe node - dropping the HBA (self) lock after
6136 6142 * the node is linked and visible (after ddi_initchild). A side effect
6137 6143 * of this is that transports should not "go over the wire" (i.e. do
6138 6144 * things that incur significant delays) until after tran_target_init.
6139 6145 * This means that the first "over the wire" operation should occur
6140 6146 * at tran_target_probe time - when things are running in parallel
6141 6147 * again.
6142 6148 *
6143 6149 * If the probe node exists then another probe with the same @addr is
6144 6150 * in progress, we must wait until there is no probe in progress
6145 6151 * before proceeding, and when we proceed we must continue to hold the
6146 6152 * HBA (self) until we have linked a new probe node as a barrier.
6147 6153 *
6148 6154 * When a device is found to *not* exist, its probe/barrier node may be
6149 6155 * marked with DEVICE_REMOVED with node deletion scheduled for some
6150 6156 * future time (seconds). This asynchronous deletion allows the
6151 6157 * framework to detect repeated requests to the same non-existent
6152 6158 * device and avoid overhead associated with contacting a non-existent
6153 6159 * device again and again.
6154 6160 */
6155 6161 for (;;) {
6156 6162 /*
6157 6163 * Search for probe node - they should only exist as devinfo
6158 6164 * nodes.
6159 6165 */
6160 6166 (void) scsi_findchild(self, "probe", addr,
6161 6167 0, &probe, &psearch, NULL);
6162 6168 if (probe == NULL) {
6163 6169 if (psearch)
6164 6170 SCSI_HBA_LOG((_LOG(2), self,
6165 6171 mdi_pi_get_client(psearch),
6166 6172 "???? @%s 'probe' search found "
6167 6173 "pathinfo: %p", addr, (void *)psearch));
6168 6174 break;
6169 6175 }
6170 6176
6171 6177 /*
6172 6178 * The barrier node may cache the non-existence of a device
6173 6179 * by leaving the barrier node in place (with
6174 6180 * DEVI_DEVICE_REMOVED flag set ) for some amount of time after
6175 6181 * the failure of a probe. This flag is used to fail
6176 6182 * additional probes until the barrier probe node is deleted,
6177 6183 * which will occur from a timeout some time after a failed
6178 6184 * probe. The failed probe will use DEVI_SET_DEVICE_REMOVED
6179 6185 * and schedule probe node deletion from a timeout. The callers
6180 6186 * scsi_hba_devi_exit on the way out of the first failure will
6181 6187 * do the cv_broadcast associated with the cv_wait below - this
6182 6188 * handles threads that wait prior to DEVI_DEVICE_REMOVED being
6183 6189 * set.
6184 6190 */
6185 6191 if (DEVI_IS_DEVICE_REMOVED(probe)) {
6186 6192 SCSI_HBA_LOG((_LOG(3), NULL, probe,
6187 6193 "detected probe DEVICE_REMOVED"));
6188 6194 probe = NULL; /* deletion already scheduled */
6189 6195 goto fail;
6190 6196 }
6191 6197
6192 6198 /*
6193 6199 * Drop the lock on the HBA (self) and wait until the probe in
6194 6200 * progress has completed. A changes in the sibling list from
6195 6201 * removing the probe node will cause cv_wait to return
6196 6202 * (scsi_hba_devi_exit does the cv_broadcast).
6197 6203 */
6198 6204 if (wait_msg) {
6199 6205 wait_msg--;
6200 6206 SCSI_HBA_LOG((_LOG(2), NULL, probe,
6201 6207 "exists, probe already in progress: %s", wait_msg ?
6202 6208 "waiting..." : "last msg, but still waiting..."));
6203 6209 }
6204 6210
6205 6211 /*
6206 6212 * NOTE: we could avoid rare case of one second delay by
6207 6213 * implementing scsi_hba_devi_exit_and_wait based on
6208 6214 * ndi/mdi_devi_exit_and_wait (and consider switching devcfg.c
6209 6215 * code to use these ndi/mdi interfaces too).
6210 6216 */
6211 6217 scsi_hba_devi_exit(self, *circp);
6212 6218 mutex_enter(&DEVI(self)->devi_lock);
6213 6219 (void) cv_timedwait(&DEVI(self)->devi_cv,
6214 6220 &DEVI(self)->devi_lock,
6215 6221 ddi_get_lbolt() + drv_usectohz(MICROSEC));
6216 6222 mutex_exit(&DEVI(self)->devi_lock);
6217 6223 scsi_hba_devi_enter(self, circp);
6218 6224 }
6219 6225 ASSERT(probe == NULL);
6220 6226
6221 6227 /*
6222 6228 * Search to see if we are requesting a SID node that already exists.
6223 6229 * We hold the HBA (self) and there is not another probe in progress at
6224 6230 * the same @addr. scsi_findchild() does not hold the returned
6225 6231 * devinfo node but this is OK since we hold the HBA (self).
6226 6232 */
6227 6233 if (name) {
6228 6234 (void) scsi_findchild(self, name, addr, 1, &dsearch, NULL, &pi);
6229 6235 if (dsearch && scsi_hba_dev_is_sid(dsearch)) {
6230 6236 SCSI_HBA_LOG((_LOG(4), NULL, dsearch,
6231 6237 "%s@%s probe devinfo fastpath",
6232 6238 name ? name : "", addr));
6233 6239 child = dsearch;
6234 6240 goto done;
6235 6241 }
6236 6242 }
6237 6243
6238 6244 /*
6239 6245 * We are looking for a SID node that does not exist or a driver.conf
6240 6246 * node.
6241 6247 *
6242 6248 * To avoid probe side effects, before we probe the device at the
6243 6249 * specified address we need to check to see if there is already an
6244 6250 * initialized child "@addr".
6245 6251 *
6246 6252 * o If we find an initialized SID child and name is NULL or matches
6247 6253 * the name or the name of the attached driver then we return the
6248 6254 * existing node.
6249 6255 *
6250 6256 * o If we find a non-matching SID node, we will attempt to autodetach
6251 6257 * and remove the node in preference to our new node.
6252 6258 *
6253 6259 * o If SID node found does not match and can't be autodetached, we
6254 6260 * fail: we only allow one SID node at an address.
6255 6261 *
6256 6262 * NOTE: This code depends on SID nodes showing up prior to
6257 6263 * driver.conf nodes in the sibling list.
6258 6264 */
6259 6265 for (;;) {
6260 6266 /* first NULL name call is with init set */
6261 6267 (void) scsi_findchild(self, NULL, addr, 1, &dsearch, NULL, &pi);
6262 6268 if (dsearch == NULL)
6263 6269 break;
6264 6270 ASSERT(!scsi_hba_devi_is_barrier(dsearch));
6265 6271
6266 6272 /*
6267 6273 * To detect changes in driver binding that should attempt
6268 6274 * autodetach we determine the major number of the driver
6269 6275 * that should currently be associated with the device based
6270 6276 * on the compatible property.
6271 6277 */
6272 6278 major = DDI_MAJOR_T_NONE;
6273 6279 if (scsi_hba_dev_is_sid(dsearch))
6274 6280 major = ddi_compatible_driver_major(dsearch, NULL);
6275 6281 if ((major == DDI_MAJOR_T_NONE) && (name == NULL))
6276 6282 major = ddi_driver_major(dsearch);
6277 6283
6278 6284 if ((scsi_hba_dev_is_sid(dsearch) ||
6279 6285 (i_ddi_node_state(dsearch) >= DS_INITIALIZED)) &&
6280 6286 ((name == NULL) ||
6281 6287 (strcmp(ddi_node_name(dsearch), name) == 0) ||
6282 6288 (strcmp(ddi_driver_name(dsearch), name) == 0)) &&
6283 6289 (major == ddi_driver_major(dsearch))) {
6284 6290 SCSI_HBA_LOG((_LOG(3), NULL, dsearch,
6285 6291 "already attached @addr"));
6286 6292 child = dsearch;
6287 6293 goto done;
6288 6294 }
6289 6295
6290 6296 if (!scsi_hba_dev_is_sid(dsearch))
6291 6297 break; /* driver.conf node */
6292 6298
6293 6299 /*
6294 6300 * Implement autodetach of SID node for situations like a
6295 6301 * previously "scsinodev" LUN0 coming into existence (or a
6296 6302 * disk/tape on an SPI transport at same addr but never both
6297 6303 * powered on at the same time). Try to autodetach the existing
6298 6304 * SID node @addr. If that works, search again - otherwise fail.
6299 6305 */
6300 6306 SCSI_HBA_LOG((_LOG(2), NULL, dsearch,
6301 6307 "looking for %s@%s: SID @addr exists, autodetach",
6302 6308 name ? name : "", addr));
6303 6309 if (!scsi_hba_remove_node(dsearch)) {
6304 6310 SCSI_HBA_LOG((_LOG(2), NULL, dsearch,
6305 6311 "autodetach @%s failed: fail %s@%s",
6306 6312 addr, name ? name : "", addr));
6307 6313 goto fail;
6308 6314 }
6309 6315 SCSI_HBA_LOG((_LOG(2), self, NULL, "autodetach @%s OK", addr));
6310 6316 }
6311 6317
6312 6318 /*
6313 6319 * We will be creating a new SID node, allocate probe node
6314 6320 * used to find out information about the device located @addr.
6315 6321 * The probe node also acts as a barrier against additional
6316 6322 * configuration at the same address, and in the case of non-existent
6317 6323 * devices it will (for some amount of time) avoid re-learning that
6318 6324 * the device does not exist on every reference. Once the probe
6319 6325 * node is DS_LINKED we can drop the HBA (self).
6320 6326 *
6321 6327 * The probe node is allocated as a hidden node so that it does not
6322 6328 * show up in devinfo snapshots.
6323 6329 */
6324 6330 ndi_devi_alloc_sleep(self, "probe",
6325 6331 (se == SE_HP) ? DEVI_SID_HP_HIDDEN_NODEID : DEVI_SID_HIDDEN_NODEID,
6326 6332 &probe);
6327 6333 ASSERT(probe);
6328 6334 ndi_flavor_set(probe, SCSA_FLAVOR_SCSI_DEVICE);
6329 6335
6330 6336 /*
6331 6337 * Decorate the probe node with the property representation of @addr
6332 6338 * unit-address string prior to initchild so that initchild can
6333 6339 * construct the name of the node from properties and tran_tgt_init
6334 6340 * implementation can determine what LUN is being referenced.
6335 6341 *
6336 6342 * If the addr specified has incorrect syntax (busconfig one of bogus
6337 6343 * /devices path) then scsi_hba_ua_set can fail. If the address
6338 6344 * is not understood by the SCSA HBA driver then this operation will
6339 6345 * work, but tran_tgt_init may still fail (for example the HBA
6340 6346 * driver may not support secondary functions).
6341 6347 */
6342 6348 if (scsi_hba_ua_set(addr, probe, NULL) == 0) {
6343 6349 SCSI_HBA_LOG((_LOG(2), NULL, probe,
6344 6350 "@%s failed scsi_hba_ua_set", addr));
6345 6351 goto fail;
6346 6352 }
6347 6353
6348 6354 /*
6349 6355 * Set the class property to "scsi". This is sufficient to distinguish
6350 6356 * the node for HBAs that have multiple classes of children (like uata
6351 6357 * - which has "dada" class for ATA children and "scsi" class for
6352 6358 * ATAPI children) and may not use our scsi_busctl_initchild()
6353 6359 * implementation. We also add a "compatible" property of "scsiprobe"
6354 6360 * to select the probe driver.
6355 6361 */
6356 6362 if ((ndi_prop_update_string(DDI_DEV_T_NONE, probe,
6357 6363 "class", "scsi") != DDI_PROP_SUCCESS) ||
6358 6364 (ndi_prop_update_string_array(DDI_DEV_T_NONE, probe,
6359 6365 "compatible", &compatible_probe, 1) != DDI_PROP_SUCCESS)) {
6360 6366 SCSI_HBA_LOG((_LOG(1), NULL, probe,
6361 6367 "@%s failed node decoration", addr));
6362 6368 goto fail;
6363 6369 }
6364 6370
6365 6371 /*
6366 6372 * Promote probe node to DS_INITIALIZED so that transport can be used
6367 6373 * for scsi_probe. After this the node is linked and visible as a
6368 6374 * barrier for serialization of other @addr operations.
6369 6375 *
6370 6376 * NOTE: If we attached the probe node, we could get rid of
6371 6377 * uninit_prevent.
6372 6378 */
6373 6379 if (ddi_initchild(self, probe) != DDI_SUCCESS) {
6374 6380 SCSI_HBA_LOG((_LOG(2), NULL, probe,
6375 6381 "@%s failed initchild", addr));
6376 6382
6377 6383 /* probe node will be removed in fail exit path */
6378 6384 goto fail;
6379 6385 }
6380 6386
6381 6387 /* get the scsi_device structure of the probe node */
6382 6388 sdprobe = ddi_get_driver_private(probe);
6383 6389 ASSERT(sdprobe);
6384 6390
6385 6391 /*
6386 6392 * Do scsi_probe. The probe node is linked and visible as a barrier.
6387 6393 * We prevent uninitialization of the probe node and drop our HBA (self)
6388 6394 * while we run scsi_probe() of this "@addr". This allows the framework
6389 6395 * to support multiple scsi_probes for different devices attached to
6390 6396 * the same HBA (self) in parallel. We prevent node demotion of the
6391 6397 * probe node from DS_INITIALIZED by setting sd_uninit_prevent. The
6392 6398 * probe node can not be successfully demoted below DS_INITIALIZED
6393 6399 * (scsi_busctl_uninitchild will fail) until we zero sd_uninit_prevent
6394 6400 * as we are freeing the node via scsi_hba_remove_node(probe).
6395 6401 */
6396 6402 sdprobe->sd_uninit_prevent++;
6397 6403 scsi_hba_devi_exit(self, *circp);
6398 6404 sp = scsi_probe(sdprobe, SLEEP_FUNC);
6399 6405
6400 6406 /* Introduce a small delay here to increase parallelism. */
6401 6407 delay_random(5);
6402 6408
6403 6409 if (sp == SCSIPROBE_EXISTS) {
6404 6410 /*
6405 6411 * For a device that exists, while still running in parallel,
6406 6412 * also get identity information from device. This is done
6407 6413 * separate from scsi_probe/tran_tgt_probe/scsi_hba_probe
6408 6414 * since the probe code path may still be used for HBAs
6409 6415 * that don't use common bus_config services (we don't want
6410 6416 * to expose that code path to a behavior change). This
6411 6417 * operation is called 'identity' to avoid confusion with
6412 6418 * deprecated identify(9E).
6413 6419 *
6414 6420 * Future: We may eventually want to allow HBA customization via
6415 6421 * scsi_identity/tran_tgt_identity/scsi_device_identity, but for
6416 6422 * now we just scsi_device_identity.
6417 6423 *
6418 6424 * The identity operation will establish additional properties
6419 6425 * on the probe node related to device identity:
6420 6426 *
6421 6427 * "inquiry-page-80" byte array of SCSI page 80
6422 6428 * "inquiry-page-83" byte array of SCSI page 83
6423 6429 *
6424 6430 * These properties will be used to generate a devid
6425 6431 * (ddi_devid_scsi_encode) and guid - and to register
6426 6432 * (ddi_devid_register) a devid for the device.
6427 6433 *
6428 6434 * If identify fails (non-zero return), the we had allocation
6429 6435 * problems or the device returned inconsistent results then
6430 6436 * we pretend that device does not exist.
6431 6437 */
6432 6438 if (scsi_device_identity(sdprobe, SLEEP_FUNC)) {
6433 6439 scsi_enumeration_failed(probe, -1, NULL, "identify");
6434 6440 sp = SCSIPROBE_FAILURE;
6435 6441 }
6436 6442
6437 6443 /*
6438 6444 * Future: Is there anything more we can do here to help avoid
6439 6445 * serialization on iport parent during scsi_device attach(9E)?
6440 6446 */
6441 6447 }
6442 6448 scsi_hba_devi_enter(self, circp);
6443 6449 sdprobe->sd_uninit_prevent--;
6444 6450
6445 6451 if (sp != SCSIPROBE_EXISTS) {
6446 6452 scsi_enumeration_failed(probe, -1, NULL, "probe");
6447 6453
6448 6454 if ((se != SE_HP) && scsi_hba_barrier_timeout) {
6449 6455 /*
6450 6456 * Target does not exist. Mark the barrier probe node
6451 6457 * as DEVICE_REMOVED and schedule an asynchronous
6452 6458 * deletion of the node in scsi_hba_barrier_timeout
6453 6459 * seconds. We keep our hold on the probe node
6454 6460 * until we are ready perform the asynchronous node
6455 6461 * deletion.
6456 6462 */
6457 6463 SCSI_HBA_LOG((_LOG(3), NULL, probe,
6458 6464 "set probe DEVICE_REMOVED"));
6459 6465 mutex_enter(&DEVI(probe)->devi_lock);
6460 6466 DEVI_SET_DEVICE_REMOVED(probe);
6461 6467 mutex_exit(&DEVI(probe)->devi_lock);
6462 6468
6463 6469 scsi_hba_barrier_add(probe, scsi_hba_barrier_timeout);
6464 6470 probe = NULL;
6465 6471 }
6466 6472 goto fail;
6467 6473 }
6468 6474
6469 6475 /* Create the child node from the inquiry data in the probe node. */
6470 6476 if ((child = scsi_device_configchild(self, addr, se, sdprobe,
6471 6477 circp, &pi)) == NULL) {
6472 6478 /*
6473 6479 * This may fail because there was no driver binding identified
6474 6480 * via driver_alias. We may still have a conf node.
6475 6481 */
6476 6482 if (name) {
6477 6483 (void) scsi_findchild(self, name, addr,
6478 6484 0, &child, NULL, &pi);
6479 6485 if (child)
6480 6486 SCSI_HBA_LOG((_LOG(2), NULL, child,
6481 6487 "using driver.conf driver binding"));
6482 6488 }
6483 6489 if (child == NULL) {
6484 6490 SCSI_HBA_LOG((_LOG(2), NULL, probe,
6485 6491 "device not configured"));
6486 6492 goto fail;
6487 6493 }
6488 6494 }
6489 6495
6490 6496 /*
6491 6497 * Transfer the inquiry data from the probe node to the child
6492 6498 * SID node to avoid an extra scsi_probe. Callers depend on
6493 6499 * established inquiry data for the returned scsi_device.
6494 6500 */
6495 6501 sdchild = ddi_get_driver_private(child);
6496 6502 if (sdchild && (sdchild->sd_inq == NULL)) {
6497 6503 sdchild->sd_inq = sdprobe->sd_inq;
6498 6504 sdprobe->sd_inq = NULL;
6499 6505 }
6500 6506
6501 6507 /*
6502 6508 * If we are doing a bus_configone and the node we created has the
6503 6509 * wrong node and driver name then switch the return result to a
6504 6510 * driver.conf node with the correct name - if such a node exists.
6505 6511 */
6506 6512 if (name && (strcmp(ddi_node_name(child), name) != 0) &&
6507 6513 (strcmp(ddi_driver_name(child), name) != 0)) {
6508 6514 (void) scsi_findchild(self, name, addr,
6509 6515 0, &dsearch, NULL, &pi);
6510 6516 if (dsearch == NULL) {
6511 6517 SCSI_HBA_LOG((_LOG(2), NULL, child,
6512 6518 "wrong device configured %s@%s", name, addr));
6513 6519 /*
6514 6520 * We can't remove when modrootloaded == 0 in case
6515 6521 * boot-device a uses generic name and
6516 6522 * scsi_hba_nodename_compatible_get() returned a
6517 6523 * legacy binding-set driver oriented name.
6518 6524 */
6519 6525 if (modrootloaded) {
6520 6526 (void) scsi_hba_remove_node(child);
6521 6527 child = NULL;
6522 6528 goto fail;
6523 6529 }
6524 6530 } else {
6525 6531 SCSI_HBA_LOG((_LOG(2), NULL, dsearch,
6526 6532 "device configured, but switching to driver.conf"));
6527 6533 child = dsearch;
6528 6534 }
6529 6535 }
6530 6536
6531 6537 /* get the scsi_device structure from the node */
6532 6538 SCSI_HBA_LOG((_LOG(3), NULL, child, "device configured"));
6533 6539
6534 6540 if (child) {
6535 6541 done: ASSERT(child);
6536 6542 sdchild = ddi_get_driver_private(child);
6537 6543 ASSERT(sdchild);
6538 6544
6539 6545 /*
6540 6546 * We may have ended up here after promotion of a previously
6541 6547 * demoted node, where demotion deleted sd_inq data in
6542 6548 * scsi_busctl_uninitchild. We redo the scsi_probe() to
6543 6549 * reestablish sd_inq. We also want to redo the scsi_probe
6544 6550 * for devices are currently device_isremove in order to
6545 6551 * detect new device_insert.
6546 6552 */
6547 6553 if ((sdchild->sd_inq == NULL) ||
6548 6554 ((pi == NULL) && ndi_devi_device_isremoved(child))) {
6549 6555
6550 6556 /* hotplug_node can only be revived via hotplug. */
6551 6557 if ((se == SE_HP) || !ndi_dev_is_hotplug_node(child)) {
6552 6558 SCSI_HBA_LOG((_LOG(3), NULL, child,
6553 6559 "scsi_probe() demoted devinfo"));
6554 6560
6555 6561 sp = scsi_probe(sdchild, SLEEP_FUNC);
6556 6562
6557 6563 if (sp == SCSIPROBE_EXISTS) {
6558 6564 ASSERT(sdchild->sd_inq);
6559 6565
6560 6566 /*
6561 6567 * Devinfo child exists and we are
6562 6568 * talking to the device, report
6563 6569 * reinsert and note if this was a
6564 6570 * new reinsert.
6565 6571 */
6566 6572 chg = ndi_devi_device_insert(child);
6567 6573 SCSI_HBA_LOG((_LOGCFG, NULL, child,
6568 6574 "devinfo %s@%s device_reinsert%s",
6569 6575 name ? name : "", addr,
6570 6576 chg ? "" : "ed already"));
6571 6577 } else {
6572 6578 scsi_enumeration_failed(child, se,
6573 6579 NULL, "reprobe");
6574 6580
6575 6581 chg = ndi_devi_device_remove(child);
6576 6582 SCSI_HBA_LOG((_LOG(2), NULL, child,
6577 6583 "%s device_remove%s",
6578 6584 (sp > (sizeof (scsi_probe_ascii) /
6579 6585 sizeof (scsi_probe_ascii[0]))) ?
6580 6586 "UNKNOWN" : scsi_probe_ascii[sp],
6581 6587 chg ? "" : "ed already"));
6582 6588
6583 6589 child = NULL;
6584 6590 sdchild = NULL;
6585 6591 }
6586 6592 } else {
6587 6593 SCSI_HBA_LOG((_LOG(2), NULL, child,
6588 6594 "no reprobe"));
6589 6595
6590 6596 child = NULL;
6591 6597 sdchild = NULL;
6592 6598 }
6593 6599 }
6594 6600 } else {
6595 6601 fail: ASSERT(child == NULL);
6596 6602 sdchild = NULL;
6597 6603 }
6598 6604 if (probe) {
6599 6605 /*
6600 6606 * Clean up probe node, destroying node if uninit_prevent
6601 6607 * it is going to zero. Destroying the probe node (deleting
6602 6608 * from the sibling list) will wake up any people waiting on
6603 6609 * the probe node barrier.
6604 6610 */
6605 6611 SCSI_HBA_LOG((_LOG(4), NULL, probe, "remove probe"));
6606 6612 if (!scsi_hba_remove_node(probe)) {
6607 6613 /*
6608 6614 * Probe node removal should not fail, but if it
6609 6615 * does we hand that responsibility over to the
6610 6616 * async barrier deletion thread - other references
6611 6617 * to the same unit-address can hang until the
6612 6618 * probe node delete completes.
6613 6619 */
6614 6620 SCSI_HBA_LOG((_LOG(4), NULL, probe,
6615 6621 "remove probe failed, go async"));
6616 6622 scsi_hba_barrier_add(probe, 1);
6617 6623 }
6618 6624 probe = NULL;
6619 6625 }
6620 6626
6621 6627 /*
6622 6628 * If we successfully resolved via a pathinfo node, we need to find
6623 6629 * the pathinfo node and ensure that it is online (if possible). This
6624 6630 * is done for the case where the device was open when
6625 6631 * scsi_device_unconfig occurred, so mdi_pi_free did not occur. If the
6626 6632 * device has now been reinserted, we want the path back online.
6627 6633 * NOTE: This needs to occur after destruction of the probe node to
6628 6634 * avoid ASSERT related to two nodes at the same unit-address.
6629 6635 */
6630 6636 if (sdchild && pi && (probe == NULL)) {
6631 6637 ASSERT(MDI_PHCI(self));
6632 6638
6633 6639 (void) scsi_findchild(self, NULL, addr,
6634 6640 0, &dsearch, &psearch, NULL);
6635 6641 ASSERT((psearch == NULL) ||
6636 6642 (mdi_pi_get_client(psearch) == child));
6637 6643
6638 6644 if (psearch && mdi_pi_device_isremoved(psearch)) {
6639 6645 /*
6640 6646 * Verify that we can talk to the device, and if
6641 6647 * so note if this is a new device_insert.
6642 6648 *
6643 6649 * NOTE: We depend on mdi_path_select(), when given
6644 6650 * a specific path_instance, to select that path
6645 6651 * even if the path is offline.
6646 6652 *
6647 6653 * NOTE: A Client node is not ndi_dev_is_hotplug_node().
6648 6654 */
6649 6655 if (se == SE_HP) {
6650 6656 SCSI_HBA_LOG((_LOG(3), NULL, child,
6651 6657 "%s scsi_probe() demoted pathinfo",
6652 6658 mdi_pi_spathname(psearch)));
6653 6659
6654 6660 sp = scsi_hba_probe_pi(sdchild, SLEEP_FUNC, pi);
6655 6661
6656 6662 if (sp == SCSIPROBE_EXISTS) {
6657 6663 /*
6658 6664 * Pathinfo child exists and we are
6659 6665 * talking to the device, report
6660 6666 * reinsert and note if this
6661 6667 * was a new reinsert.
6662 6668 */
6663 6669 chg = mdi_pi_device_insert(psearch);
6664 6670 SCSI_HBA_LOG((_LOGCFG, self, NULL,
6665 6671 "pathinfo %s device_reinsert%s",
6666 6672 mdi_pi_spathname(psearch),
6667 6673 chg ? "" : "ed already"));
6668 6674
6669 6675 if (chg)
6670 6676 (void) mdi_pi_online(psearch,
6671 6677 0);
6672 6678
6673 6679 /*
6674 6680 * Report client reinsert and note if
6675 6681 * this was a new reinsert.
6676 6682 */
6677 6683 chg = ndi_devi_device_insert(child);
6678 6684 SCSI_HBA_LOG((_LOGCFG, NULL, child,
6679 6685 "client devinfo %s@%s "
6680 6686 "device_reinsert%s",
6681 6687 name ? name : "", addr,
6682 6688 chg ? "" : "ed already"));
6683 6689 } else {
6684 6690 scsi_enumeration_failed(child, se,
6685 6691 mdi_pi_spathname(psearch),
6686 6692 "reprobe");
6687 6693 child = NULL;
6688 6694 sdchild = NULL;
6689 6695 }
6690 6696
6691 6697 } else {
6692 6698 SCSI_HBA_LOG((_LOG(2), NULL, child,
6693 6699 "%s no reprobe",
6694 6700 mdi_pi_spathname(psearch)));
6695 6701
6696 6702 child = NULL;
6697 6703 sdchild = NULL;
6698 6704 }
6699 6705 }
6700 6706 }
6701 6707
6702 6708 /* If asked for path_instance, return it. */
6703 6709 if (ppi)
6704 6710 *ppi = pi;
6705 6711
6706 6712 return (sdchild);
6707 6713 }
6708 6714
6709 6715 static void
6710 6716 scsi_device_unconfig(dev_info_t *self, char *name, char *addr, int *circp)
6711 6717 {
6712 6718 dev_info_t *child = NULL;
6713 6719 mdi_pathinfo_t *path = NULL;
6714 6720 char *spathname;
6715 6721 int rval;
6716 6722
6717 6723 ASSERT(self && addr && DEVI_BUSY_OWNED(self));
6718 6724
6719 6725 /*
6720 6726 * We have a catch-22. We may have a demoted node that we need to find
6721 6727 * and offline/remove. To find the node if it isn't demoted, we
6722 6728 * use scsi_findchild. If it's demoted, we then use
6723 6729 * ndi_devi_findchild_by_callback.
6724 6730 */
6725 6731 (void) scsi_findchild(self, name, addr, 0, &child, &path, NULL);
6726 6732
6727 6733 if ((child == NULL) && (path == NULL)) {
6728 6734 child = ndi_devi_findchild_by_callback(self, name, addr,
6729 6735 scsi_busctl_ua);
6730 6736 if (child) {
6731 6737 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6732 6738 "devinfo %s@%s found by callback",
6733 6739 name ? name : "", addr));
6734 6740 ASSERT(ndi_flavor_get(child) ==
6735 6741 SCSA_FLAVOR_SCSI_DEVICE);
6736 6742 if (ndi_flavor_get(child) != SCSA_FLAVOR_SCSI_DEVICE) {
6737 6743 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6738 6744 "devinfo %s@%s not SCSI_DEVICE flavored",
6739 6745 name ? name : "", addr));
6740 6746 child = NULL;
6741 6747 }
6742 6748 }
6743 6749 }
6744 6750
6745 6751 if (child) {
6746 6752 ASSERT(child && (path == NULL));
6747 6753
6748 6754 /* Don't unconfig probe nodes. */
6749 6755 if (scsi_hba_devi_is_barrier(child)) {
6750 6756 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6751 6757 "devinfo %s@%s is_barrier, skip",
6752 6758 name ? name : "", addr));
6753 6759 return;
6754 6760 }
6755 6761
6756 6762 /* Attempt to offline/remove the devinfo node */
6757 6763 if (ndi_devi_offline(child,
6758 6764 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) {
6759 6765 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6760 6766 "devinfo %s@%s offlined and removed",
6761 6767 name ? name : "", addr));
6762 6768 } else if (ndi_devi_device_remove(child)) {
6763 6769 /* Offline/remove failed, note new device_remove */
6764 6770 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6765 6771 "devinfo %s@%s offline failed, device_remove",
6766 6772 name ? name : "", addr));
6767 6773 }
6768 6774 } else if (path) {
6769 6775 ASSERT(path && (child == NULL));
6770 6776
6771 6777 /*
6772 6778 * Attempt to offline/remove the pathinfo node.
6773 6779 *
6774 6780 * NOTE: mdi_pi_offline of last path will fail if the
6775 6781 * device is open (i.e. the client can't be offlined).
6776 6782 *
6777 6783 * NOTE: For mdi there is no REMOVE flag for mdi_pi_offline().
6778 6784 * When mdi_pi_offline returns MDI_SUCCESS, we are responsible
6779 6785 * for remove via mdi_pi_free().
6780 6786 */
6781 6787 mdi_hold_path(path);
6782 6788 spathname = mdi_pi_spathname(path); /* valid after free */
6783 6789 scsi_hba_devi_exit_phci(self, *circp);
6784 6790 rval = mdi_pi_offline(path, 0);
6785 6791 scsi_hba_devi_enter_phci(self, circp);
6786 6792
6787 6793 /* Note new device_remove */
6788 6794 if (mdi_pi_device_remove(path))
6789 6795 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6790 6796 "pathinfo %s note device_remove", spathname));
6791 6797
6792 6798 mdi_rele_path(path);
6793 6799 if (rval == MDI_SUCCESS) {
6794 6800 (void) mdi_pi_free(path, 0);
6795 6801 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6796 6802 "pathinfo %s offlined, then freed", spathname));
6797 6803 }
6798 6804 } else {
6799 6805 ASSERT((path == NULL) && (child == NULL));
6800 6806
6801 6807 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
6802 6808 "%s@%s not found", name ? name : "", addr));
6803 6809 }
6804 6810 }
6805 6811
6806 6812 /*
6807 6813 * configure the device at the specified "@addr" address.
6808 6814 */
6809 6815 static struct scsi_device *
6810 6816 scsi_hba_bus_configone_addr(dev_info_t *self, char *addr, scsi_enum_t se)
6811 6817 {
6812 6818 int circ;
6813 6819 struct scsi_device *sd;
6814 6820
6815 6821 scsi_hba_devi_enter(self, &circ);
6816 6822 sd = scsi_device_config(self, NULL, addr, se, &circ, NULL);
6817 6823 scsi_hba_devi_exit(self, circ);
6818 6824 return (sd);
6819 6825 }
6820 6826
6821 6827 /*
6822 6828 * unconfigure the device at the specified "@addr" address.
6823 6829 */
6824 6830 static void
6825 6831 scsi_hba_bus_unconfigone_addr(dev_info_t *self, char *addr)
6826 6832 {
6827 6833 int circ;
6828 6834
6829 6835 scsi_hba_devi_enter(self, &circ);
6830 6836 (void) scsi_device_unconfig(self, NULL, addr, &circ);
6831 6837 scsi_hba_devi_exit(self, circ);
6832 6838 }
6833 6839
6834 6840 /*
6835 6841 * The bus_config_all operations are multi-threaded for performance. A
6836 6842 * separate thread per target and per LUN is used. The config handle is used
6837 6843 * to coordinate all the threads at a given level and the config thread data
6838 6844 * contains the required information for a specific thread to identify what it
6839 6845 * is processing and the handle under which this is being processed.
6840 6846 */
6841 6847
6842 6848 /* multi-threaded config handle */
6843 6849 struct scsi_hba_mte_h {
6844 6850 dev_info_t *h_self; /* initiator port */
6845 6851 int h_thr_count;
6846 6852 kmutex_t h_lock;
6847 6853 kcondvar_t h_cv;
6848 6854 };
6849 6855
6850 6856 /* target of 'self' config thread data */
6851 6857 struct scsi_hba_mte_td {
6852 6858 struct scsi_hba_mte_h *td_h;
6853 6859 char *td_taddr; /* target port */
6854 6860 int td_mt;
6855 6861 scsi_enum_t td_se;
6856 6862 };
6857 6863
6858 6864 /* Invoke callback on a vector of taddrs from multiple threads */
6859 6865 static void
6860 6866 scsi_hba_thread_taddrs(dev_info_t *self, char **taddrs, int mt,
6861 6867 scsi_enum_t se, void (*callback)(void *arg))
6862 6868 {
6863 6869 struct scsi_hba_mte_h *h; /* HBA header */
6864 6870 struct scsi_hba_mte_td *td; /* target data */
6865 6871 char **taddr;
6866 6872
6867 6873 /* allocate and initialize the handle */
6868 6874 h = kmem_zalloc(sizeof (*h), KM_SLEEP);
6869 6875 mutex_init(&h->h_lock, NULL, MUTEX_DEFAULT, NULL);
6870 6876 cv_init(&h->h_cv, NULL, CV_DEFAULT, NULL);
6871 6877 h->h_self = self;
6872 6878
6873 6879 /* loop over all the targets */
6874 6880 for (taddr = taddrs; *taddr; taddr++) {
6875 6881 /* allocate a thread data structure for target */
6876 6882 td = kmem_alloc(sizeof (*td), KM_SLEEP);
6877 6883 td->td_h = h;
6878 6884 td->td_taddr = *taddr;
6879 6885 td->td_mt = mt;
6880 6886 td->td_se = se;
6881 6887
6882 6888 /* process the target */
6883 6889 mutex_enter(&h->h_lock);
6884 6890 h->h_thr_count++;
6885 6891 mutex_exit(&h->h_lock);
6886 6892
6887 6893 if (mt & SCSI_ENUMERATION_MT_TARGET_DISABLE)
6888 6894 callback((void *)td);
6889 6895 else
6890 6896 (void) thread_create(NULL, 0, callback, (void *)td,
6891 6897 0, &p0, TS_RUN, minclsyspri);
6892 6898 }
6893 6899
6894 6900 /* wait for all the target threads to complete */
6895 6901 mutex_enter(&h->h_lock);
6896 6902 while (h->h_thr_count > 0)
6897 6903 cv_wait(&h->h_cv, &h->h_lock);
6898 6904 mutex_exit(&h->h_lock);
6899 6905
6900 6906 /* free the handle */
6901 6907 cv_destroy(&h->h_cv);
6902 6908 mutex_destroy(&h->h_lock);
6903 6909 kmem_free(h, sizeof (*h));
6904 6910 }
6905 6911
6906 6912
6907 6913 /* lun/secondary function of lun0 config thread data */
6908 6914 struct scsi_hba_mte_ld {
6909 6915 struct scsi_hba_mte_h *ld_h;
6910 6916 char *ld_taddr; /* target port */
6911 6917 scsi_lun64_t ld_lun64; /* lun */
6912 6918 int ld_sfunc; /* secondary function */
6913 6919 scsi_enum_t ld_se;
6914 6920 };
6915 6921
6916 6922 /*
6917 6923 * Enumerate the LUNs and secondary functions of the specified target. The
6918 6924 * target portion of the "@addr" is already represented as a string in the
6919 6925 * thread data, we add a ",lun" representation to this and perform a
6920 6926 * bus_configone byte of enumeration on that "@addr".
6921 6927 */
6922 6928 static void
6923 6929 scsi_hba_enum_lsf_of_tgt_thr(void *arg)
6924 6930 {
6925 6931 struct scsi_hba_mte_ld *ld = (struct scsi_hba_mte_ld *)arg;
6926 6932 struct scsi_hba_mte_h *h = ld->ld_h;
6927 6933 dev_info_t *self = h->h_self;
6928 6934 char addr[SCSI_MAXNAMELEN];
6929 6935
6930 6936 /* make string form of "@taddr,lun[,sfunc]" and see if it exists */
6931 6937 if (ld->ld_sfunc == -1)
6932 6938 (void) snprintf(addr, sizeof (addr),
6933 6939 "%s,%" PRIx64, ld->ld_taddr, ld->ld_lun64);
6934 6940 else
6935 6941 (void) snprintf(addr, sizeof (addr),
6936 6942 "%s,%" PRIx64 ",%x",
6937 6943 ld->ld_taddr, ld->ld_lun64, ld->ld_sfunc);
6938 6944
6939 6945 /* configure device at that unit-address address */
6940 6946 (void) scsi_hba_bus_configone_addr(self, addr, ld->ld_se);
6941 6947
6942 6948 /* signal completion of this LUN thread to the target */
6943 6949 mutex_enter(&h->h_lock);
6944 6950 if (--h->h_thr_count == 0)
6945 6951 cv_broadcast(&h->h_cv);
6946 6952 mutex_exit(&h->h_lock);
6947 6953
6948 6954 /* free config thread data */
6949 6955 kmem_free(ld, sizeof (*ld));
6950 6956 }
6951 6957
6952 6958 /* Format of SCSI REPORT_LUNS report */
6953 6959 typedef struct scsi_lunrpt {
6954 6960 uchar_t lunrpt_len_msb; /* # LUNs being reported */
6955 6961 uchar_t lunrpt_len_mmsb;
6956 6962 uchar_t lunrpt_len_mlsb;
6957 6963 uchar_t lunrpt_len_lsb;
6958 6964 uchar_t lunrpt_reserved[4];
6959 6965 scsi_lun_t lunrpt_luns[1]; /* LUNs, variable size */
6960 6966 } scsi_lunrpt_t;
6961 6967
6962 6968 /*
6963 6969 * scsi_device_reportluns()
6964 6970 *
6965 6971 * Callers of this routine should ensure that the 'sd0' scsi_device structure
6966 6972 * and 'pi' path_instance specified are associated with a responding LUN0.
6967 6973 * This should not be called for SCSI-1 devices.
6968 6974 *
6969 6975 * To get a LUN report, we must allocate a buffer. To know how big to make the
6970 6976 * buffer, we must know the number of LUNs. To know the number of LUNs, we must
6971 6977 * get a LUN report. We first issue a SCMD_REPORT_LUNS command using a
6972 6978 * reasonably sized buffer that's big enough to report all LUNs for most
6973 6979 * typical devices. If it turns out that we needed a bigger buffer, we attempt
6974 6980 * to allocate a buffer of sufficient size, and reissue the command. If the
6975 6981 * first command succeeds, but the second fails, we return whatever we were
6976 6982 * able to get the first time. We return enough information for the caller to
6977 6983 * tell whether they got all the LUNs or only a subset.
6978 6984 *
6979 6985 * If successful, we allocate an array of scsi_lun_t to hold the results. The
6980 6986 * caller must kmem_free(*lunarrayp, *sizep) when finished with it. Upon
6981 6987 * successful return return value is NDI_SUCCESS and:
6982 6988 *
6983 6989 * *lunarrayp points to the allocated array,
6984 6990 * *nlunsp is the number of valid LUN entries in the array,
6985 6991 * *tlunsp is the total number of LUNs in the target,
6986 6992 * *sizep is the size of the lunarrayp array, which must be freed.
6987 6993 *
6988 6994 * If the *nlunsp is less than *tlunsp, then we were only able to retrieve a
6989 6995 * subset of the total set of LUNs in the target.
6990 6996 */
6991 6997 static int
6992 6998 scsi_device_reportluns(struct scsi_device *sd0, char *taddr, int pi,
6993 6999 scsi_lun_t **lunarrayp, uint32_t *nlunsp, uint32_t *tlunsp, size_t *sizep)
6994 7000 {
6995 7001 struct buf *lunrpt_bp;
6996 7002 struct scsi_pkt *lunrpt_pkt;
6997 7003 scsi_lunrpt_t *lunrpt;
6998 7004 uint32_t bsize;
6999 7005 uint32_t tluns, nluns;
7000 7006 int default_maxluns = scsi_lunrpt_default_max;
7001 7007 dev_info_t *child;
7002 7008
7003 7009 ASSERT(sd0 && lunarrayp && nlunsp && tlunsp && sizep);
7004 7010
7005 7011 /*
7006 7012 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7007 7013 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7008 7014 * of a child of the 'self' pHCI we are enumerating.
7009 7015 */
7010 7016 child = sd0->sd_dev;
7011 7017
7012 7018 /* first try, look for up to scsi_lunrpt_default_max LUNs */
7013 7019 nluns = default_maxluns;
7014 7020
7015 7021 again: bsize = sizeof (struct scsi_lunrpt) +
7016 7022 ((nluns - 1) * sizeof (struct scsi_lun));
7017 7023
7018 7024 lunrpt_bp = scsi_alloc_consistent_buf(&sd0->sd_address,
7019 7025 (struct buf *)NULL, bsize, B_READ, SLEEP_FUNC, NULL);
7020 7026 if (lunrpt_bp == NULL) {
7021 7027 SCSI_HBA_LOG((_LOG(1), NULL, child, "failed alloc"));
7022 7028 return (NDI_NOMEM);
7023 7029 }
7024 7030
7025 7031 lunrpt_pkt = scsi_init_pkt(&sd0->sd_address,
7026 7032 (struct scsi_pkt *)NULL, lunrpt_bp, CDB_GROUP5,
7027 7033 sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT,
7028 7034 SLEEP_FUNC, NULL);
7029 7035 if (lunrpt_pkt == NULL) {
7030 7036 SCSI_HBA_LOG((_LOG(1), NULL, child, "failed init"));
7031 7037 scsi_free_consistent_buf(lunrpt_bp);
7032 7038 return (NDI_NOMEM);
7033 7039 }
7034 7040
7035 7041 (void) scsi_setup_cdb((union scsi_cdb *)lunrpt_pkt->pkt_cdbp,
7036 7042 SCMD_REPORT_LUNS, 0, bsize, 0);
7037 7043
7038 7044 lunrpt_pkt->pkt_time = scsi_lunrpt_timeout;
7039 7045
7040 7046 /*
7041 7047 * When sd0 is a vHCI scsi device, we need reportlun to be issued
7042 7048 * against a specific LUN0 path_instance that we are enumerating.
7043 7049 */
7044 7050 lunrpt_pkt->pkt_path_instance = pi;
7045 7051 lunrpt_pkt->pkt_flags |= FLAG_PKT_PATH_INSTANCE;
7046 7052
7047 7053 /*
7048 7054 * NOTE: scsi_poll may not allow HBA specific recovery from TRAN_BUSY.
7049 7055 */
7050 7056 if (scsi_poll(lunrpt_pkt) < 0) {
7051 7057 SCSI_HBA_LOG((_LOG(2), NULL, child, "reportlun not supported"));
7052 7058 scsi_destroy_pkt(lunrpt_pkt);
7053 7059 scsi_free_consistent_buf(lunrpt_bp);
7054 7060 return (NDI_FAILURE);
7055 7061 }
7056 7062
7057 7063 scsi_destroy_pkt(lunrpt_pkt);
7058 7064
7059 7065 lunrpt = (scsi_lunrpt_t *)lunrpt_bp->b_un.b_addr;
7060 7066
7061 7067 /* Compute the total number of LUNs in the target */
7062 7068 tluns = (((uint_t)lunrpt->lunrpt_len_msb << 24) |
7063 7069 ((uint_t)lunrpt->lunrpt_len_mmsb << 16) |
7064 7070 ((uint_t)lunrpt->lunrpt_len_mlsb << 8) |
7065 7071 ((uint_t)lunrpt->lunrpt_len_lsb)) >> 3;
7066 7072
7067 7073 if (tluns == 0) {
7068 7074 /* Illegal response -- this target is broken */
7069 7075 SCSI_HBA_LOG((_LOG(1), NULL, child, "illegal tluns of zero"));
7070 7076 scsi_free_consistent_buf(lunrpt_bp);
7071 7077 return (DDI_NOT_WELL_FORMED);
7072 7078 }
7073 7079
7074 7080 if (tluns > nluns) {
7075 7081 /* have more than we allocated space for */
7076 7082 if (nluns == default_maxluns) {
7077 7083 /* first time around, reallocate larger */
7078 7084 scsi_free_consistent_buf(lunrpt_bp);
7079 7085 nluns = tluns;
7080 7086 goto again;
7081 7087 }
7082 7088
7083 7089 /* uh oh, we got a different tluns the second time! */
7084 7090 SCSI_HBA_LOG((_LOG(1), NULL, child,
7085 7091 "tluns changed from %d to %d", nluns, tluns));
7086 7092 } else
7087 7093 nluns = tluns;
7088 7094
7089 7095 /*
7090 7096 * Now we have:
7091 7097 * lunrpt_bp is the buffer we're using;
7092 7098 * tluns is the total number of LUNs the target says it has;
7093 7099 * nluns is the number of LUNs we were able to get into the buffer.
7094 7100 *
7095 7101 * Copy the data out of scarce iopb memory into regular kmem.
7096 7102 * The caller must kmem_free(*lunarrayp, *sizep) when finished with it.
7097 7103 */
7098 7104 *lunarrayp = (scsi_lun_t *)kmem_alloc(
7099 7105 nluns * sizeof (scsi_lun_t), KM_SLEEP);
7100 7106 if (*lunarrayp == NULL) {
7101 7107 SCSI_HBA_LOG((_LOG(1), NULL, child, "NULL lunarray"));
7102 7108 scsi_free_consistent_buf(lunrpt_bp);
7103 7109 return (NDI_NOMEM);
7104 7110 }
7105 7111
7106 7112 *sizep = nluns * sizeof (scsi_lun_t);
7107 7113 *nlunsp = nluns;
7108 7114 *tlunsp = tluns;
7109 7115 bcopy((void *)&lunrpt->lunrpt_luns, (void *)*lunarrayp, *sizep);
7110 7116 scsi_free_consistent_buf(lunrpt_bp);
7111 7117 SCSI_HBA_LOG((_LOG(3), NULL, child,
7112 7118 "@%s,0 path %d: %d/%d luns", taddr, pi, nluns, tluns));
7113 7119 return (NDI_SUCCESS);
7114 7120 }
7115 7121
7116 7122 /*
7117 7123 * Enumerate all the LUNs and secondary functions of the specified 'taddr'
7118 7124 * target port as accessed via 'self' pHCI. Note that sd0 may be associated
7119 7125 * with a child of the vHCI instead of 'self' - in this case the 'pi'
7120 7126 * path_instance is used to ensure that the SCMD_REPORT_LUNS command is issued
7121 7127 * through the 'self' pHCI path.
7122 7128 *
7123 7129 * We multi-thread across all the LUNs and secondary functions and enumerate
7124 7130 * them. Which LUNs exist is based on SCMD_REPORT_LUNS data.
7125 7131 *
7126 7132 * The scsi_device we are called with should be for LUN0 and has been probed.
7127 7133 *
7128 7134 * This function is structured so that an HBA that has a different target
7129 7135 * addressing structure can still use this function to enumerate the its
7130 7136 * LUNs if it uses "taddr,lun" for its LUN space.
7131 7137 *
7132 7138 * We make assumptions about other LUNs associated with the target:
7133 7139 *
7134 7140 * For SCSI-2 and SCSI-3 target we will issue the SCSI report_luns
7135 7141 * command. If this fails or we have a SCSI-1 then the number of
7136 7142 * LUNs is determined based on SCSI_OPTIONS_NLUNS. For a SCSI-1
7137 7143 * target we never probe above LUN 8, even if SCSI_OPTIONS_NLUNS
7138 7144 * indicates we should.
7139 7145 *
7140 7146 * HBA drivers wanting a different set of assumptions should implement their
7141 7147 * own LUN enumeration code.
7142 7148 */
7143 7149 static int
7144 7150 scsi_hba_enum_lsf_of_t(struct scsi_device *sd0,
7145 7151 dev_info_t *self, char *taddr, int pi, int mt, scsi_enum_t se)
7146 7152 {
7147 7153 dev_info_t *child;
7148 7154 scsi_hba_tran_t *tran;
7149 7155 impl_scsi_tgtmap_t *tgtmap;
7150 7156 damap_id_t tgtid;
7151 7157 damap_t *tgtdam;
7152 7158 damap_t *lundam = NULL;
7153 7159 struct scsi_hba_mte_h *h;
7154 7160 struct scsi_hba_mte_ld *ld;
7155 7161 int aver;
7156 7162 scsi_lun_t *lunp = NULL;
7157 7163 int lun;
7158 7164 uint32_t nluns;
7159 7165 uint32_t tluns;
7160 7166 size_t size;
7161 7167 scsi_lun64_t lun64;
7162 7168 int maxluns;
7163 7169
7164 7170 /*
7165 7171 * If LUN0 failed then we have no other LUNs.
7166 7172 *
7167 7173 * NOTE: We need sd_inq to be valid to check ansi version. Since
7168 7174 * scsi_unprobe is now a noop (sd_inq freeded in
7169 7175 * scsi_busctl_uninitchild) sd_inq remains valid even if a target
7170 7176 * driver detach(9E) occurs, resulting in a scsi_unprobe call
7171 7177 * (sd_uninit_prevent keeps sd_inq valid by failing any
7172 7178 * device_uninitchild attempts).
7173 7179 */
7174 7180 ASSERT(sd0 && sd0->sd_uninit_prevent && sd0->sd_dev && sd0->sd_inq);
7175 7181 if ((sd0 == NULL) || (sd0->sd_dev == NULL) || (sd0->sd_inq == NULL)) {
7176 7182 SCSI_HBA_LOG((_LOG(1), NULL, sd0 ? sd0->sd_dev : NULL,
7177 7183 "not setup correctly:%s%s%s",
7178 7184 (sd0 == NULL) ? " device" : "",
7179 7185 (sd0 && (sd0->sd_dev == NULL)) ? " dip" : "",
7180 7186 (sd0 && (sd0->sd_inq == NULL)) ? " inq" : ""));
7181 7187 return (DDI_FAILURE);
7182 7188 }
7183 7189
7184 7190 /*
7185 7191 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7186 7192 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7187 7193 * of a child of the 'self' pHCI we are enumerating.
7188 7194 */
7189 7195 child = sd0->sd_dev;
7190 7196
7191 7197 /* Determine if we are reporting lun observations into lunmap. */
7192 7198 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
7193 7199 tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap;
7194 7200 if (tgtmap) {
7195 7201 tgtdam = tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE];
7196 7202 tgtid = damap_lookup(tgtdam, taddr);
7197 7203 if (tgtid != NODAM) {
7198 7204 lundam = damap_id_priv_get(tgtdam, tgtid);
7199 7205 damap_id_rele(tgtdam, tgtid);
7200 7206 ASSERT(lundam);
7201 7207 }
7202 7208 }
7203 7209
7204 7210 if (lundam) {
7205 7211 /* If using lunmap, start the observation */
7206 7212 scsi_lunmap_set_begin(self, lundam);
7207 7213 } else {
7208 7214 /* allocate and initialize the LUN handle */
7209 7215 h = kmem_zalloc(sizeof (*h), KM_SLEEP);
7210 7216 mutex_init(&h->h_lock, NULL, MUTEX_DEFAULT, NULL);
7211 7217 cv_init(&h->h_cv, NULL, CV_DEFAULT, NULL);
7212 7218 h->h_self = self;
7213 7219 }
7214 7220
7215 7221 /* See if SCMD_REPORT_LUNS works for SCSI-2 and beyond */
7216 7222 aver = sd0->sd_inq->inq_ansi;
7217 7223 if ((aver >= SCSI_VERSION_2) && (scsi_device_reportluns(sd0,
7218 7224 taddr, pi, &lunp, &nluns, &tluns, &size) == NDI_SUCCESS)) {
7219 7225
7220 7226 ASSERT(lunp && (size > 0) && (nluns > 0) && (tluns > 0));
7221 7227
7222 7228 /* loop over the reported LUNs */
7223 7229 SCSI_HBA_LOG((_LOG(2), NULL, child,
7224 7230 "@%s,0 path %d: enumerating %d reported lun%s", taddr, pi,
7225 7231 nluns, nluns > 1 ? "s" : ""));
7226 7232
7227 7233 for (lun = 0; lun < nluns; lun++) {
7228 7234 lun64 = scsi_lun_to_lun64(lunp[lun]);
7229 7235
7230 7236 if (lundam) {
7231 7237 if (scsi_lunmap_set_add(self, lundam,
7232 7238 taddr, lun64, -1) != DDI_SUCCESS) {
7233 7239 SCSI_HBA_LOG((_LOG_NF(WARN),
7234 7240 "@%s,%" PRIx64 " failed to create",
7235 7241 taddr, lun64));
7236 7242 }
7237 7243 } else {
7238 7244 if (lun64 == 0)
7239 7245 continue;
7240 7246
7241 7247 /* allocate a thread data structure for LUN */
7242 7248 ld = kmem_alloc(sizeof (*ld), KM_SLEEP);
7243 7249 ld->ld_h = h;
7244 7250 ld->ld_taddr = taddr;
7245 7251 ld->ld_lun64 = lun64;
7246 7252 ld->ld_sfunc = -1;
7247 7253 ld->ld_se = se;
7248 7254
7249 7255 /* process the LUN */
7250 7256 mutex_enter(&h->h_lock);
7251 7257 h->h_thr_count++;
7252 7258 mutex_exit(&h->h_lock);
7253 7259
7254 7260 if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE)
7255 7261 scsi_hba_enum_lsf_of_tgt_thr(
7256 7262 (void *)ld);
7257 7263 else
7258 7264 (void) thread_create(NULL, 0,
7259 7265 scsi_hba_enum_lsf_of_tgt_thr,
7260 7266 (void *)ld, 0, &p0, TS_RUN,
7261 7267 minclsyspri);
7262 7268 }
7263 7269 }
7264 7270
7265 7271 /* free the LUN array allocated by scsi_device_reportluns */
7266 7272 kmem_free(lunp, size);
7267 7273 } else {
7268 7274 /* Determine the number of LUNs to enumerate. */
7269 7275 maxluns = scsi_get_scsi_maxluns(sd0);
7270 7276
7271 7277 /* Couldn't get SCMD_REPORT_LUNS data */
7272 7278 if (aver >= SCSI_VERSION_3) {
7273 7279 scsi_enumeration_failed(child, se, taddr, "report_lun");
7274 7280
7275 7281 /*
7276 7282 * Based on calling context tunable, only enumerate one
7277 7283 * lun (lun0) if scsi_device_reportluns() fails on a
7278 7284 * SCSI_VERSION_3 or greater device.
7279 7285 */
7280 7286 if (scsi_lunrpt_failed_do1lun & (1 << se))
7281 7287 maxluns = 1;
7282 7288 }
7283 7289
7284 7290 /* loop over possible LUNs, skipping LUN0 */
7285 7291 if (maxluns > 1)
7286 7292 SCSI_HBA_LOG((_LOG(2), NULL, child,
7287 7293 "@%s,0 path %d: enumerating luns 1-%d", taddr, pi,
7288 7294 maxluns - 1));
7289 7295 else
7290 7296 SCSI_HBA_LOG((_LOG(2), NULL, child,
7291 7297 "@%s,0 path %d: enumerating just lun0", taddr, pi));
7292 7298
7293 7299 for (lun64 = 0; lun64 < maxluns; lun64++) {
7294 7300 if (lundam) {
7295 7301 if (scsi_lunmap_set_add(self, lundam,
7296 7302 taddr, lun64, -1) != DDI_SUCCESS) {
7297 7303 SCSI_HBA_LOG((_LOG_NF(WARN),
7298 7304 "@%s,%" PRIx64 " failed to create",
7299 7305 taddr, lun64));
7300 7306 }
7301 7307 } else {
7302 7308 if (lun64 == 0)
7303 7309 continue;
7304 7310
7305 7311 /* allocate a thread data structure for LUN */
7306 7312 ld = kmem_alloc(sizeof (*ld), KM_SLEEP);
7307 7313 ld->ld_h = h;
7308 7314 ld->ld_taddr = taddr;
7309 7315 ld->ld_lun64 = lun64;
7310 7316 ld->ld_sfunc = -1;
7311 7317 ld->ld_se = se;
7312 7318
7313 7319 /* process the LUN */
7314 7320 mutex_enter(&h->h_lock);
7315 7321 h->h_thr_count++;
7316 7322 mutex_exit(&h->h_lock);
7317 7323 if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE)
7318 7324 scsi_hba_enum_lsf_of_tgt_thr(
7319 7325 (void *)ld);
7320 7326 else
7321 7327 (void) thread_create(NULL, 0,
7322 7328 scsi_hba_enum_lsf_of_tgt_thr,
7323 7329 (void *)ld, 0, &p0, TS_RUN,
7324 7330 minclsyspri);
7325 7331 }
7326 7332 }
7327 7333 }
7328 7334
7329 7335 /*
7330 7336 * If we have an embedded service as a secondary function on LUN0 and
7331 7337 * the primary LUN0 function is different than the secondary function
7332 7338 * then enumerate the secondary function. The sfunc value is the dtype
7333 7339 * associated with the embedded service.
7334 7340 *
7335 7341 * inq_encserv: enclosure service and our dtype is not DTYPE_ESI
7336 7342 * or DTYPE_UNKNOWN then create a separate DTYPE_ESI node for
7337 7343 * enclosure service access.
7338 7344 */
7339 7345 ASSERT(sd0->sd_inq);
7340 7346 if (sd0->sd_inq->inq_encserv &&
7341 7347 ((sd0->sd_inq->inq_dtype & DTYPE_MASK) != DTYPE_UNKNOWN) &&
7342 7348 ((sd0->sd_inq->inq_dtype & DTYPE_MASK) != DTYPE_ESI) &&
7343 7349 ((sd0->sd_inq->inq_ansi >= SCSI_VERSION_3))) {
7344 7350 if (lundam) {
7345 7351 if (scsi_lunmap_set_add(self, lundam,
7346 7352 taddr, 0, DTYPE_ESI) != DDI_SUCCESS) {
7347 7353 SCSI_HBA_LOG((_LOG_NF(WARN),
7348 7354 "@%s,0,%x failed to create",
7349 7355 taddr, DTYPE_ESI));
7350 7356 }
7351 7357 } else {
7352 7358 /* allocate a thread data structure for sfunc */
7353 7359 ld = kmem_alloc(sizeof (*ld), KM_SLEEP);
7354 7360 ld->ld_h = h;
7355 7361 ld->ld_taddr = taddr;
7356 7362 ld->ld_lun64 = 0;
7357 7363 ld->ld_sfunc = DTYPE_ESI;
7358 7364 ld->ld_se = se;
7359 7365
7360 7366 /* process the LUN */
7361 7367 mutex_enter(&h->h_lock);
7362 7368 h->h_thr_count++;
7363 7369 mutex_exit(&h->h_lock);
7364 7370 if (mt & SCSI_ENUMERATION_MT_LUN_DISABLE)
7365 7371 scsi_hba_enum_lsf_of_tgt_thr((void *)ld);
7366 7372 else
7367 7373 (void) thread_create(NULL, 0,
7368 7374 scsi_hba_enum_lsf_of_tgt_thr, (void *)ld,
7369 7375 0, &p0, TS_RUN, minclsyspri);
7370 7376 }
7371 7377 }
7372 7378
7373 7379 /*
7374 7380 * Future: Add secondary function support for:
7375 7381 * inq_mchngr (DTYPE_CHANGER)
7376 7382 * inq_sccs (DTYPE_ARRAY_CTRL)
7377 7383 */
7378 7384
7379 7385 if (lundam) {
7380 7386 /* If using lunmap, end the observation */
7381 7387 scsi_lunmap_set_end(self, lundam);
7382 7388 } else {
7383 7389 /* wait for all the LUN threads of this target to complete */
7384 7390 mutex_enter(&h->h_lock);
7385 7391 while (h->h_thr_count > 0)
7386 7392 cv_wait(&h->h_cv, &h->h_lock);
7387 7393 mutex_exit(&h->h_lock);
7388 7394
7389 7395 /* free the target handle */
7390 7396 cv_destroy(&h->h_cv);
7391 7397 mutex_destroy(&h->h_lock);
7392 7398 kmem_free(h, sizeof (*h));
7393 7399 }
7394 7400
7395 7401 return (DDI_SUCCESS);
7396 7402 }
7397 7403
7398 7404 /*
7399 7405 * Enumerate LUN0 and all other LUNs and secondary functions associated with
7400 7406 * the specified target address.
7401 7407 *
7402 7408 * Return NDI_SUCCESS if we might have created a new node.
7403 7409 * Return NDI_FAILURE if we definitely did not create a new node.
7404 7410 */
7405 7411 static int
7406 7412 scsi_hba_bus_config_taddr(dev_info_t *self, char *taddr, int mt, scsi_enum_t se)
7407 7413 {
7408 7414 char addr[SCSI_MAXNAMELEN];
7409 7415 struct scsi_device *sd;
7410 7416 int circ;
7411 7417 int ret;
7412 7418 int pi;
7413 7419
7414 7420 /* See if LUN0 of the specified target exists. */
7415 7421 (void) snprintf(addr, sizeof (addr), "%s,0", taddr);
7416 7422
7417 7423 scsi_hba_devi_enter(self, &circ);
7418 7424 sd = scsi_device_config(self, NULL, addr, se, &circ, &pi);
7419 7425
7420 7426 if (sd) {
7421 7427 /*
7422 7428 * LUN0 exists, enumerate all the other LUNs.
7423 7429 *
7424 7430 * With vHCI enumeration, when 'self' is a pHCI the sd
7425 7431 * scsi_device may be associated with the vHCI 'client'.
7426 7432 * In this case 'pi' is the path_instance needed to
7427 7433 * continue enumeration communication LUN0 via 'self'
7428 7434 * pHCI and specific 'taddr' target address.
7429 7435 *
7430 7436 * We prevent the removal of LUN0 until we are done with
7431 7437 * prevent/allow because we must exit the parent for
7432 7438 * multi-threaded scsi_hba_enum_lsf_of_t().
7433 7439 *
7434 7440 * NOTE: scsi_unprobe is a noop, sd->sd_inq is valid until
7435 7441 * device_uninitchild - so sd_uninit_prevent keeps sd_inq valid
7436 7442 * by failing any device_uninitchild attempts.
7437 7443 */
7438 7444 ret = NDI_SUCCESS;
7439 7445 sd->sd_uninit_prevent++;
7440 7446 scsi_hba_devi_exit(self, circ);
7441 7447
7442 7448 (void) scsi_hba_enum_lsf_of_t(sd, self, taddr, pi, mt, se);
7443 7449
7444 7450 scsi_hba_devi_enter(self, &circ);
7445 7451 sd->sd_uninit_prevent--;
7446 7452 } else
7447 7453 ret = NDI_FAILURE;
7448 7454 scsi_hba_devi_exit(self, circ);
7449 7455 return (ret);
7450 7456 }
7451 7457
7452 7458 /* Config callout from scsi_hba_thread_taddrs */
7453 7459 static void
7454 7460 scsi_hba_taddr_config_thr(void *arg)
7455 7461 {
7456 7462 struct scsi_hba_mte_td *td = (struct scsi_hba_mte_td *)arg;
7457 7463 struct scsi_hba_mte_h *h = td->td_h;
7458 7464
7459 7465 (void) scsi_hba_bus_config_taddr(h->h_self, td->td_taddr,
7460 7466 td->td_mt, td->td_se);
7461 7467
7462 7468 /* signal completion of this target thread to the HBA */
7463 7469 mutex_enter(&h->h_lock);
7464 7470 if (--h->h_thr_count == 0)
7465 7471 cv_broadcast(&h->h_cv);
7466 7472 mutex_exit(&h->h_lock);
7467 7473
7468 7474 /* free config thread data */
7469 7475 kmem_free(td, sizeof (*td));
7470 7476 }
7471 7477
7472 7478 /*
7473 7479 * Enumerate all the children of the specified SCSI parallel interface (spi).
7474 7480 * An HBA associated with a non-parallel scsi bus should be using another bus
7475 7481 * level enumeration implementation (possibly their own) and calling
7476 7482 * scsi_hba_bus_config_taddr to do enumeration of devices associated with a
7477 7483 * particular target address.
7478 7484 *
7479 7485 * On an spi bus the targets are sequentially enumerated based on the
7480 7486 * width of the bus. We also take care to try to skip the HBAs own initiator
7481 7487 * id. See scsi_hba_enum_lsf_of_t() for LUN and secondary function enumeration.
7482 7488 *
7483 7489 * Return NDI_SUCCESS if we might have created a new node.
7484 7490 * Return NDI_FAILURE if we definitely did not create a new node.
7485 7491 *
7486 7492 * Note: At some point we may want to expose this interface in transport.h
7487 7493 * if we find an hba that implements bus_config but still uses spi-like target
7488 7494 * addresses.
7489 7495 */
7490 7496 static int
7491 7497 scsi_hba_bus_configall_spi(dev_info_t *self, int mt)
7492 7498 {
7493 7499 int options;
7494 7500 int ntargets;
7495 7501 int id;
7496 7502 int tgt;
7497 7503 char **taddrs;
7498 7504 char **taddr;
7499 7505 char *tbuf;
7500 7506
7501 7507 /*
7502 7508 * Find the number of targets supported on the bus. Look at the per
7503 7509 * bus scsi-options property on the HBA node and check its
7504 7510 * SCSI_OPTIONS_WIDE setting.
7505 7511 */
7506 7512 options = ddi_prop_get_int(DDI_DEV_T_ANY, self,
7507 7513 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-options", -1);
7508 7514 if ((options != -1) && ((options & SCSI_OPTIONS_WIDE) == 0))
7509 7515 ntargets = NTARGETS; /* 8 */
7510 7516 else
7511 7517 ntargets = NTARGETS_WIDE; /* 16 */
7512 7518
7513 7519 /*
7514 7520 * Find the initiator-id for the HBA so we can skip that. We get the
7515 7521 * cached value on the HBA node, established in scsi_hba_attach_setup.
7516 7522 * If we were unable to determine the id then we rely on the HBA to
7517 7523 * fail gracefully when asked to enumerate itself.
7518 7524 */
7519 7525 id = ddi_prop_get_int(DDI_DEV_T_ANY, self,
7520 7526 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-initiator-id", -1);
7521 7527 if (id > ntargets) {
7522 7528 SCSI_HBA_LOG((_LOG(1), self, NULL,
7523 7529 "'scsi-initiator-id' bogus for %d target bus: %d",
7524 7530 ntargets, id));
7525 7531 id = -1;
7526 7532 }
7527 7533 SCSI_HBA_LOG((_LOG(2), self, NULL,
7528 7534 "enumerating targets 0-%d skip %d", ntargets, id));
7529 7535
7530 7536 /* form vector of target addresses */
7531 7537 taddrs = kmem_zalloc(sizeof (char *) * (ntargets + 1), KM_SLEEP);
7532 7538 for (tgt = 0, taddr = taddrs; tgt < ntargets; tgt++) {
7533 7539 /* skip initiator */
7534 7540 if (tgt == id)
7535 7541 continue;
7536 7542
7537 7543 /* convert to string and enumerate the target address */
7538 7544 tbuf = kmem_alloc(((tgt/16) + 1) + 1, KM_SLEEP);
7539 7545 (void) sprintf(tbuf, "%x", tgt);
7540 7546 ASSERT(strlen(tbuf) == ((tgt/16) + 1));
7541 7547 *taddr++ = tbuf;
7542 7548 }
7543 7549
7544 7550 /* null terminate vector of target addresses */
7545 7551 *taddr = NULL;
7546 7552
7547 7553 /* configure vector of target addresses */
7548 7554 scsi_hba_thread_taddrs(self, taddrs, mt, SE_BUSCONFIG,
7549 7555 scsi_hba_taddr_config_thr);
7550 7556
7551 7557 /* free vector of target addresses */
7552 7558 for (taddr = taddrs; *taddr; taddr++)
7553 7559 kmem_free(*taddr, strlen(*taddr) + 1);
7554 7560 kmem_free(taddrs, sizeof (char *) * (ntargets + 1));
7555 7561 return (NDI_SUCCESS);
7556 7562 }
7557 7563
7558 7564 /*
7559 7565 * Transport independent bus_configone BUS_CONFIG_ONE implementation. Takes
7560 7566 * same arguments, minus op, as scsi_hba_bus_config(), tran_bus_config(),
7561 7567 * and scsi_hba_bus_config_spi().
7562 7568 */
7563 7569 int
7564 7570 scsi_hba_bus_configone(dev_info_t *self, uint_t flags, char *arg,
7565 7571 dev_info_t **childp)
7566 7572 {
7567 7573 int ret;
7568 7574 int circ;
7569 7575 char *name, *addr;
7570 7576 char *lcp;
7571 7577 char sc1, sc2;
7572 7578 char nameaddr[SCSI_MAXNAMELEN];
7573 7579 extern int i_ndi_make_spec_children(dev_info_t *, uint_t);
7574 7580 struct scsi_device *sd0, *sd;
7575 7581 scsi_lun64_t lun64;
7576 7582 int mt;
7577 7583
7578 7584 /* parse_name modifies arg1, we must duplicate "name@addr" */
7579 7585 (void) strcpy(nameaddr, arg);
7580 7586 i_ddi_parse_name(nameaddr, &name, &addr, NULL);
7581 7587
7582 7588 /* verify the form of the node - we need an @addr */
7583 7589 if ((name == NULL) || (addr == NULL) ||
7584 7590 (*name == '\0') || (*addr == '\0')) {
7585 7591 /*
7586 7592 * OBP may create ill formed template/stub/wild-card
7587 7593 * nodes (no @addr) for legacy driver loading methods -
7588 7594 * ignore them.
7589 7595 */
7590 7596 SCSI_HBA_LOG((_LOG(2), self, NULL, "%s ill formed", arg));
7591 7597 return (NDI_FAILURE);
7592 7598 }
7593 7599
7594 7600 /*
7595 7601 * Check to see if this is a non-scsi flavor configuration operation.
7596 7602 */
7597 7603 if (strcmp(name, "smp") == 0) {
7598 7604 /*
7599 7605 * Configure the child, and if we're successful return with
7600 7606 * active hold.
7601 7607 */
7602 7608 return (smp_hba_bus_config(self, addr, childp));
7603 7609 }
7604 7610
7605 7611 /*
7606 7612 * The framework does not ensure the creation of driver.conf
7607 7613 * nodes prior to calling a nexus bus_config. For legacy
7608 7614 * support of driver.conf file nodes we want to create our
7609 7615 * driver.conf file children now so that we can detect if we
7610 7616 * are being asked to bus_configone one of these nodes.
7611 7617 *
7612 7618 * Needing driver.conf file nodes prior to bus config is unique
7613 7619 * to scsi_enumeration mixed mode (legacy driver.conf and
7614 7620 * dynamic SID node) support. There is no general need for the
7615 7621 * framework to make driver.conf children prior to bus_config.
7616 7622 *
7617 7623 * We enter our HBA (self) prior to scsi_device_config, and
7618 7624 * pass it our circ. The scsi_device_config may exit the
7619 7625 * HBA around scsi_probe() operations to allow for parallelism.
7620 7626 * This is done after the probe node "@addr" is available as a
7621 7627 * barrier to prevent parallel probes of the same device. The
7622 7628 * probe node is also configured in a way that it can't be
7623 7629 * removed by the framework until we are done with it.
7624 7630 *
7625 7631 * NOTE: The framework is currently preventing many parallel
7626 7632 * sibling operations (such as attaches), so the parallelism
7627 7633 * we are providing is of marginal use until that is improved.
7628 7634 * The most logical way to solve this would be to have separate
7629 7635 * target and lun nodes. This would be a large change in the
7630 7636 * format of /devices paths and is not being pursued at this
7631 7637 * time. The need for parallelism will become more of an issue
7632 7638 * with top-down attach for mpxio/vhci and for iSCSI support.
7633 7639 * We may want to eventually want a dual mode implementation,
7634 7640 * where the HBA determines if we should construct separate
7635 7641 * target and lun devinfo nodes.
7636 7642 */
7637 7643 scsi_hba_devi_enter(self, &circ);
7638 7644 SCSI_HBA_LOG((_LOG(4), self, NULL, "%s@%s config_one", name, addr));
7639 7645 (void) i_ndi_make_spec_children(self, flags);
7640 7646
7641 7647 /*
7642 7648 * For bus_configone, we make sure that we can find LUN0
7643 7649 * first. This allows the delayed probe/barrier deletion for a
7644 7650 * non-existent LUN0 (if enabled in scsi_device_config) to
7645 7651 * cover all LUNs on the target. This is done to minimize the
7646 7652 * number of independent target selection timeouts that occur
7647 7653 * when a target with many LUNs is no longer accessible
7648 7654 * (powered off). This removes the need for target driver
7649 7655 * probe cache implementations.
7650 7656 *
7651 7657 * This optimization may not be desirable in a pure bridge
7652 7658 * environment where targets on the other side of the bridge
7653 7659 * show up as LUNs to the host. If we ever need to support
7654 7660 * such a configuration then we should consider implementing a
7655 7661 * SCSI_OPTIONS_ILUN0 bit.
7656 7662 *
7657 7663 * NOTE: we are *not* applying any target limitation filtering
7658 7664 * to bus_configone, which means that we are relying on the
7659 7665 * HBA tran_tgt_init entry point invoked by scsi_busctl_initchild
7660 7666 * to fail.
7661 7667 */
7662 7668 sd0 = (struct scsi_device *)-1;
7663 7669 lcp = strchr(addr, ','); /* "addr,lun[,sfunc]" */
7664 7670 if (lcp) {
7665 7671 /*
7666 7672 * With "tgt,lun[,sfunc]" addressing, multiple addressing levels
7667 7673 * have been compressed into single devinfo node unit-address.
7668 7674 * This presents a mismatch - there is no bus_config to discover
7669 7675 * LUNs below a specific target, the only choice is to
7670 7676 * BUS_CONFIG_ALL the HBA. To support BUS_CONFIG_ALL_LUNS below
7671 7677 * a specific target, a bus_configone with lun address of "*"
7672 7678 * triggers lun discovery below a target.
7673 7679 */
7674 7680 if (*(lcp + 1) == '*') {
7675 7681 mt = ddi_prop_get_int(DDI_DEV_T_ANY, self,
7676 7682 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7677 7683 "scsi-enumeration", scsi_enumeration);
7678 7684 mt |= scsi_hba_log_mt_disable;
7679 7685
7680 7686 SCSI_HBA_LOG((_LOG(2), self, NULL,
7681 7687 "%s@%s lun enumeration triggered", name, addr));
7682 7688 *lcp = '\0'; /* turn ',' into '\0' */
7683 7689 scsi_hba_devi_exit(self, circ);
7684 7690 (void) scsi_hba_bus_config_taddr(self, addr,
7685 7691 mt, SE_BUSCONFIG);
7686 7692 return (NDI_FAILURE);
7687 7693 }
7688 7694
7689 7695 /* convert hex lun number from ascii */
7690 7696 lun64 = scsi_addr_to_lun64(lcp + 1);
7691 7697
7692 7698 if ((lun64 != 0) && (lun64 != SCSI_LUN64_ILLEGAL)) {
7693 7699 /*
7694 7700 * configure ",0" lun first, saving off
7695 7701 * original lun characters.
7696 7702 */
7697 7703 sc1 = *(lcp + 1);
7698 7704 sc2 = *(lcp + 2);
7699 7705 *(lcp + 1) = '0';
7700 7706 *(lcp + 2) = '\0';
7701 7707 sd0 = scsi_device_config(self,
7702 7708 NULL, addr, SE_BUSCONFIG, &circ, NULL);
7703 7709
7704 7710 /* restore original lun */
7705 7711 *(lcp + 1) = sc1;
7706 7712 *(lcp + 2) = sc2;
7707 7713
7708 7714 /*
7709 7715 * Apply maxlun filtering.
7710 7716 *
7711 7717 * Future: We still have the kludged
7712 7718 * scsi_check_ss2_LUN_limit() filtering off
7713 7719 * scsi_probe() to catch bogus driver.conf
7714 7720 * entries.
7715 7721 */
7716 7722 if (sd0 && (lun64 < SCSI_32LUNS_PER_TARGET) &&
7717 7723 (lun64 >= scsi_get_scsi_maxluns(sd0))) {
7718 7724 sd0 = NULL;
7719 7725 SCSI_HBA_LOG((_LOG(4), self, NULL,
7720 7726 "%s@%s filtered", name, addr));
7721 7727 } else
7722 7728 SCSI_HBA_LOG((_LOG(4), self, NULL,
7723 7729 "%s@%s lun 0 %s", name, addr,
7724 7730 sd0 ? "worked" : "failed"));
7725 7731 }
7726 7732 }
7727 7733
7728 7734 /*
7729 7735 * configure the requested device if LUN0 exists or we were
7730 7736 * unable to determine the lun format to determine if LUN0
7731 7737 * exists.
7732 7738 */
7733 7739 if (sd0) {
7734 7740 sd = scsi_device_config(self,
7735 7741 name, addr, SE_BUSCONFIG, &circ, NULL);
7736 7742 } else {
7737 7743 sd = NULL;
7738 7744 SCSI_HBA_LOG((_LOG(2), self, NULL,
7739 7745 "%s@%s no lun 0 or filtered lun", name, addr));
7740 7746 }
7741 7747
7742 7748 /*
7743 7749 * We know what we found, to reduce overhead we finish BUS_CONFIG_ONE
7744 7750 * processing without calling back to the frameworks
7745 7751 * ndi_busop_bus_config (unless we goto framework below).
7746 7752 *
7747 7753 * If the reference is to a driver name and we created a generic name
7748 7754 * (bound to that driver) we will still succeed. This is important
7749 7755 * for correctly resolving old drivername references to device that now
7750 7756 * uses a generic names across the transition to generic naming. This
7751 7757 * is effectively an internal implementation of the NDI_DRIVERNAME flag.
7752 7758 *
7753 7759 * We also need to special case the resolve_pathname OBP boot-device
7754 7760 * case (modrootloaded == 0) where reference is to a generic name but
7755 7761 * we created a legacy driver name node by returning just returning
7756 7762 * the node created.
7757 7763 */
7758 7764 if (sd && sd->sd_dev &&
7759 7765 ((strcmp(ddi_node_name(sd->sd_dev), name) == 0) ||
7760 7766 (strcmp(ddi_driver_name(sd->sd_dev), name) == 0) ||
7761 7767 (modrootloaded == 0)) &&
7762 7768 (ndi_devi_online(sd->sd_dev,
7763 7769 flags & NDI_NO_EVENT) == NDI_SUCCESS)) {
7764 7770
7765 7771 /* device attached, return devinfo node with hold */
7766 7772 ret = NDI_SUCCESS;
7767 7773 *childp = sd->sd_dev;
7768 7774 ndi_hold_devi(sd->sd_dev);
7769 7775 } else {
7770 7776 /*
7771 7777 * In the process of failing we may have added nodes to the HBA
7772 7778 * (self), clearing DEVI_MADE_CHILDREN. To reduce the overhead
7773 7779 * associated with the frameworks reaction to this we clear the
7774 7780 * flag here.
7775 7781 */
7776 7782 mutex_enter(&DEVI(self)->devi_lock);
7777 7783 DEVI(self)->devi_flags &= ~DEVI_MADE_CHILDREN;
7778 7784 mutex_exit(&DEVI(self)->devi_lock);
7779 7785 ret = NDI_FAILURE;
7780 7786
7781 7787 /*
7782 7788 * The framework may still be able to succeed with
7783 7789 * with its GENERIC_PROP code.
7784 7790 */
7785 7791 scsi_hba_devi_exit(self, circ);
7786 7792 if (flags & NDI_DRV_CONF_REPROBE)
7787 7793 flags |= NDI_CONFIG_REPROBE;
7788 7794 flags |= NDI_MDI_FALLBACK; /* devinfo&pathinfo children */
7789 7795 return (ndi_busop_bus_config(self, flags, BUS_CONFIG_ONE,
7790 7796 (void *)arg, childp, 0));
7791 7797 }
7792 7798
7793 7799 scsi_hba_devi_exit(self, circ);
7794 7800 return (ret);
7795 7801 }
7796 7802
7797 7803 /*
7798 7804 * Perform SCSI Parallel Interconnect bus_config
7799 7805 */
7800 7806 static int
7801 7807 scsi_hba_bus_config_spi(dev_info_t *self, uint_t flags,
7802 7808 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
7803 7809 {
7804 7810 int ret;
7805 7811 int mt;
7806 7812
7807 7813 /*
7808 7814 * Enumerate scsi target devices: See if we are doing generic dynamic
7809 7815 * enumeration: if driver.conf has not specified the 'scsi-enumeration'
7810 7816 * knob then use the global scsi_enumeration knob.
7811 7817 */
7812 7818 mt = ddi_prop_get_int(DDI_DEV_T_ANY, self,
7813 7819 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7814 7820 "scsi-enumeration", scsi_enumeration);
7815 7821 mt |= scsi_hba_log_mt_disable;
7816 7822
7817 7823 if ((mt & SCSI_ENUMERATION_ENABLE) == 0) {
7818 7824 /*
7819 7825 * Static driver.conf file enumeration:
7820 7826 *
7821 7827 * Force reprobe for BUS_CONFIG_ONE or when manually
7822 7828 * reconfiguring via devfsadm(1m) to emulate deferred attach.
7823 7829 * Reprobe only discovers driver.conf enumerated nodes, more
7824 7830 * dynamic implementations probably require their own
7825 7831 * bus_config.
7826 7832 */
7827 7833 if ((op == BUS_CONFIG_ONE) || (flags & NDI_DRV_CONF_REPROBE))
7828 7834 flags |= NDI_CONFIG_REPROBE;
7829 7835 flags |= NDI_MDI_FALLBACK; /* devinfo&pathinfo children */
7830 7836 return (ndi_busop_bus_config(self, flags, op, arg, childp, 0));
7831 7837 }
7832 7838
7833 7839 if (scsi_hba_bus_config_debug)
7834 7840 flags |= NDI_DEVI_DEBUG;
7835 7841
7836 7842 /*
7837 7843 * Generic spi dynamic bus config enumeration to discover and enumerate
7838 7844 * the target device nodes we are looking for.
7839 7845 */
7840 7846 switch (op) {
7841 7847 case BUS_CONFIG_ONE: /* enumerate the named child */
7842 7848 ret = scsi_hba_bus_configone(self, flags, (char *)arg, childp);
7843 7849 break;
7844 7850
7845 7851 case BUS_CONFIG_ALL: /* enumerate all children on the bus */
7846 7852 case BUS_CONFIG_DRIVER: /* enumerate all children that bind to driver */
7847 7853 SCSI_HBA_LOG((_LOG(3), self, NULL,
7848 7854 "BUS_CONFIG_%s mt %x",
7849 7855 (op == BUS_CONFIG_ALL) ? "ALL" : "DRIVER", mt));
7850 7856
7851 7857 /*
7852 7858 * Enumerate targets on SCSI parallel interconnect and let the
7853 7859 * framework finish the operation (attach the nodes).
7854 7860 */
7855 7861 if ((ret = scsi_hba_bus_configall_spi(self, mt)) == NDI_SUCCESS)
7856 7862 ret = ndi_busop_bus_config(self, flags, op,
7857 7863 arg, childp, 0);
7858 7864 break;
7859 7865
7860 7866 default:
7861 7867 ret = NDI_FAILURE;
7862 7868 break;
7863 7869 }
7864 7870 return (ret);
7865 7871 }
7866 7872
7867 7873 /*
7868 7874 * Perform SCSI Parallel Interconnect bus_unconfig
7869 7875 */
7870 7876 static int
7871 7877 scsi_hba_bus_unconfig_spi(dev_info_t *self, uint_t flags,
7872 7878 ddi_bus_config_op_t op, void *arg)
7873 7879 {
7874 7880 int mt;
7875 7881 int circ;
7876 7882 int ret;
7877 7883
7878 7884 /*
7879 7885 * See if we are doing generic dynamic enumeration: if driver.conf has
7880 7886 * not specified the 'scsi-enumeration' knob then use the global
7881 7887 * scsi_enumeration knob.
7882 7888 */
7883 7889 mt = ddi_prop_get_int(DDI_DEV_T_ANY, self,
7884 7890 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
7885 7891 "scsi-enumeration", scsi_enumeration);
7886 7892 mt |= scsi_hba_log_mt_disable;
7887 7893
7888 7894 if ((mt & SCSI_ENUMERATION_ENABLE) == 0)
7889 7895 return (ndi_busop_bus_unconfig(self, flags, op, arg));
7890 7896
7891 7897 if (scsi_hba_bus_config_debug)
7892 7898 flags |= NDI_DEVI_DEBUG;
7893 7899
7894 7900 scsi_hba_devi_enter(self, &circ);
7895 7901 switch (op) {
7896 7902 case BUS_UNCONFIG_ONE:
7897 7903 SCSI_HBA_LOG((_LOG(3), self, NULL,
7898 7904 "unconfig one: %s", (char *)arg));
7899 7905 ret = NDI_SUCCESS;
7900 7906 break;
7901 7907
7902 7908 case BUS_UNCONFIG_ALL:
7903 7909 case BUS_UNCONFIG_DRIVER:
7904 7910 ret = NDI_SUCCESS;
7905 7911 break;
7906 7912
7907 7913 default:
7908 7914 ret = NDI_FAILURE;
7909 7915 break;
7910 7916 }
7911 7917
7912 7918 /* Perform the generic default bus unconfig */
7913 7919 if (ret == NDI_SUCCESS)
7914 7920 ret = ndi_busop_bus_unconfig(self, flags, op, arg);
7915 7921
7916 7922 scsi_hba_devi_exit(self, circ);
7917 7923
7918 7924 return (ret);
7919 7925 }
7920 7926
7921 7927 static int
7922 7928 scsi_hba_bus_config_tgtmap(dev_info_t *self, uint_t flags,
7923 7929 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
7924 7930 {
7925 7931 scsi_hba_tran_t *tran;
7926 7932 impl_scsi_tgtmap_t *tgtmap;
7927 7933 uint64_t tsa = 0; /* clock64_t */
7928 7934 int maxdev;
7929 7935 int sync_usec;
7930 7936 int synced;
7931 7937 int ret = NDI_FAILURE;
7932 7938
7933 7939 if ((op != BUS_CONFIG_ONE) && (op != BUS_CONFIG_ALL) &&
7934 7940 (op != BUS_CONFIG_DRIVER))
7935 7941 goto out;
7936 7942
7937 7943 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
7938 7944 tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap;
7939 7945 ASSERT(tgtmap);
7940 7946
7941 7947 /*
7942 7948 * MPXIO is never a sure thing (and we have mixed children), so
7943 7949 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
7944 7950 * search for both devinfo and pathinfo children.
7945 7951 *
7946 7952 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
7947 7953 * devinfo/pathinfo children in parallel (instead of old way of
7948 7954 * looking for one form of child and then doing "fallback" to
7949 7955 * look for other form of child).
7950 7956 */
7951 7957 flags |= NDI_MDI_FALLBACK; /* devinfo&pathinfo children */
7952 7958
7953 7959 /*
7954 7960 * If bus_config occurred within the map create-to-hotplug_sync window,
7955 7961 * we need the framework to wait for children that are physicaly
7956 7962 * present at map create time to show up (via tgtmap hotplug config).
7957 7963 *
7958 7964 * The duration of this window is specified by the HBA driver at
7959 7965 * scsi_hba_tgtmap_create(9F) time (during attach(9E)). Its
7960 7966 * 'csync_usec' value is selected based on how long it takes the HBA
7961 7967 * driver to get from map creation to initial observation for something
7962 7968 * already plugged in. Estimate high, a low estimate can result in
7963 7969 * devices not showing up correctly on first reference. The call to
7964 7970 * ndi_busop_bus_config needs a timeout value large enough so that
7965 7971 * the map sync call further down is not a noop (i.e. done against
7966 7972 * an empty map when something is infact plugged in). With
7967 7973 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
7968 7974 * soon as the desired device is enumerated via hotplug - so we are
7969 7975 * not committed to waiting the entire time.
7970 7976 *
7971 7977 * We are typically outside the window, so timeout is 0.
7972 7978 */
7973 7979 sync_usec = tgtmap->tgtmap_create_csync_usec;
7974 7980 if (tgtmap->tgtmap_create_window) {
7975 7981 tsa = ddi_get_lbolt64() - tgtmap->tgtmap_create_time;
7976 7982 if (tsa < drv_usectohz(sync_usec)) {
7977 7983 tsa = drv_usectohz(sync_usec) - tsa;
7978 7984 ret = ndi_busop_bus_config(self,
7979 7985 flags, op, arg, childp, (clock_t)tsa);
7980 7986 } else
7981 7987 tsa = 0; /* passed window */
7982 7988
7983 7989 /* First one out closes the window. */
7984 7990 tgtmap->tgtmap_create_window = 0;
7985 7991 } else if (op == BUS_CONFIG_ONE)
7986 7992 ret = ndi_busop_bus_config(self, flags, op, arg, childp, 0);
7987 7993
7988 7994 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
7989 7995 if ((op == BUS_CONFIG_ONE) && (ret == NDI_SUCCESS))
7990 7996 goto out; /* performance path */
7991 7997
7992 7998 /*
7993 7999 * We sync if we were in the window, on the first bus_config_one, and
7994 8000 * every bus_config_all (or bus_config_driver).
7995 8001 */
7996 8002 if (tsa || (tgtmap->tgtmap_sync_cnt == 0) ||
7997 8003 (op != BUS_CONFIG_ONE)) {
7998 8004 /*
7999 8005 * Sync current observations in the map and look again. We
8000 8006 * place an upper bound on the amount of time we will wait for
8001 8007 * sync to complete to avoid a bad device causing this
8002 8008 * busconfig operation to hang.
8003 8009 *
8004 8010 * We are typically stable, so damap_sync returns immediately.
8005 8011 *
8006 8012 * Max time to wait for sync is settle_usec per possible device.
8007 8013 */
8008 8014 tgtmap->tgtmap_sync_cnt++;
8009 8015 maxdev = damap_size(tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]);
8010 8016 maxdev = (maxdev > scsi_hba_map_settle_f) ? maxdev :
8011 8017 scsi_hba_map_settle_f;
8012 8018 sync_usec = maxdev * tgtmap->tgtmap_settle_usec;
8013 8019 synced = scsi_tgtmap_sync((scsi_hba_tgtmap_t *)tgtmap,
8014 8020 sync_usec);
8015 8021 if (!synced)
8016 8022 SCSI_HBA_LOG((_LOGCFG, self, NULL,
8017 8023 "tgtmap_sync timeout"));
8018 8024 } else
8019 8025 synced = -1;
8020 8026
8021 8027 if (op == BUS_CONFIG_ONE)
8022 8028 ret = scsi_hba_bus_configone(self, flags, arg, childp);
8023 8029 else
8024 8030 ret = ndi_busop_bus_config(self, flags, op, arg, childp, 0);
8025 8031
8026 8032 out:
8027 8033 #ifdef DEBUG
8028 8034 if (ret != NDI_SUCCESS) {
8029 8035 if (scsi_hba_bus_config_failure_msg ||
8030 8036 scsi_hba_bus_config_failure_dbg) {
8031 8037 scsi_hba_bus_config_failure_msg--;
8032 8038 printf("%s%d: bus_config_tgtmap %p failure on %s: "
8033 8039 "%d %d\n",
8034 8040 ddi_driver_name(self), ddi_get_instance(self),
8035 8041 (void *)tgtmap,
8036 8042 (op == BUS_CONFIG_ONE) ? (char *)arg : "ALL",
8037 8043 (int)tsa, synced);
8038 8044 }
8039 8045 if (scsi_hba_bus_config_failure_dbg) {
8040 8046 scsi_hba_bus_config_failure_dbg--;
8041 8047 debug_enter("config_tgtmap failure");
8042 8048 }
8043 8049 } else if (scsi_hba_bus_config_success_msg ||
8044 8050 scsi_hba_bus_config_success_dbg) {
8045 8051 scsi_hba_bus_config_success_msg--;
8046 8052 printf("%s%d: bus_config_tgtmap %p success on %s: %d %d\n",
8047 8053 ddi_driver_name(self), ddi_get_instance(self),
8048 8054 (void *)tgtmap,
8049 8055 (op == BUS_CONFIG_ONE) ? (char *)arg : "ALL",
8050 8056 (int)tsa, synced);
8051 8057 if (scsi_hba_bus_config_success_dbg) {
8052 8058 scsi_hba_bus_config_success_dbg--;
8053 8059 debug_enter("config_tgtmap success");
8054 8060 }
8055 8061 }
8056 8062 #endif /* DEBUG */
8057 8063 return (ret);
8058 8064 }
8059 8065
8060 8066 static int
8061 8067 scsi_hba_bus_unconfig_tgtmap(dev_info_t *self, uint_t flags,
8062 8068 ddi_bus_config_op_t op, void *arg)
8063 8069 {
8064 8070 int ret = NDI_FAILURE;
8065 8071
8066 8072 switch (op) {
8067 8073 case BUS_UNCONFIG_ONE:
8068 8074 case BUS_UNCONFIG_DRIVER:
8069 8075 case BUS_UNCONFIG_ALL:
8070 8076 ret = NDI_SUCCESS;
8071 8077 break;
8072 8078 default:
8073 8079 break;
8074 8080 }
8075 8081
8076 8082 if (ret == NDI_SUCCESS) {
8077 8083 flags &= ~NDI_DEVI_REMOVE;
8078 8084 ret = ndi_busop_bus_unconfig(self, flags, op, arg);
8079 8085 }
8080 8086 return (ret);
8081 8087 }
8082 8088
8083 8089 static int
8084 8090 scsi_hba_bus_config_iportmap(dev_info_t *self, uint_t flags,
8085 8091 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
8086 8092 {
8087 8093 scsi_hba_tran_t *tran;
8088 8094 impl_scsi_iportmap_t *iportmap;
8089 8095 dev_info_t *child;
8090 8096 int circ;
8091 8097 uint64_t tsa = 0; /* clock64_t */
8092 8098 int sync_usec;
8093 8099 int synced;
8094 8100 int ret = NDI_FAILURE;
8095 8101
8096 8102 if ((op != BUS_CONFIG_ONE) && (op != BUS_CONFIG_ALL) &&
8097 8103 (op != BUS_CONFIG_DRIVER))
8098 8104 goto out;
8099 8105
8100 8106 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
8101 8107 iportmap = (impl_scsi_iportmap_t *)tran->tran_iportmap;
8102 8108 ASSERT(iportmap);
8103 8109
8104 8110 /*
8105 8111 * MPXIO is never a sure thing (and we have mixed children), so
8106 8112 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
8107 8113 * search for both devinfo and pathinfo children.
8108 8114 *
8109 8115 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
8110 8116 * devinfo/pathinfo children in parallel (instead of old way of
8111 8117 * looking for one form of child and then doing "fallback" to
8112 8118 * look for other form of child).
8113 8119 */
8114 8120 flags |= NDI_MDI_FALLBACK; /* devinfo&pathinfo children */
8115 8121
8116 8122 /*
8117 8123 * If bus_config occurred within the map create-to-hotplug_sync window,
8118 8124 * we need the framework to wait for children that are physicaly
8119 8125 * present at map create time to show up (via iportmap hotplug config).
8120 8126 *
8121 8127 * The duration of this window is specified by the HBA driver at
8122 8128 * scsi_hba_iportmap_create(9F) time (during attach(9E)). Its
8123 8129 * 'csync_usec' value is selected based on how long it takes the HBA
8124 8130 * driver to get from map creation to initial observation for something
8125 8131 * already plugged in. Estimate high, a low estimate can result in
8126 8132 * devices not showing up correctly on first reference. The call to
8127 8133 * ndi_busop_bus_config needs a timeout value large enough so that
8128 8134 * the map sync call further down is not a noop (i.e. done against
8129 8135 * an empty map when something is infact plugged in). With
8130 8136 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
8131 8137 * soon as the desired device is enumerated via hotplug - so we are
8132 8138 * not committed to waiting the entire time.
8133 8139 *
8134 8140 * We are typically outside the window, so timeout is 0.
8135 8141 */
8136 8142 sync_usec = iportmap->iportmap_create_csync_usec;
8137 8143 if (iportmap->iportmap_create_window) {
8138 8144 tsa = ddi_get_lbolt64() - iportmap->iportmap_create_time;
8139 8145 if (tsa < drv_usectohz(sync_usec)) {
8140 8146 tsa = drv_usectohz(sync_usec) - tsa;
8141 8147 ret = ndi_busop_bus_config(self,
8142 8148 flags, op, arg, childp, (clock_t)tsa);
8143 8149 } else
8144 8150 tsa = 0; /* passed window */
8145 8151
8146 8152 /* First one out closes the window. */
8147 8153 iportmap->iportmap_create_window = 0;
8148 8154 } else if (op == BUS_CONFIG_ONE)
8149 8155 ret = ndi_busop_bus_config(self, flags, op, arg, childp, 0);
8150 8156
8151 8157 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
8152 8158 if ((op == BUS_CONFIG_ONE) && (ret == NDI_SUCCESS))
8153 8159 goto out; /* performance path */
8154 8160
8155 8161 /*
8156 8162 * We sync if we were in the window, on the first bus_config_one, and
8157 8163 * every bus_config_all (or bus_config_driver).
8158 8164 */
8159 8165 if (tsa || (iportmap->iportmap_sync_cnt == 0) ||
8160 8166 (op != BUS_CONFIG_ONE)) {
8161 8167 /*
8162 8168 * Sync current observations in the map and look again. We
8163 8169 * place an upper bound on the amount of time we will wait for
8164 8170 * sync to complete to avoid a bad device causing this
8165 8171 * busconfig operation to hang.
8166 8172 *
8167 8173 * We are typically stable, so damap_sync returns immediately.
8168 8174 *
8169 8175 * Max time to wait for sync is settle_usec times settle factor.
8170 8176 */
8171 8177 iportmap->iportmap_sync_cnt++;
8172 8178 synced = damap_sync(iportmap->iportmap_dam, sync_usec);
8173 8179 if (!synced)
8174 8180 SCSI_HBA_LOG((_LOGCFG, self, NULL,
8175 8181 "iportmap_sync timeout"));
8176 8182 } else
8177 8183 synced = -1;
8178 8184
8179 8185 if (op == BUS_CONFIG_ONE) {
8180 8186 /* create the iport node child */
8181 8187 scsi_hba_devi_enter(self, &circ);
8182 8188 if ((child = scsi_hba_bus_config_port(self, (char *)arg,
8183 8189 SE_BUSCONFIG)) != NULL) {
8184 8190 if (childp) {
8185 8191 ndi_hold_devi(child);
8186 8192 *childp = child;
8187 8193 }
8188 8194 ret = NDI_SUCCESS;
8189 8195 }
8190 8196 scsi_hba_devi_exit(self, circ);
8191 8197 } else
8192 8198 ret = ndi_busop_bus_config(self, flags, op, arg, childp, 0);
8193 8199
8194 8200 out:
8195 8201 #ifdef DEBUG
8196 8202 if (ret != NDI_SUCCESS) {
8197 8203 if (scsi_hba_bus_config_failure_msg ||
8198 8204 scsi_hba_bus_config_failure_dbg) {
8199 8205 scsi_hba_bus_config_failure_msg--;
8200 8206 printf("%s%d: bus_config_iportmap %p failure on %s: "
8201 8207 "%d %d\n",
8202 8208 ddi_driver_name(self), ddi_get_instance(self),
8203 8209 (void *)iportmap,
8204 8210 (op == BUS_CONFIG_ONE) ? (char *)arg : "ALL",
8205 8211 (int)tsa, synced);
8206 8212 }
8207 8213 if (scsi_hba_bus_config_failure_dbg) {
8208 8214 scsi_hba_bus_config_failure_dbg--;
8209 8215 debug_enter("config_iportmap failure");
8210 8216 }
8211 8217 } else if (scsi_hba_bus_config_success_msg ||
8212 8218 scsi_hba_bus_config_success_dbg) {
8213 8219 scsi_hba_bus_config_success_msg--;
8214 8220 printf("%s%d: bus_config_iportmap %p success on %s: %d %d\n",
8215 8221 ddi_driver_name(self), ddi_get_instance(self),
8216 8222 (void *)iportmap,
8217 8223 (op == BUS_CONFIG_ONE) ? (char *)arg : "ALL",
8218 8224 (int)tsa, synced);
8219 8225 if (scsi_hba_bus_config_success_dbg) {
8220 8226 scsi_hba_bus_config_success_dbg--;
8221 8227 debug_enter("config_iportmap success");
8222 8228 }
8223 8229 }
8224 8230 #endif /* DEBUG */
8225 8231 return (ret);
8226 8232 }
8227 8233
8228 8234 static int
8229 8235 scsi_hba_bus_unconfig_iportmap(dev_info_t *self, uint_t flags,
8230 8236 ddi_bus_config_op_t op, void *arg)
8231 8237 {
8232 8238 flags &= ~NDI_DEVI_REMOVE;
8233 8239 return (ndi_busop_bus_unconfig(self, flags, op, arg));
8234 8240 }
8235 8241
8236 8242 /*
8237 8243 * SCSI HBA bus config enumeration entry point. Called via the bus_ops
8238 8244 * bus_config entry point for all SCSA HBA drivers.
8239 8245 *
8240 8246 * o If an HBA implements its own bus_config via tran_bus_config then we
8241 8247 * invoke it. An HBA that implements its own tran_bus_config entry point
8242 8248 * may still call back into common SCSA code bus_config code for:
8243 8249 *
8244 8250 * o SPI bus_config (scsi_hba_bus_spi)
8245 8251 * o LUN and secondary function enumeration (scsi_hba_enum_lsf_of_t()).
8246 8252 * o configuration of a specific device (scsi_device_config).
8247 8253 * o determining 1275 SCSI nodename and compatible property
8248 8254 * (scsi_hba_nodename_compatible_get/_free).
8249 8255 *
8250 8256 * o Otherwise we implement a SCSI parallel interface (spi) bus config.
8251 8257 *
8252 8258 * Return NDI_SUCCESS if we might have created a new node.
8253 8259 * Return NDI_FAILURE if we definitely did not create a new node.
8254 8260 */
8255 8261 static int
8256 8262 scsi_hba_bus_config(dev_info_t *self, uint_t flags,
8257 8263 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
8258 8264 {
8259 8265 scsi_hba_tran_t *tran;
8260 8266 int ret;
8261 8267
8262 8268 /* make sure that we will not disappear */
8263 8269 ASSERT(DEVI(self)->devi_ref);
8264 8270
8265 8271 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
8266 8272 if (tran == NULL) {
8267 8273 /* NULL tran driver.conf config (used by cmdk). */
8268 8274 if ((op == BUS_CONFIG_ONE) || (flags & NDI_DRV_CONF_REPROBE))
8269 8275 flags |= NDI_CONFIG_REPROBE;
8270 8276 return (ndi_busop_bus_config(self, flags, op, arg, childp, 0));
8271 8277 }
8272 8278
8273 8279 /* Check if self is HBA-only node. */
8274 8280 if (tran->tran_hba_flags & SCSI_HBA_HBA) {
8275 8281 /* The bus_config request is to configure iports below HBA. */
8276 8282
8277 8283 #ifdef sparc
8278 8284 /*
8279 8285 * Sparc's 'boot-device' OBP property value lacks an /iport@X/
8280 8286 * component. Prior to the mount of root, we drive a disk@
8281 8287 * BUS_CONFIG_ONE operatino down a level to resolve an
8282 8288 * OBP 'boot-device' path.
8283 8289 *
8284 8290 * Future: Add (modrootloaded == 0) below, and insure that
8285 8291 * all attempts bus_conf of 'bo_name' (in OBP form) occur
8286 8292 * prior to 'modrootloaded = 1;' assignment in vfs_mountroot.
8287 8293 */
8288 8294 if ((op == BUS_CONFIG_ONE) &&
8289 8295 (strncmp((char *)arg, "disk@", strlen("disk@")) == 0)) {
8290 8296 return (scsi_hba_bus_config_prom_node(self,
8291 8297 flags, arg, childp));
8292 8298 }
8293 8299 #endif /* sparc */
8294 8300
8295 8301 if (tran->tran_iportmap) {
8296 8302 /* config based on scsi_hba_iportmap API */
8297 8303 ret = scsi_hba_bus_config_iportmap(self,
8298 8304 flags, op, arg, childp);
8299 8305 } else {
8300 8306 /* config based on 'iport_register' API */
8301 8307 ret = scsi_hba_bus_config_iports(self,
8302 8308 flags, op, arg, childp);
8303 8309 }
8304 8310 return (ret);
8305 8311 }
8306 8312
8307 8313 /* Check to see how the iport/HBA does target/lun bus config. */
8308 8314 if (tran->tran_bus_config) {
8309 8315 /* HBA config based on Sun-private/legacy tran_bus_config */
8310 8316 ret = tran->tran_bus_config(self, flags, op, arg, childp);
8311 8317 } else if (tran->tran_tgtmap) {
8312 8318 /* SCSAv3 config based on scsi_hba_tgtmap_*() API */
8313 8319 ret = scsi_hba_bus_config_tgtmap(self, flags, op, arg, childp);
8314 8320 } else {
8315 8321 /* SCSA config based on SCSI Parallel Interconnect */
8316 8322 ret = scsi_hba_bus_config_spi(self, flags, op, arg, childp);
8317 8323 }
8318 8324 return (ret);
8319 8325 }
8320 8326
8321 8327 /*
8322 8328 * Called via the bus_ops bus_unconfig entry point for SCSI HBA drivers.
8323 8329 */
8324 8330 static int
8325 8331 scsi_hba_bus_unconfig(dev_info_t *self, uint_t flags,
8326 8332 ddi_bus_config_op_t op, void *arg)
8327 8333 {
8328 8334 int circ;
8329 8335 scsi_hba_tran_t *tran;
8330 8336 int ret;
8331 8337
8332 8338 tran = ddi_get_driver_private(self);
8333 8339 if (tran == NULL) {
8334 8340 /* NULL tran driver.conf unconfig (used by cmdk). */
8335 8341 return (ndi_busop_bus_unconfig(self, flags, op, arg));
8336 8342 }
8337 8343
8338 8344 /*
8339 8345 * Purge barrier/probe node children. We do this prior to
8340 8346 * tran_bus_unconfig in case the unconfig implementation calls back
8341 8347 * into the common code at a different enumeration level, such a
8342 8348 * scsi_device_config, which still creates barrier/probe nodes.
8343 8349 */
8344 8350 scsi_hba_devi_enter(self, &circ);
8345 8351 scsi_hba_barrier_purge(self);
8346 8352 scsi_hba_devi_exit(self, circ);
8347 8353
8348 8354 /* DEBUG: for testing, allow bus_unconfig do drive removal. */
8349 8355 if (scsi_hba_bus_unconfig_remove)
8350 8356 flags |= NDI_DEVI_REMOVE;
8351 8357
8352 8358 /* Check if self is HBA-only node. */
8353 8359 if (tran->tran_hba_flags & SCSI_HBA_HBA) {
8354 8360 /* The bus_config request is to unconfigure iports below HBA. */
8355 8361 if (tran->tran_iportmap) {
8356 8362 /* SCSAv3 unconfig based on scsi_hba_iportmap API */
8357 8363 ret = scsi_hba_bus_unconfig_iportmap(self,
8358 8364 flags, op, arg);
8359 8365 } else if (tran->tran_bus_unconfig) {
8360 8366 /* HBA unconfig based on Sun-private/legacy API */
8361 8367 ret = tran->tran_bus_unconfig(self, flags, op, arg);
8362 8368 } else {
8363 8369 /* Standard framework unconfig. */
8364 8370 ret = ndi_busop_bus_unconfig(self, flags, op, arg);
8365 8371 }
8366 8372 return (ret);
8367 8373 }
8368 8374
8369 8375 /* Check to see how the iport/HBA does target/lun bus unconfig. */
8370 8376 if (tran->tran_bus_unconfig) {
8371 8377 /* HBA unconfig based on Sun-private/legacy tran_bus_unconfig */
8372 8378 ret = tran->tran_bus_unconfig(self, flags, op, arg);
8373 8379 } else if (tran->tran_tgtmap) {
8374 8380 /* SCSAv3 unconfig based on scsi_hba_tgtmap_*() API */
8375 8381 ret = scsi_hba_bus_unconfig_tgtmap(self, flags, op, arg);
8376 8382 } else {
8377 8383 /* SCSA unconfig based on SCSI Parallel Interconnect */
8378 8384 ret = scsi_hba_bus_unconfig_spi(self, flags, op, arg);
8379 8385 }
8380 8386 return (ret);
8381 8387 }
8382 8388
8383 8389 static int
8384 8390 scsi_tgtmap_scsi_config(void *arg, damap_t *mapp, damap_id_t tgtid)
8385 8391 {
8386 8392 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
8387 8393 dev_info_t *self = tran->tran_iport_dip;
8388 8394 impl_scsi_tgtmap_t *tgtmap;
8389 8395 char *tgtaddr;
8390 8396 int cfg_status, mt;
8391 8397
8392 8398 tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap;
8393 8399 tgtaddr = damap_id2addr(mapp, tgtid);
8394 8400
8395 8401 if (scsi_lunmap_create(self, tgtmap, tgtaddr) != DDI_SUCCESS) {
8396 8402 SCSI_HBA_LOG((_LOG_NF(WARN),
8397 8403 "failed to create lunmap for %s", tgtaddr));
8398 8404 }
8399 8405
8400 8406 mt = ddi_prop_get_int(DDI_DEV_T_ANY, self,
8401 8407 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration",
8402 8408 scsi_enumeration);
8403 8409 mt |= scsi_hba_log_mt_disable;
8404 8410
8405 8411 cfg_status = scsi_hba_bus_config_taddr(self, tgtaddr, mt, SE_HP);
8406 8412 if (cfg_status != NDI_SUCCESS) {
8407 8413 SCSI_HBA_LOG((_LOGCFG, self, NULL, "%s @%s config status %d",
8408 8414 damap_name(mapp), tgtaddr, cfg_status));
8409 8415 scsi_lunmap_destroy(self, tgtmap, tgtaddr);
8410 8416 return (DAM_FAILURE);
8411 8417 }
8412 8418
8413 8419 return (DAM_SUCCESS);
8414 8420 }
8415 8421
8416 8422
8417 8423 static int
8418 8424 scsi_tgtmap_scsi_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid)
8419 8425 {
8420 8426 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
8421 8427 dev_info_t *self = tran->tran_iport_dip;
8422 8428 impl_scsi_tgtmap_t *tgtmap;
8423 8429 char *tgt_addr;
8424 8430
8425 8431 tgtmap = (impl_scsi_tgtmap_t *)tran->tran_tgtmap;
8426 8432 tgt_addr = damap_id2addr(mapp, tgtid);
8427 8433
8428 8434 SCSI_HBA_LOG((_LOGUNCFG, self, NULL, "%s @%s", damap_name(mapp),
8429 8435 tgt_addr));
8430 8436 scsi_lunmap_destroy(self, tgtmap, tgt_addr);
8431 8437 return (DAM_SUCCESS);
8432 8438 }
8433 8439
8434 8440 static int
8435 8441 scsi_tgtmap_smp_config(void *arg, damap_t *mapp, damap_id_t tgtid)
8436 8442 {
8437 8443 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
8438 8444 dev_info_t *self = tran->tran_iport_dip;
8439 8445 char *addr;
8440 8446
8441 8447 addr = damap_id2addr(mapp, tgtid);
8442 8448 SCSI_HBA_LOG((_LOGCFG, self, NULL, "%s @%s", damap_name(mapp), addr));
8443 8449
8444 8450 return ((smp_hba_bus_config_taddr(self, addr) == NDI_SUCCESS) ?
8445 8451 DAM_SUCCESS : DAM_FAILURE);
8446 8452 }
8447 8453
8448 8454 static int
8449 8455 scsi_tgtmap_smp_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid)
8450 8456 {
8451 8457 scsi_hba_tran_t *tran = (scsi_hba_tran_t *)arg;
8452 8458 dev_info_t *self = tran->tran_iport_dip;
8453 8459 char *addr;
8454 8460 dev_info_t *child;
8455 8461 char nameaddr[SCSI_MAXNAMELEN];
8456 8462 int circ;
8457 8463
8458 8464 addr = damap_id2addr(mapp, tgtid);
8459 8465 SCSI_HBA_LOG((_LOGUNCFG, self, NULL, "%s @%s", damap_name(mapp), addr));
8460 8466
8461 8467 (void) snprintf(nameaddr, sizeof (nameaddr), "smp@%s", addr);
8462 8468 scsi_hba_devi_enter(self, &circ);
8463 8469 if ((child = ndi_devi_findchild(self, nameaddr)) == NULL) {
8464 8470 scsi_hba_devi_exit(self, circ);
8465 8471 return (DAM_SUCCESS);
8466 8472 }
8467 8473
8468 8474 if (ndi_devi_offline(child,
8469 8475 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) {
8470 8476 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
8471 8477 "devinfo smp@%s offlined and removed", addr));
8472 8478 } else if (ndi_devi_device_remove(child)) {
8473 8479 /* Offline/remove failed, note new device_remove */
8474 8480 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
8475 8481 "devinfo smp@%s offline failed, device_remove",
8476 8482 addr));
8477 8483 }
8478 8484 scsi_hba_devi_exit(self, circ);
8479 8485 return (DAM_SUCCESS);
8480 8486 }
8481 8487
8482 8488 /* ARGSUSED1 */
8483 8489 static void
8484 8490 scsi_tgtmap_smp_activate(void *map_priv, char *tgt_addr, int addrid,
8485 8491 void **tgt_privp)
8486 8492 {
8487 8493 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)map_priv;
8488 8494 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8489 8495
8490 8496 if (tgtmap->tgtmap_activate_cb) {
8491 8497 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s @%s activated",
8492 8498 damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SMP_DEVICE]),
8493 8499 tgt_addr));
8494 8500
8495 8501 (*tgtmap->tgtmap_activate_cb)(tgtmap->tgtmap_mappriv,
8496 8502 tgt_addr, SCSI_TGT_SMP_DEVICE, tgt_privp);
8497 8503 }
8498 8504 }
8499 8505
8500 8506 /* ARGSUSED1 */
8501 8507 static void
8502 8508 scsi_tgtmap_smp_deactivate(void *map_priv, char *tgt_addr, int addrid,
8503 8509 void *tgt_privp, damap_deact_rsn_t damap_rsn)
8504 8510 {
8505 8511 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)map_priv;
8506 8512 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8507 8513 boolean_t tgtmap_rereport;
8508 8514 scsi_tgtmap_deact_rsn_t tgtmap_rsn;
8509 8515
8510 8516 if (tgtmap->tgtmap_deactivate_cb) {
8511 8517 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s @%s deactivated %d",
8512 8518 damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SMP_DEVICE]),
8513 8519 tgt_addr, damap_rsn));
8514 8520
8515 8521 if (damap_rsn == DAMAP_DEACT_RSN_GONE)
8516 8522 tgtmap_rsn = SCSI_TGT_DEACT_RSN_GONE;
8517 8523 else if (damap_rsn == DAMAP_DEACT_RSN_CFG_FAIL)
8518 8524 tgtmap_rsn = SCSI_TGT_DEACT_RSN_CFG_FAIL;
8519 8525 else if (damap_rsn == DAMAP_DEACT_RSN_UNSTBL)
8520 8526 tgtmap_rsn = SCSI_TGT_DEACT_RSN_UNSTBL;
8521 8527 else {
8522 8528 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
8523 8529 "%s @%s deactivated with unknown rsn",
8524 8530 damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SMP_DEVICE]),
8525 8531 tgt_addr));
8526 8532 return;
8527 8533 }
8528 8534
8529 8535 tgtmap_rereport = (*tgtmap->tgtmap_deactivate_cb)
8530 8536 (tgtmap->tgtmap_mappriv, tgt_addr,
8531 8537 SCSI_TGT_SMP_DEVICE, tgt_privp, tgtmap_rsn);
8532 8538
8533 8539 if ((tgtmap_rsn == SCSI_TGT_DEACT_RSN_CFG_FAIL) &&
8534 8540 (tgtmap_rereport == B_FALSE)) {
8535 8541 SCSI_HBA_LOG((_LOG(WARN), NULL, self,
8536 8542 "%s enumeration failed, no more retries until "
8537 8543 "config change occurs", tgt_addr));
8538 8544 }
8539 8545 }
8540 8546 }
8541 8547
8542 8548 /* ARGSUSED1 */
8543 8549 static void
8544 8550 scsi_tgtmap_scsi_activate(void *map_priv, char *tgt_addr, int addrid,
8545 8551 void **tgt_privp)
8546 8552 {
8547 8553 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)map_priv;
8548 8554 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8549 8555
8550 8556 if (tgtmap->tgtmap_activate_cb) {
8551 8557 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s @%s activated",
8552 8558 damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]),
8553 8559 tgt_addr));
8554 8560
8555 8561 (*tgtmap->tgtmap_activate_cb)(tgtmap->tgtmap_mappriv,
8556 8562 tgt_addr, SCSI_TGT_SCSI_DEVICE, tgt_privp);
8557 8563 }
8558 8564 }
8559 8565
8560 8566 /* ARGSUSED1 */
8561 8567 static void
8562 8568 scsi_tgtmap_scsi_deactivate(void *map_priv, char *tgt_addr, int addrid,
8563 8569 void *tgt_privp, damap_deact_rsn_t damap_rsn)
8564 8570 {
8565 8571 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)map_priv;
8566 8572 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8567 8573 boolean_t tgtmap_rereport;
8568 8574 scsi_tgtmap_deact_rsn_t tgtmap_rsn;
8569 8575
8570 8576 if (tgtmap->tgtmap_deactivate_cb) {
8571 8577 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s @%s deactivated %d",
8572 8578 damap_name(tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]),
8573 8579 tgt_addr, damap_rsn));
8574 8580
8575 8581 if (damap_rsn == DAMAP_DEACT_RSN_GONE)
8576 8582 tgtmap_rsn = SCSI_TGT_DEACT_RSN_GONE;
8577 8583 else if (damap_rsn == DAMAP_DEACT_RSN_CFG_FAIL)
8578 8584 tgtmap_rsn = SCSI_TGT_DEACT_RSN_CFG_FAIL;
8579 8585 else if (damap_rsn == DAMAP_DEACT_RSN_UNSTBL)
8580 8586 tgtmap_rsn = SCSI_TGT_DEACT_RSN_UNSTBL;
8581 8587 else {
8582 8588 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
8583 8589 "%s @%s deactivated with unknown rsn", damap_name(
8584 8590 tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]),
8585 8591 tgt_addr));
8586 8592 return;
8587 8593 }
8588 8594
8589 8595 tgtmap_rereport = (*tgtmap->tgtmap_deactivate_cb)
8590 8596 (tgtmap->tgtmap_mappriv, tgt_addr,
8591 8597 SCSI_TGT_SCSI_DEVICE, tgt_privp, tgtmap_rsn);
8592 8598
8593 8599 if ((tgtmap_rsn == SCSI_TGT_DEACT_RSN_CFG_FAIL) &&
8594 8600 (tgtmap_rereport == B_FALSE)) {
8595 8601 SCSI_HBA_LOG((_LOG(WARN), NULL, self,
8596 8602 "%s enumeration failed, no more retries until "
8597 8603 "config change occurs", tgt_addr));
8598 8604 }
8599 8605 }
8600 8606 }
8601 8607
8602 8608
8603 8609 int
8604 8610 scsi_hba_tgtmap_create(dev_info_t *self, scsi_tgtmap_mode_t mode,
8605 8611 int csync_usec, int settle_usec, void *tgtmap_priv,
8606 8612 scsi_tgt_activate_cb_t activate_cb, scsi_tgt_deactivate_cb_t deactivate_cb,
8607 8613 scsi_hba_tgtmap_t **handle)
8608 8614 {
8609 8615 scsi_hba_tran_t *tran;
8610 8616 damap_t *mapp;
8611 8617 char context[64];
8612 8618 impl_scsi_tgtmap_t *tgtmap;
8613 8619 damap_rptmode_t rpt_style;
8614 8620 char *scsi_binding_set;
8615 8621 int optflags;
8616 8622
8617 8623 if (self == NULL || csync_usec == 0 ||
8618 8624 settle_usec == 0 || handle == NULL)
8619 8625 return (DDI_FAILURE);
8620 8626
8621 8627 *handle = NULL;
8622 8628
8623 8629 if (scsi_hba_iport_unit_address(self) == NULL)
8624 8630 return (DDI_FAILURE);
8625 8631
8626 8632 switch (mode) {
8627 8633 case SCSI_TM_FULLSET:
8628 8634 rpt_style = DAMAP_REPORT_FULLSET;
8629 8635 break;
8630 8636 case SCSI_TM_PERADDR:
8631 8637 rpt_style = DAMAP_REPORT_PERADDR;
8632 8638 break;
8633 8639 default:
8634 8640 return (DDI_FAILURE);
8635 8641 }
8636 8642
8637 8643 tran = (scsi_hba_tran_t *)ddi_get_driver_private(self);
8638 8644 ASSERT(tran);
8639 8645 if (tran == NULL)
8640 8646 return (DDI_FAILURE);
8641 8647
8642 8648 tgtmap = kmem_zalloc(sizeof (*tgtmap), KM_SLEEP);
8643 8649 tgtmap->tgtmap_tran = tran;
8644 8650 tgtmap->tgtmap_activate_cb = activate_cb;
8645 8651 tgtmap->tgtmap_deactivate_cb = deactivate_cb;
8646 8652 tgtmap->tgtmap_mappriv = tgtmap_priv;
8647 8653
8648 8654 tgtmap->tgtmap_create_window = 1; /* start with window */
8649 8655 tgtmap->tgtmap_create_time = ddi_get_lbolt64();
8650 8656 tgtmap->tgtmap_create_csync_usec = csync_usec;
8651 8657 tgtmap->tgtmap_settle_usec = settle_usec;
8652 8658 tgtmap->tgtmap_sync_cnt = 0;
8653 8659
8654 8660 optflags = (ddi_prop_get_int(DDI_DEV_T_ANY, self,
8655 8661 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration",
8656 8662 scsi_enumeration) & SCSI_ENUMERATION_MT_TARGET_DISABLE) ?
8657 8663 DAMAP_SERIALCONFIG : DAMAP_MTCONFIG;
8658 8664
8659 8665 (void) snprintf(context, sizeof (context), "%s%d.tgtmap.scsi",
8660 8666 ddi_driver_name(self), ddi_get_instance(self));
8661 8667 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context));
8662 8668 if (damap_create(context, rpt_style, optflags, settle_usec,
8663 8669 tgtmap, scsi_tgtmap_scsi_activate, scsi_tgtmap_scsi_deactivate,
8664 8670 tran, scsi_tgtmap_scsi_config, scsi_tgtmap_scsi_unconfig,
8665 8671 &mapp) != DAM_SUCCESS) {
8666 8672 kmem_free(tgtmap, sizeof (*tgtmap));
8667 8673 return (DDI_FAILURE);
8668 8674 }
8669 8675 tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE] = mapp;
8670 8676
8671 8677 (void) snprintf(context, sizeof (context), "%s%d.tgtmap.smp",
8672 8678 ddi_driver_name(self), ddi_get_instance(self));
8673 8679 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context));
8674 8680 if (damap_create(context, rpt_style, optflags,
8675 8681 settle_usec, tgtmap, scsi_tgtmap_smp_activate,
8676 8682 scsi_tgtmap_smp_deactivate,
8677 8683 tran, scsi_tgtmap_smp_config, scsi_tgtmap_smp_unconfig,
8678 8684 &mapp) != DAM_SUCCESS) {
8679 8685 damap_destroy(tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE]);
8680 8686 kmem_free(tgtmap, sizeof (*tgtmap));
8681 8687 return (DDI_FAILURE);
8682 8688 }
8683 8689 tgtmap->tgtmap_dam[SCSI_TGT_SMP_DEVICE] = mapp;
8684 8690
8685 8691 tran->tran_tgtmap = (scsi_hba_tgtmap_t *)tgtmap;
8686 8692 *handle = (scsi_hba_tgtmap_t *)tgtmap;
8687 8693
8688 8694 /*
8689 8695 * We have now set tran_tgtmap, marking the tran as using tgtmap
8690 8696 * enumeration services. To prevent the generation of legacy spi
8691 8697 * 'binding-set' compatible forms, remove the 'scsi-binding-set'
8692 8698 * property.
8693 8699 */
8694 8700 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, self,
8695 8701 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-binding-set",
8696 8702 &scsi_binding_set) == DDI_PROP_SUCCESS) {
8697 8703 if (strcmp(scsi_binding_set, scsi_binding_set_spi) == 0)
8698 8704 (void) ndi_prop_remove(DDI_DEV_T_NONE, self,
8699 8705 "scsi-binding-set");
8700 8706 ddi_prop_free(scsi_binding_set);
8701 8707 }
8702 8708 return (DDI_SUCCESS);
8703 8709 }
8704 8710
8705 8711 void
8706 8712 scsi_hba_tgtmap_destroy(scsi_hba_tgtmap_t *handle)
8707 8713 {
8708 8714 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8709 8715 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8710 8716 int i;
8711 8717
8712 8718 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8713 8719 if (tgtmap->tgtmap_dam[i]) {
8714 8720 SCSI_HBA_LOG((_LOGTGT, self, NULL,
8715 8721 "%s", damap_name(tgtmap->tgtmap_dam[i])));
8716 8722 damap_destroy(tgtmap->tgtmap_dam[i]);
8717 8723 }
8718 8724 }
8719 8725 kmem_free(tgtmap, sizeof (*tgtmap));
8720 8726 }
8721 8727
8722 8728 /* return 1 if all maps ended up syned */
8723 8729 static int
8724 8730 scsi_tgtmap_sync(scsi_hba_tgtmap_t *handle, int sync_usec)
8725 8731 {
8726 8732 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8727 8733 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8728 8734 int all_synced = 1;
8729 8735 int synced;
8730 8736 int i;
8731 8737
8732 8738 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8733 8739 if (tgtmap->tgtmap_dam[i]) {
8734 8740 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s sync begin",
8735 8741 damap_name(tgtmap->tgtmap_dam[i])));
8736 8742 synced = damap_sync(tgtmap->tgtmap_dam[i], sync_usec);
8737 8743 all_synced &= synced;
8738 8744 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s sync end %d",
8739 8745 damap_name(tgtmap->tgtmap_dam[i]), synced));
8740 8746
8741 8747 }
8742 8748 }
8743 8749 return (all_synced);
8744 8750 }
8745 8751
8746 8752 /* return 1 if all maps ended up empty */
8747 8753 static int
8748 8754 scsi_tgtmap_is_empty(scsi_hba_tgtmap_t *handle)
8749 8755 {
8750 8756 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8751 8757 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8752 8758 int all_empty = 1;
8753 8759 int empty;
8754 8760 int i;
8755 8761
8756 8762 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8757 8763 if (tgtmap->tgtmap_dam[i]) {
8758 8764 empty = damap_is_empty(tgtmap->tgtmap_dam[i]);
8759 8765 all_empty &= empty;
8760 8766 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s is_empty %d",
8761 8767 damap_name(tgtmap->tgtmap_dam[i]), empty));
8762 8768 }
8763 8769 }
8764 8770
8765 8771 return (all_empty);
8766 8772 }
8767 8773
8768 8774 static int
8769 8775 scsi_tgtmap_beginf(scsi_hba_tgtmap_t *handle, boolean_t do_begin)
8770 8776 {
8771 8777 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8772 8778 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8773 8779 char *context;
8774 8780 int rv = DAM_SUCCESS;
8775 8781 int i;
8776 8782
8777 8783 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8778 8784 if (tgtmap->tgtmap_dam[i] == NULL) {
8779 8785 continue;
8780 8786 }
8781 8787
8782 8788 context = damap_name(tgtmap->tgtmap_dam[i]);
8783 8789 if (do_begin == B_TRUE) {
8784 8790 if (i == SCSI_TGT_SCSI_DEVICE) {
8785 8791 /*
8786 8792 * In scsi_device context, so we have the
8787 8793 * 'context' string, diagnose the case where
8788 8794 * the tgtmap caller is failing to make
8789 8795 * forward progress, i.e. the caller is never
8790 8796 * completing an observation by calling
8791 8797 * scsi_hbg_tgtmap_set_end. If this occurs,
8792 8798 * the solaris target/lun state may be out
8793 8799 * of sync with hardware.
8794 8800 */
8795 8801 if (tgtmap->tgtmap_reports++ >=
8796 8802 scsi_hba_tgtmap_reports_max) {
8797 8803 tgtmap->tgtmap_noisy++;
8798 8804 if (tgtmap->tgtmap_noisy == 1) {
8799 8805 SCSI_HBA_LOG((_LOG(WARN),
8800 8806 self, NULL,
8801 8807 "%s: failing tgtmap begin",
8802 8808 context));
8803 8809 }
8804 8810 }
8805 8811 }
8806 8812
8807 8813 rv = damap_addrset_begin(tgtmap->tgtmap_dam[i]);
8808 8814 } else {
8809 8815 rv = damap_addrset_flush(tgtmap->tgtmap_dam[i]);
8810 8816 }
8811 8817
8812 8818 if (rv != DAM_SUCCESS) {
8813 8819 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s FAIL", context));
8814 8820 } else {
8815 8821 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context));
8816 8822 }
8817 8823 }
8818 8824
8819 8825 return ((rv == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
8820 8826 }
8821 8827
8822 8828
8823 8829 int
8824 8830 scsi_hba_tgtmap_set_begin(scsi_hba_tgtmap_t *handle)
8825 8831 {
8826 8832 return (scsi_tgtmap_beginf(handle, B_TRUE));
8827 8833 }
8828 8834
8829 8835 int
8830 8836 scsi_hba_tgtmap_set_flush(scsi_hba_tgtmap_t *handle)
8831 8837 {
8832 8838 return (scsi_tgtmap_beginf(handle, B_FALSE));
8833 8839 }
8834 8840
8835 8841 int
8836 8842 scsi_hba_tgtmap_set_add(scsi_hba_tgtmap_t *handle,
8837 8843 scsi_tgtmap_tgt_type_t tgt_type, char *tgt_addr, void *tgt_priv)
8838 8844 {
8839 8845 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8840 8846 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8841 8847
8842 8848 if (tgt_type >= SCSI_TGT_NTYPES || !tgtmap->tgtmap_dam[tgt_type])
8843 8849 return (DDI_FAILURE);
8844 8850
8845 8851 SCSI_HBA_LOG((_LOGTGT, self, NULL,
8846 8852 "%s @%s", damap_name(tgtmap->tgtmap_dam[tgt_type]), tgt_addr));
8847 8853
8848 8854 return ((damap_addrset_add(tgtmap->tgtmap_dam[tgt_type], tgt_addr,
8849 8855 NULL, NULL, tgt_priv) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
8850 8856 }
8851 8857
8852 8858 /*ARGSUSED*/
8853 8859 int
8854 8860 scsi_hba_tgtmap_set_end(scsi_hba_tgtmap_t *handle, uint_t flags)
8855 8861 {
8856 8862 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8857 8863 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8858 8864 char *context;
8859 8865 int rv = DDI_SUCCESS;
8860 8866 int i;
8861 8867
8862 8868 tgtmap->tgtmap_reports = tgtmap->tgtmap_noisy = 0;
8863 8869
8864 8870 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8865 8871 if (tgtmap->tgtmap_dam[i] == NULL)
8866 8872 continue;
8867 8873 context = damap_name(tgtmap->tgtmap_dam[i]);
8868 8874 if (damap_addrset_end(
8869 8875 tgtmap->tgtmap_dam[i], 0) != DAM_SUCCESS) {
8870 8876 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s FAIL", context));
8871 8877 rv = DDI_FAILURE;
8872 8878 continue;
8873 8879 }
8874 8880
8875 8881 SCSI_HBA_LOG((_LOGTGT, self, NULL, "%s", context));
8876 8882 }
8877 8883 return (rv);
8878 8884 }
8879 8885
8880 8886 int
8881 8887 scsi_hba_tgtmap_tgt_add(scsi_hba_tgtmap_t *handle,
8882 8888 scsi_tgtmap_tgt_type_t tgt_type, char *tgt_addr, void *tgt_priv)
8883 8889
8884 8890 {
8885 8891 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8886 8892 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8887 8893
8888 8894 if (tgt_type >= SCSI_TGT_NTYPES || !tgtmap->tgtmap_dam[tgt_type])
8889 8895 return (DDI_FAILURE);
8890 8896
8891 8897 SCSI_HBA_LOG((_LOGTGT, self, NULL,
8892 8898 "%s @%s", damap_name(tgtmap->tgtmap_dam[tgt_type]), tgt_addr));
8893 8899
8894 8900 return ((damap_addr_add(tgtmap->tgtmap_dam[tgt_type], tgt_addr, NULL,
8895 8901 NULL, tgt_priv) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
8896 8902 }
8897 8903
8898 8904 int
8899 8905 scsi_hba_tgtmap_tgt_remove(scsi_hba_tgtmap_t *handle,
8900 8906 scsi_tgtmap_tgt_type_t tgt_type, char *tgt_addr)
8901 8907 {
8902 8908 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8903 8909 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8904 8910
8905 8911 if (tgt_type >= SCSI_TGT_NTYPES || !tgtmap->tgtmap_dam[tgt_type])
8906 8912 return (DDI_FAILURE);
8907 8913
8908 8914 SCSI_HBA_LOG((_LOGTGT, self, NULL,
8909 8915 "%s @%s", damap_name(tgtmap->tgtmap_dam[tgt_type]), tgt_addr));
8910 8916
8911 8917 return ((damap_addr_del(tgtmap->tgtmap_dam[tgt_type],
8912 8918 tgt_addr) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
8913 8919 }
8914 8920
8915 8921 int
8916 8922 scsi_hba_tgtmap_lookup(scsi_hba_tgtmap_t *handle,
8917 8923 char *tgt_addr, scsi_tgtmap_tgt_type_t *r_type)
8918 8924 {
8919 8925 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)handle;
8920 8926 dev_info_t *self = tgtmap->tgtmap_tran->tran_iport_dip;
8921 8927 damap_id_t tgtid;
8922 8928 int i;
8923 8929
8924 8930 for (i = 0; i < SCSI_TGT_NTYPES; i++) {
8925 8931 tgtid = damap_lookup(tgtmap->tgtmap_dam[i], tgt_addr);
8926 8932 if (tgtid != NODAM) {
8927 8933 *r_type = i;
8928 8934 SCSI_HBA_LOG((_LOG(3), self, NULL,
8929 8935 "%s @%s found: type %d",
8930 8936 damap_name(tgtmap->tgtmap_dam[i]), tgt_addr, i));
8931 8937 damap_id_rele(tgtmap->tgtmap_dam[i], tgtid);
8932 8938 return (DDI_SUCCESS);
8933 8939 }
8934 8940 }
8935 8941
8936 8942 SCSI_HBA_LOG((_LOG(3), self, NULL,
8937 8943 "%s%d.tgtmap @%s not found",
8938 8944 ddi_driver_name(self), ddi_get_instance(self), tgt_addr));
8939 8945 return (DDI_FAILURE);
8940 8946 }
8941 8947
8942 8948 /*
8943 8949 * Return the unit-address of an 'iport' node, or NULL for non-iport node.
8944 8950 */
8945 8951 char *
8946 8952 scsi_hba_iport_unit_address(dev_info_t *self)
8947 8953 {
8948 8954 /*
8949 8955 * NOTE: Since 'self' could be a SCSA iport node or a SCSA HBA node,
8950 8956 * we can't use SCSA flavors: the flavor of a SCSA HBA node is not
8951 8957 * established/owned by SCSA, it is established by the nexus that
8952 8958 * created the SCSA HBA node (PCI) as a child.
8953 8959 *
8954 8960 * NOTE: If we want to support a node_name other than "iport" for
8955 8961 * an iport node then we can add support for a "scsa-iport-node-name"
8956 8962 * property on the SCSA HBA node. A SCSA HBA driver would set this
8957 8963 * property on the SCSA HBA node prior to using the iport API.
8958 8964 */
8959 8965 if (strcmp(ddi_node_name(self), "iport") == 0)
8960 8966 return (ddi_get_name_addr(self));
8961 8967 else
8962 8968 return (NULL);
8963 8969 }
8964 8970
8965 8971 /*
8966 8972 * Define a SCSI initiator port (bus/channel) for an HBA card that needs to
8967 8973 * support multiple SCSI ports, but only has a single HBA devinfo node. This
8968 8974 * function should be called from the HBA's attach(9E) implementation (when
8969 8975 * processing the HBA devinfo node attach) after the number of SCSI ports on
8970 8976 * the card is known or when the HBA driver DR handler detects a new port.
8971 8977 * The function returns 0 on failure and 1 on success.
8972 8978 *
8973 8979 * The implementation will add the port value into the "scsi-iports" property
8974 8980 * value maintained on the HBA node as. These properties are used by the generic
8975 8981 * scsi bus_config implementation to dynamicaly enumerate the specified iport
8976 8982 * children. The enumeration code will, on demand, create the appropriate
8977 8983 * iport children with a SCSI_ADDR_PROP_IPORTUA unit address. This node will
8978 8984 * bind to the same driver as the HBA node itself. This means that an HBA
8979 8985 * driver that uses iports should expect probe(9E), attach(9E), and detach(9E)
8980 8986 * calls on the iport children of the HBA. If configuration for all ports was
8981 8987 * already done during HBA node attach, the driver should just return
8982 8988 * DDI_SUCCESS when confronted with an iport node.
8983 8989 *
8984 8990 * A maximum of 32 iport ports are supported per HBA devinfo node.
8985 8991 *
8986 8992 * A NULL "port" can be used to indicate that the framework should enumerate
8987 8993 * target children on the HBA node itself, in addition to enumerating target
8988 8994 * children on any iport nodes declared. There are two reasons that an HBA may
8989 8995 * wish to have target children enumerated on both the HBA node and iport
8990 8996 * node(s):
8991 8997 *
8992 8998 * o If, in the past, HBA hardware had only a single physical port but now
8993 8999 * supports multiple physical ports, the updated driver that supports
8994 9000 * multiple physical ports may want to avoid /devices path upgrade issues
8995 9001 * by enumerating the first physical port under the HBA instead of as a
8996 9002 * iport.
8997 9003 *
8998 9004 * o Some hardware RAID HBA controllers (mlx, chs, etc) support multiple
8999 9005 * SCSI physical ports configured so that various physical devices on
9000 9006 * the physical ports are amalgamated into virtual devices on a virtual
9001 9007 * port. Amalgamated physical devices no longer appear to the host OS
9002 9008 * on the physical ports, but other non-amalgamated devices may still be
9003 9009 * visible on the physical ports. These drivers use a model where the
9004 9010 * physical ports are iport nodes and the HBA node is the virtual port to
9005 9011 * the configured virtual devices.
9006 9012 */
9007 9013 int
9008 9014 scsi_hba_iport_register(dev_info_t *self, char *port)
9009 9015 {
9010 9016 unsigned int ports = 0;
9011 9017 int rval, i;
9012 9018 char **iports, **newiports;
9013 9019
9014 9020 ASSERT(self);
9015 9021 if (self == NULL)
9016 9022 return (DDI_FAILURE);
9017 9023
9018 9024 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, self,
9019 9025 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-iports", &iports,
9020 9026 &ports);
9021 9027
9022 9028 if (ports >= SCSI_HBA_MAX_IPORTS) {
9023 9029 ddi_prop_free(iports);
9024 9030 return (DDI_FAILURE);
9025 9031 }
9026 9032
9027 9033 if (rval == DDI_PROP_SUCCESS) {
9028 9034 for (i = 0; i < ports; i++) {
9029 9035 if (strcmp(port, iports[i]) == 0) {
9030 9036 /* iport already registered */
9031 9037 ddi_prop_free(iports);
9032 9038 return (DDI_SUCCESS);
9033 9039 }
9034 9040 }
9035 9041 }
9036 9042
9037 9043 newiports = kmem_alloc((sizeof (char *) * (ports + 1)), KM_SLEEP);
9038 9044
9039 9045 for (i = 0; i < ports; i++) {
9040 9046 newiports[i] = strdup(iports[i]);
9041 9047 }
9042 9048 newiports[ports] = strdup(port);
9043 9049 ports++;
9044 9050
9045 9051 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, self,
9046 9052 "scsi-iports", newiports, ports) != DDI_PROP_SUCCESS) {
9047 9053 SCSI_HBA_LOG((_LOG(WARN), self, NULL,
9048 9054 "failed to establish %s %s",
9049 9055 SCSI_ADDR_PROP_IPORTUA, port));
9050 9056 rval = DDI_FAILURE;
9051 9057 } else {
9052 9058 rval = DDI_SUCCESS;
9053 9059 }
9054 9060
9055 9061 /* If there is iport exist, free property */
9056 9062 if (ports > 1)
9057 9063 ddi_prop_free(iports);
9058 9064 for (i = 0; i < ports; i++) {
9059 9065 strfree(newiports[i]);
9060 9066 }
9061 9067 kmem_free(newiports, (sizeof (char *)) * ports);
9062 9068
9063 9069 return (rval);
9064 9070 }
9065 9071
9066 9072 /*
9067 9073 * Check if the HBA has any scsi_hba_iport_register()ed children.
9068 9074 */
9069 9075 int
9070 9076 scsi_hba_iport_exist(dev_info_t *self)
9071 9077 {
9072 9078 unsigned int ports = 0;
9073 9079 char **iports;
9074 9080 int rval;
9075 9081
9076 9082 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, self,
9077 9083 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-iports", &iports,
9078 9084 &ports);
9079 9085
9080 9086 if (rval != DDI_PROP_SUCCESS)
9081 9087 return (0);
9082 9088
9083 9089 /* If there is now at least 1 iport, then iports is valid */
9084 9090 if (ports > 0) {
9085 9091 rval = 1;
9086 9092 } else
9087 9093 rval = 0;
9088 9094 ddi_prop_free(iports);
9089 9095
9090 9096 return (rval);
9091 9097 }
9092 9098
9093 9099 dev_info_t *
9094 9100 scsi_hba_iport_find(dev_info_t *self, char *portnm)
9095 9101 {
9096 9102 char *addr = NULL;
9097 9103 char **iports;
9098 9104 unsigned int num_iports = 0;
9099 9105 int rval = DDI_FAILURE;
9100 9106 int i = 0;
9101 9107 dev_info_t *child = NULL;
9102 9108
9103 9109 /* check to see if this is an HBA that defined scsi iports */
9104 9110 rval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, self,
9105 9111 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-iports", &iports,
9106 9112 &num_iports);
9107 9113
9108 9114 if (rval != DDI_SUCCESS) {
9109 9115 return (NULL);
9110 9116 }
9111 9117 ASSERT(num_iports > 0);
9112 9118
9113 9119 /* check to see if this port was registered */
9114 9120 for (i = 0; i < num_iports; i++) {
9115 9121 if (strcmp(iports[i], portnm) == 0)
9116 9122 break;
9117 9123 }
9118 9124
9119 9125 if (i == num_iports) {
9120 9126 child = NULL;
9121 9127 goto out;
9122 9128 }
9123 9129
9124 9130 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
9125 9131 (void) snprintf(addr, SCSI_MAXNAMELEN, "iport@%s", portnm);
9126 9132 rval = ndi_devi_config_one(self, addr, &child, NDI_NO_EVENT);
9127 9133 kmem_free(addr, SCSI_MAXNAMELEN);
9128 9134
9129 9135 if (rval != DDI_SUCCESS) {
9130 9136 child = NULL;
9131 9137 }
9132 9138 out:
9133 9139 ddi_prop_free(iports);
9134 9140 return (child);
9135 9141 }
9136 9142
9137 9143 /*
9138 9144 * Search/create the specified iport node
9139 9145 */
9140 9146 static dev_info_t *
9141 9147 scsi_hba_bus_config_port(dev_info_t *self, char *nameaddr, scsi_enum_t se)
9142 9148 {
9143 9149 dev_info_t *child; /* iport child of HBA node */
9144 9150 scsi_hba_tran_t *tran;
9145 9151 char *addr;
9146 9152 char *compat;
9147 9153
9148 9154 /*
9149 9155 * See if the iport node already exists.
9150 9156 */
9151 9157 addr = nameaddr + strlen("iport@");
9152 9158 if (child = ndi_devi_findchild(self, nameaddr)) {
9153 9159 if (ndi_devi_device_isremoved(child)) {
9154 9160 if ((se == SE_HP) || !ndi_dev_is_hotplug_node(child)) {
9155 9161 if (ndi_devi_device_insert(child))
9156 9162 SCSI_HBA_LOG((_LOGCFG, self, NULL,
9157 9163 "devinfo iport@%s device_reinsert",
9158 9164 addr));
9159 9165 } else
9160 9166 return (NULL);
9161 9167 }
9162 9168 return (child);
9163 9169 }
9164 9170
9165 9171
9166 9172 /*
9167 9173 * If config based on scsi_hba_iportmap API, only allow create
9168 9174 * from hotplug.
9169 9175 */
9170 9176 tran = ndi_flavorv_get(self, SCSA_FLAVOR_SCSI_DEVICE);
9171 9177 ASSERT(tran);
9172 9178 if (tran->tran_iportmap && (se != SE_HP))
9173 9179 return (NULL);
9174 9180
9175 9181 /* allocate and initialize a new "iport" node */
9176 9182 ndi_devi_alloc_sleep(self, "iport",
9177 9183 (se == SE_HP) ? DEVI_SID_HP_NODEID : DEVI_SID_NODEID,
9178 9184 &child);
9179 9185 ASSERT(child);
9180 9186 /*
9181 9187 * Set the flavor of the child to be IPORT flavored
9182 9188 */
9183 9189 ndi_flavor_set(child, SCSA_FLAVOR_IPORT);
9184 9190
9185 9191 /*
9186 9192 * Add the SCSI_ADDR_PROP_IPORTUA addressing property for this child.
9187 9193 * This property is used to identify a iport node, and to represent the
9188 9194 * nodes @addr form via node properties.
9189 9195 *
9190 9196 * Add "compatible" property to the "scsi-iport" node to cause it bind
9191 9197 * to the same driver as the HBA driver. Use the "driver" name
9192 9198 * instead of the "binding name" to distinguish from hw node.
9193 9199 *
9194 9200 * Give the HBA a chance, via tran_set_name_prop, to set additional
9195 9201 * iport node properties or to change the "compatible" binding
9196 9202 * prior to init_child.
9197 9203 *
9198 9204 * NOTE: the order of these operations is important so that
9199 9205 * scsi_hba_iport works when called.
9200 9206 */
9201 9207 compat = (char *)ddi_driver_name(self);
9202 9208 if ((ndi_prop_update_string(DDI_DEV_T_NONE, child,
9203 9209 SCSI_ADDR_PROP_IPORTUA, addr) != DDI_PROP_SUCCESS) ||
9204 9210 (ndi_prop_update_string_array(DDI_DEV_T_NONE, child,
9205 9211 "compatible", &compat, 1) != DDI_PROP_SUCCESS) ||
9206 9212 ddi_pathname_obp_set(child, NULL) != DDI_SUCCESS) {
9207 9213 SCSI_HBA_LOG((_LOG_NF(WARN), "%s failed dynamic decoration",
9208 9214 nameaddr));
9209 9215 (void) ddi_remove_child(child, 0);
9210 9216 child = NULL;
9211 9217 } else {
9212 9218 /*
9213 9219 * Online/attach in order to get events so devfsadm will
9214 9220 * create public names.
9215 9221 */
9216 9222 ndi_hold_devi(child);
9217 9223 if (ndi_devi_online(child, 0) != NDI_SUCCESS) {
9218 9224 ndi_rele_devi(child);
9219 9225 ndi_prop_remove_all(child);
9220 9226 (void) ndi_devi_free(child);
9221 9227 child = NULL;
9222 9228 } else
9223 9229 ndi_rele_devi(child);
9224 9230 }
9225 9231
9226 9232 return (child);
9227 9233 }
9228 9234
9229 9235 #ifdef sparc
9230 9236 /*
9231 9237 * Future: When iportmap boot support is added, consider rewriting this to
9232 9238 * perform a scsi_hba_bus_config(BUS_CONFIG_ALL) on self (HBA) followed by
9233 9239 * a scsi_hba_bus_config(BUS_CONFIG_ONE) on each child of self (each iport).
9234 9240 */
9235 9241 /* ARGSUSED */
9236 9242 static int
9237 9243 scsi_hba_bus_config_prom_node(dev_info_t *self, uint_t flags,
9238 9244 void *arg, dev_info_t **childp)
9239 9245 {
9240 9246 char **iports;
9241 9247 int circ, i;
9242 9248 int ret = NDI_FAILURE;
9243 9249 unsigned int num_iports = 0;
9244 9250 dev_info_t *pdip = NULL;
9245 9251 char *addr = NULL;
9246 9252
9247 9253 /* check to see if this is an HBA that defined scsi iports */
9248 9254 ret = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, self,
9249 9255 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-iports", &iports,
9250 9256 &num_iports);
9251 9257
9252 9258 if (ret != DDI_SUCCESS) {
9253 9259 return (ret);
9254 9260 }
9255 9261
9256 9262 ASSERT(num_iports > 0);
9257 9263
9258 9264 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
9259 9265
9260 9266 ret = NDI_FAILURE;
9261 9267
9262 9268 scsi_hba_devi_enter(self, &circ);
9263 9269
9264 9270 /* create iport nodes for each scsi port/bus */
9265 9271 for (i = 0; i < num_iports; i++) {
9266 9272 bzero(addr, SCSI_MAXNAMELEN);
9267 9273 /* Prepend the iport name */
9268 9274 (void) snprintf(addr, SCSI_MAXNAMELEN, "iport@%s",
9269 9275 iports[i]);
9270 9276 if (pdip = scsi_hba_bus_config_port(self, addr, SE_BUSCONFIG)) {
9271 9277 if (ndi_busop_bus_config(self, NDI_NO_EVENT,
9272 9278 BUS_CONFIG_ONE, addr, &pdip, 0) !=
9273 9279 NDI_SUCCESS) {
9274 9280 continue;
9275 9281 }
9276 9282 /*
9277 9283 * Try to configure child under iport see wehter
9278 9284 * request node is the child of the iport node
9279 9285 */
9280 9286 if (ndi_devi_config_one(pdip, arg, childp,
9281 9287 NDI_NO_EVENT) == NDI_SUCCESS) {
9282 9288 ret = NDI_SUCCESS;
9283 9289 break;
9284 9290 }
9285 9291 }
9286 9292 }
9287 9293
9288 9294 scsi_hba_devi_exit(self, circ);
9289 9295
9290 9296 kmem_free(addr, SCSI_MAXNAMELEN);
9291 9297
9292 9298 ddi_prop_free(iports);
9293 9299
9294 9300 return (ret);
9295 9301 }
9296 9302 #endif
9297 9303
9298 9304 /*
9299 9305 * Perform iport port/bus bus_config.
9300 9306 */
9301 9307 static int
9302 9308 scsi_hba_bus_config_iports(dev_info_t *self, uint_t flags,
9303 9309 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
9304 9310 {
9305 9311 char *nameaddr, *addr;
9306 9312 char **iports;
9307 9313 int circ, i;
9308 9314 int ret = NDI_FAILURE;
9309 9315 unsigned int num_iports = 0;
9310 9316
9311 9317 /* check to see if this is an HBA that defined scsi iports */
9312 9318 ret = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, self,
9313 9319 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "scsi-iports", &iports,
9314 9320 &num_iports);
9315 9321
9316 9322 if (ret != DDI_SUCCESS) {
9317 9323 return (ret);
9318 9324 }
9319 9325
9320 9326 ASSERT(num_iports > 0);
9321 9327
9322 9328 scsi_hba_devi_enter(self, &circ);
9323 9329
9324 9330 switch (op) {
9325 9331 case BUS_CONFIG_ONE:
9326 9332 /* return if this operation is not against an iport node */
9327 9333 nameaddr = (char *)arg;
9328 9334 if ((nameaddr == NULL) ||
9329 9335 (strncmp(nameaddr, "iport@", strlen("iport@")) != 0)) {
9330 9336 ret = NDI_FAILURE;
9331 9337 scsi_hba_devi_exit(self, circ);
9332 9338 ddi_prop_free(iports);
9333 9339 return (ret);
9334 9340 }
9335 9341
9336 9342 /* parse the port number from "iport@%s" */
9337 9343 addr = nameaddr + strlen("iport@");
9338 9344
9339 9345 /* check to see if this port was registered */
9340 9346 for (i = 0; i < num_iports; i++) {
9341 9347 if (strcmp((iports[i]), addr) == 0)
9342 9348 break;
9343 9349 }
9344 9350
9345 9351 if (i == num_iports) {
9346 9352 ret = NDI_FAILURE;
9347 9353 break;
9348 9354 }
9349 9355
9350 9356 /* create the iport node child */
9351 9357 if (scsi_hba_bus_config_port(self, nameaddr, SE_BUSCONFIG)) {
9352 9358 ret = NDI_SUCCESS;
9353 9359 }
9354 9360 break;
9355 9361
9356 9362 case BUS_CONFIG_ALL:
9357 9363 case BUS_CONFIG_DRIVER:
9358 9364 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
9359 9365 /* create iport nodes for each scsi port/bus */
9360 9366 for (i = 0; i < num_iports; i++) {
9361 9367 bzero(addr, SCSI_MAXNAMELEN);
9362 9368 /* Prepend the iport name */
9363 9369 (void) snprintf(addr, SCSI_MAXNAMELEN, "iport@%s",
9364 9370 iports[i]);
9365 9371 (void) scsi_hba_bus_config_port(self, addr,
9366 9372 SE_BUSCONFIG);
9367 9373 }
9368 9374
9369 9375 kmem_free(addr, SCSI_MAXNAMELEN);
9370 9376 ret = NDI_SUCCESS;
9371 9377 break;
9372 9378 }
9373 9379 if (ret == NDI_SUCCESS) {
9374 9380 #ifdef sparc
9375 9381 /*
9376 9382 * Mask NDI_PROMNAME since PROM doesn't have iport
9377 9383 * node at all.
9378 9384 */
9379 9385 flags &= (~NDI_PROMNAME);
9380 9386 #endif
9381 9387 flags |= NDI_MDI_FALLBACK; /* devinfo&pathinfo children */
9382 9388 ret = ndi_busop_bus_config(self, flags, op,
9383 9389 arg, childp, 0);
9384 9390 }
9385 9391 scsi_hba_devi_exit(self, circ);
9386 9392
9387 9393 ddi_prop_free(iports);
9388 9394
9389 9395 return (ret);
9390 9396 }
9391 9397
9392 9398 static int
9393 9399 scsi_iportmap_config(void *arg, damap_t *mapp, damap_id_t tgtid)
9394 9400 {
9395 9401 dev_info_t *self = (dev_info_t *)arg;
9396 9402 int circ;
9397 9403 char nameaddr[SCSI_MAXNAMELEN];
9398 9404 char *iport_addr;
9399 9405 dev_info_t *childp;
9400 9406
9401 9407 scsi_hba_devi_enter(self, &circ);
9402 9408
9403 9409 iport_addr = damap_id2addr(mapp, tgtid);
9404 9410 SCSI_HBA_LOG((_LOGIPT, self, NULL,
9405 9411 "%s @%s", damap_name(mapp), iport_addr));
9406 9412
9407 9413 (void) snprintf(nameaddr, sizeof (nameaddr), "iport@%s", iport_addr);
9408 9414 childp = scsi_hba_bus_config_port(self, nameaddr, SE_HP);
9409 9415 scsi_hba_devi_exit(self, circ);
9410 9416 return (childp != NULL ? DAM_SUCCESS : DAM_FAILURE);
9411 9417 }
9412 9418
9413 9419 static int
9414 9420 scsi_iportmap_unconfig(void *arg, damap_t *mapp, damap_id_t tgtid)
9415 9421 {
9416 9422 dev_info_t *self = arg;
9417 9423 dev_info_t *childp; /* iport child of HBA node */
9418 9424 int circ, empty;
9419 9425 char *addr;
9420 9426 char nameaddr[SCSI_MAXNAMELEN];
9421 9427 scsi_hba_tran_t *tran;
9422 9428
9423 9429 addr = damap_id2addr(mapp, tgtid);
9424 9430 SCSI_HBA_LOG((_LOGIPT, self, NULL, "%s @%s", damap_name(mapp), addr));
9425 9431
9426 9432 (void) snprintf(nameaddr, sizeof (nameaddr), "iport@%s", addr);
9427 9433 scsi_hba_devi_enter(self, &circ);
9428 9434 if ((childp = ndi_devi_findchild(self, nameaddr)) == NULL) {
9429 9435 scsi_hba_devi_exit(self, circ);
9430 9436 return (DAM_FAILURE);
9431 9437 }
9432 9438
9433 9439 tran = ddi_get_driver_private(childp);
9434 9440 ASSERT(tran);
9435 9441
9436 9442 ndi_hold_devi(childp);
9437 9443 scsi_hba_devi_exit(self, circ);
9438 9444
9439 9445 /*
9440 9446 * A begin/end (clear) against the iport's
9441 9447 * tgtmap will trigger unconfigure of all
9442 9448 * targets on the iport.
9443 9449 *
9444 9450 * Future: This bit of code only works if the
9445 9451 * target map reporting style is are full
9446 9452 * reports and not per-address. Maybe we
9447 9453 * should plan on handling this by
9448 9454 * auto-unconfiguration when destroying the
9449 9455 * target map(s).
9450 9456 */
9451 9457 (void) scsi_hba_tgtmap_set_begin(tran->tran_tgtmap);
9452 9458 (void) scsi_hba_tgtmap_set_end(tran->tran_tgtmap, 0);
9453 9459
9454 9460 /* wait for unconfigure */
9455 9461 (void) scsi_tgtmap_sync(tran->tran_tgtmap, 0);
9456 9462 empty = scsi_tgtmap_is_empty(tran->tran_tgtmap);
9457 9463
9458 9464 scsi_hba_devi_enter(self, &circ);
9459 9465 ndi_rele_devi(childp);
9460 9466
9461 9467 /* If begin/end/sync ends in empty map, offline/remove. */
9462 9468 if (empty) {
9463 9469 if (ndi_devi_offline(childp,
9464 9470 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE) == DDI_SUCCESS) {
9465 9471 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
9466 9472 "devinfo iport@%s offlined and removed",
9467 9473 addr));
9468 9474 } else if (ndi_devi_device_remove(childp)) {
9469 9475 /* Offline/rem failed, note new device_remove */
9470 9476 SCSI_HBA_LOG((_LOGUNCFG, self, NULL,
9471 9477 "devinfo iport@%s offline failed, "
9472 9478 "device_remove", addr));
9473 9479 }
9474 9480 }
9475 9481 scsi_hba_devi_exit(self, circ);
9476 9482 return (empty ? DAM_SUCCESS : DAM_FAILURE);
9477 9483 }
9478 9484
9479 9485
9480 9486 int
9481 9487 scsi_hba_iportmap_create(dev_info_t *self, int csync_usec, int settle_usec,
9482 9488 scsi_hba_iportmap_t **handle)
9483 9489 {
9484 9490 scsi_hba_tran_t *tran;
9485 9491 damap_t *mapp;
9486 9492 char context[64];
9487 9493 impl_scsi_iportmap_t *iportmap;
9488 9494
9489 9495 if (self == NULL || csync_usec == 0 ||
9490 9496 settle_usec == 0 || handle == NULL)
9491 9497 return (DDI_FAILURE);
9492 9498
9493 9499 *handle = NULL;
9494 9500
9495 9501 if (scsi_hba_iport_unit_address(self) != NULL)
9496 9502 return (DDI_FAILURE);
9497 9503
9498 9504 tran = (scsi_hba_tran_t *)ddi_get_driver_private(self);
9499 9505 ASSERT(tran);
9500 9506 if (tran == NULL)
9501 9507 return (DDI_FAILURE);
9502 9508
9503 9509 (void) snprintf(context, sizeof (context), "%s%d.iportmap",
9504 9510 ddi_driver_name(self), ddi_get_instance(self));
9505 9511
9506 9512 if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG,
9507 9513 settle_usec, NULL, NULL, NULL, self,
9508 9514 scsi_iportmap_config, scsi_iportmap_unconfig, &mapp) !=
9509 9515 DAM_SUCCESS) {
9510 9516 return (DDI_FAILURE);
9511 9517 }
9512 9518 iportmap = kmem_zalloc(sizeof (*iportmap), KM_SLEEP);
9513 9519 iportmap->iportmap_hba_dip = self;
9514 9520 iportmap->iportmap_dam = mapp;
9515 9521
9516 9522 iportmap->iportmap_create_window = 1; /* start with window */
9517 9523 iportmap->iportmap_create_time = ddi_get_lbolt64();
9518 9524 iportmap->iportmap_create_csync_usec = csync_usec;
9519 9525 iportmap->iportmap_settle_usec = settle_usec;
9520 9526 iportmap->iportmap_sync_cnt = 0;
9521 9527
9522 9528 tran->tran_iportmap = (scsi_hba_iportmap_t *)iportmap;
9523 9529 *handle = (scsi_hba_iportmap_t *)iportmap;
9524 9530
9525 9531 SCSI_HBA_LOG((_LOGIPT, self, NULL, "%s", damap_name(mapp)));
9526 9532 return (DDI_SUCCESS);
9527 9533 }
9528 9534
9529 9535 void
9530 9536 scsi_hba_iportmap_destroy(scsi_hba_iportmap_t *handle)
9531 9537 {
9532 9538 impl_scsi_iportmap_t *iportmap = (impl_scsi_iportmap_t *)handle;
9533 9539 dev_info_t *self = iportmap->iportmap_hba_dip;
9534 9540
9535 9541 SCSI_HBA_LOG((_LOGIPT, self, NULL,
9536 9542 "%s", damap_name(iportmap->iportmap_dam)));
9537 9543
9538 9544 damap_destroy(iportmap->iportmap_dam);
9539 9545 kmem_free(iportmap, sizeof (*iportmap));
9540 9546 }
9541 9547
9542 9548 int
9543 9549 scsi_hba_iportmap_iport_add(scsi_hba_iportmap_t *handle,
9544 9550 char *iport_addr, void *iport_priv)
9545 9551 {
9546 9552 impl_scsi_iportmap_t *iportmap = (impl_scsi_iportmap_t *)handle;
9547 9553 dev_info_t *self = iportmap->iportmap_hba_dip;
9548 9554
9549 9555 SCSI_HBA_LOG((_LOGIPT, self, NULL,
9550 9556 "%s @%s", damap_name(iportmap->iportmap_dam), iport_addr));
9551 9557
9552 9558 return ((damap_addr_add(iportmap->iportmap_dam, iport_addr, NULL,
9553 9559 NULL, iport_priv) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
9554 9560 }
9555 9561
9556 9562 int
9557 9563 scsi_hba_iportmap_iport_remove(scsi_hba_iportmap_t *handle,
9558 9564 char *iport_addr)
9559 9565 {
9560 9566 impl_scsi_iportmap_t *iportmap = (impl_scsi_iportmap_t *)handle;
9561 9567 dev_info_t *self = iportmap->iportmap_hba_dip;
9562 9568
9563 9569 SCSI_HBA_LOG((_LOGIPT, self, NULL,
9564 9570 "%s @%s", damap_name(iportmap->iportmap_dam), iport_addr));
9565 9571
9566 9572 return ((damap_addr_del(iportmap->iportmap_dam,
9567 9573 iport_addr) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
9568 9574 }
9569 9575
9570 9576 int
9571 9577 scsi_hba_iportmap_lookup(scsi_hba_iportmap_t *handle,
9572 9578 char *iport_addr)
9573 9579 {
9574 9580 impl_scsi_iportmap_t *iportmap = (impl_scsi_iportmap_t *)handle;
9575 9581 dev_info_t *self = iportmap->iportmap_hba_dip;
9576 9582 damap_id_t iportid;
9577 9583
9578 9584 iportid = damap_lookup(iportmap->iportmap_dam, iport_addr);
9579 9585 if (iportid != NODAM) {
9580 9586 SCSI_HBA_LOG((_LOG(3), self, NULL,
9581 9587 "%s @%s found",
9582 9588 damap_name(iportmap->iportmap_dam), iport_addr));
9583 9589 damap_id_rele(iportmap->iportmap_dam, iportid);
9584 9590 return (DDI_SUCCESS);
9585 9591 }
9586 9592
9587 9593 SCSI_HBA_LOG((_LOG(3), self, NULL,
9588 9594 "%s @%s not found",
9589 9595 damap_name(iportmap->iportmap_dam), iport_addr));
9590 9596 return (DDI_FAILURE);
9591 9597 }
9592 9598
9593 9599
9594 9600 static int
9595 9601 scsi_lunmap_config(void *arg, damap_t *lundam, damap_id_t lunid)
9596 9602 {
9597 9603 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)arg;
9598 9604 scsi_hba_tran_t *tran = tgtmap->tgtmap_tran;
9599 9605 dev_info_t *self = tran->tran_iport_dip;
9600 9606 char *addr;
9601 9607
9602 9608 addr = damap_id2addr(lundam, lunid);
9603 9609 SCSI_HBA_LOG((_LOGLUN, self, NULL,
9604 9610 "%s @%s", damap_name(lundam), addr));
9605 9611 if (scsi_hba_bus_configone_addr(self, addr, SE_HP) != NULL)
9606 9612 return (DAM_SUCCESS);
9607 9613 else
9608 9614 return (DAM_FAILURE);
9609 9615 }
9610 9616
9611 9617 static int
9612 9618 scsi_lunmap_unconfig(void *arg, damap_t *lundam, damap_id_t lunid)
9613 9619 {
9614 9620 impl_scsi_tgtmap_t *tgtmap = (impl_scsi_tgtmap_t *)arg;
9615 9621 scsi_hba_tran_t *tran = tgtmap->tgtmap_tran;
9616 9622 dev_info_t *self = tran->tran_iport_dip;
9617 9623 char *addr;
9618 9624
9619 9625 addr = damap_id2addr(lundam, lunid);
9620 9626 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s @%s", damap_name(lundam),
9621 9627 addr));
9622 9628
9623 9629 scsi_hba_bus_unconfigone_addr(self, addr);
9624 9630 return (DAM_SUCCESS);
9625 9631 }
9626 9632
9627 9633 static int
9628 9634 scsi_lunmap_create(dev_info_t *self, impl_scsi_tgtmap_t *tgtmap, char *taddr)
9629 9635 {
9630 9636 char context[64];
9631 9637 damap_t *tgtdam;
9632 9638 damap_id_t tgtid;
9633 9639 damap_t *lundam;
9634 9640 int optflags;
9635 9641
9636 9642 (void) snprintf(context, sizeof (context), "%s%d.%s.lunmap",
9637 9643 ddi_driver_name(self), ddi_get_instance(self), taddr);
9638 9644
9639 9645 tgtdam = tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE];
9640 9646 tgtid = damap_lookup(tgtdam, taddr);
9641 9647 if (tgtid == NODAM) {
9642 9648 SCSI_HBA_LOG((_LOG(1), self, NULL,
9643 9649 "target %s not found", context));
9644 9650 return (DDI_FAILURE);
9645 9651 }
9646 9652
9647 9653 lundam = damap_id_priv_get(tgtdam, tgtid);
9648 9654 if (lundam) {
9649 9655 SCSI_HBA_LOG((_LOG(1), self, NULL,
9650 9656 "lunmap %s already created", context));
9651 9657 damap_id_rele(tgtdam, tgtid);
9652 9658 return (DDI_FAILURE);
9653 9659 }
9654 9660
9655 9661 optflags = (ddi_prop_get_int(DDI_DEV_T_ANY, self,
9656 9662 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-enumeration",
9657 9663 scsi_enumeration) & SCSI_ENUMERATION_MT_LUN_DISABLE) ?
9658 9664 DAMAP_SERIALCONFIG : DAMAP_MTCONFIG;
9659 9665
9660 9666 /* NOTE: expected ref at tgtid/taddr: 2: caller + lookup. */
9661 9667 ASSERT(damap_id_ref(tgtdam, tgtid) == 2);
9662 9668 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s creat, id %d ref %d",
9663 9669 context, tgtid, damap_id_ref(tgtdam, tgtid)));
9664 9670
9665 9671 /* create lundam */
9666 9672 if (damap_create(context, DAMAP_REPORT_FULLSET, optflags, 1,
9667 9673 NULL, NULL, NULL, tgtmap, scsi_lunmap_config, scsi_lunmap_unconfig,
9668 9674 &lundam) != DAM_SUCCESS) {
9669 9675 SCSI_HBA_LOG((_LOG(1), self, NULL,
9670 9676 "%s create failed, id %d ref %d",
9671 9677 context, tgtid, damap_id_ref(tgtdam, tgtid)));
9672 9678 damap_id_rele(tgtdam, tgtid);
9673 9679 return (DDI_FAILURE);
9674 9680 }
9675 9681
9676 9682 /*
9677 9683 * Return with damap_id_hold at tgtid/taddr from damap_lookup to
9678 9684 * account for damap_id_prv_set below.
9679 9685 */
9680 9686 damap_id_priv_set(tgtdam, tgtid, lundam);
9681 9687 return (DDI_SUCCESS);
9682 9688 }
9683 9689
9684 9690 static void
9685 9691 scsi_lunmap_destroy(dev_info_t *self, impl_scsi_tgtmap_t *tgtmap, char *taddr)
9686 9692 {
9687 9693 char context[64];
9688 9694 damap_t *tgtdam;
9689 9695 damap_id_t tgtid;
9690 9696 damap_t *lundam;
9691 9697
9692 9698 (void) snprintf(context, sizeof (context), "%s%d.%s.lunmap",
9693 9699 ddi_driver_name(self), ddi_get_instance(self), taddr);
9694 9700
9695 9701 tgtdam = tgtmap->tgtmap_dam[SCSI_TGT_SCSI_DEVICE];
9696 9702 tgtid = damap_lookup(tgtdam, taddr);
9697 9703 if (tgtid == NODAM) {
9698 9704 SCSI_HBA_LOG((_LOG(1), self, NULL,
9699 9705 "target %s not found", context));
9700 9706 return;
9701 9707 }
9702 9708
9703 9709 lundam = (damap_t *)damap_id_priv_get(tgtdam, tgtid);
9704 9710 if (lundam == NULL) {
9705 9711 damap_id_rele(tgtdam, tgtid); /* from damap_lookup */
9706 9712 SCSI_HBA_LOG((_LOG(1), self, NULL,
9707 9713 "lunmap %s already destroyed", context));
9708 9714 return;
9709 9715 }
9710 9716
9711 9717 /* NOTE: expected ref at tgtid/taddr: 3: priv_set + caller + lookup. */
9712 9718 ASSERT(damap_id_ref(tgtdam, tgtid) == 3);
9713 9719 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s, id %d ref %d",
9714 9720 damap_name(lundam), tgtid, damap_id_ref(tgtdam, tgtid)));
9715 9721
9716 9722 /*
9717 9723 * A begin/end (clear) against a target's lunmap will trigger
9718 9724 * unconfigure of all LUNs on the target.
9719 9725 */
9720 9726 scsi_lunmap_set_begin(self, lundam);
9721 9727 scsi_lunmap_set_end(self, lundam);
9722 9728
9723 9729 SCSI_HBA_LOG((_LOGLUN, self, NULL,
9724 9730 "%s sync begin", damap_name(lundam)));
9725 9731
9726 9732 (void) damap_sync(lundam, 0); /* wait for unconfigure */
9727 9733
9728 9734 SCSI_HBA_LOG((_LOGLUN, self, NULL,
9729 9735 "%s sync end", damap_name(lundam)));
9730 9736
9731 9737 damap_id_priv_set(tgtdam, tgtid, NULL);
9732 9738
9733 9739 /* release hold established by damap_lookup above */
9734 9740 damap_id_rele(tgtdam, tgtid);
9735 9741
9736 9742 /* release hold established since scsi_lunmap_create() */
9737 9743 damap_id_rele(tgtdam, tgtid);
9738 9744
9739 9745 damap_destroy(lundam);
9740 9746 }
9741 9747
9742 9748 static void
9743 9749 scsi_lunmap_set_begin(dev_info_t *self, damap_t *lundam)
9744 9750 {
9745 9751 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s", damap_name(lundam)));
9746 9752
9747 9753 (void) damap_addrset_begin(lundam);
9748 9754 }
9749 9755
9750 9756 static int
9751 9757 scsi_lunmap_set_add(dev_info_t *self, damap_t *lundam,
9752 9758 char *taddr, scsi_lun64_t lun64, int sfunc)
9753 9759 {
9754 9760 char ua[SCSI_MAXNAMELEN];
9755 9761
9756 9762 /* make unit address string form of "@taddr,lun[,sfunc]" */
9757 9763 if (sfunc == -1)
9758 9764 (void) snprintf(ua, sizeof (ua), "%s,%" PRIx64, taddr, lun64);
9759 9765 else
9760 9766 (void) snprintf(ua, sizeof (ua), "%s,%" PRIx64 ",%x",
9761 9767 taddr, lun64, sfunc);
9762 9768
9763 9769 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s @%s", damap_name(lundam), ua));
9764 9770
9765 9771 return ((damap_addrset_add(lundam, ua, NULL, NULL,
9766 9772 NULL) == DAM_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
9767 9773 }
9768 9774
9769 9775 static void
9770 9776 scsi_lunmap_set_end(dev_info_t *self, damap_t *lundam)
9771 9777 {
9772 9778 SCSI_HBA_LOG((_LOGLUN, self, NULL, "%s", damap_name(lundam)));
9773 9779
9774 9780 (void) damap_addrset_end(lundam, 0);
9775 9781 }
9776 9782
9777 9783 int
9778 9784 scsi_lunmap_lookup(dev_info_t *self, damap_t *lundam, char *addr)
9779 9785 {
9780 9786 damap_id_t lunid;
9781 9787
9782 9788 if ((lunid = damap_lookup(lundam, addr)) != NODAM) {
9783 9789 SCSI_HBA_LOG((_LOG(3), self, NULL,
9784 9790 "%s @%s found", damap_name(lundam), addr));
9785 9791 damap_id_rele(lundam, lunid);
9786 9792 return (DDI_SUCCESS);
9787 9793 }
9788 9794
9789 9795 SCSI_HBA_LOG((_LOG(3), self, NULL,
9790 9796 "%s @%s not found", damap_name(lundam), addr));
9791 9797 return (DDI_FAILURE);
9792 9798 }
9793 9799
9794 9800 /*
9795 9801 * phymap implementation
9796 9802 *
9797 9803 * We manage the timed aggregation of phys into a phy map * by creating a
9798 9804 * SAS port construct (based upon 'name' of "local,remote" SAS addresses)
9799 9805 * upon the first link up. As time goes on additional phys may join that port.
9800 9806 * After an appropriate amount of settle time, we trigger the activation
9801 9807 * callback which will then take the resultant bit mask of phys (phymask) in
9802 9808 * the SAS port and use that to call back to the callback function
9803 9809 * provided by the additional caller.
9804 9810 *
9805 9811 * We cross check to make sure that phys only exist in one SAS port at a
9806 9812 * time by having soft state for each phy point back to the created
9807 9813 * SAS port.
9808 9814 *
9809 9815 * NOTE: Make SAS_PHY_UA_LEN max(SAS_PHY_PHYMASK_LEN, SAS_PHY_NAME_LEN)
9810 9816 * so we have enough space if sas_phymap_bitset2phymaskua phymask address
9811 9817 * is already in use, and we end up using port name as unit address.
9812 9818 */
9813 9819 #define SAS_PHY_NAME_FMT "%" PRIx64 ",%" PRIx64
9814 9820 #define SAS_PHY_NAME_LEN (16 + 1 + 16 + 1)
9815 9821 #define SAS_PHY_NPHY (SAS2_PHYNUM_MAX + 1)
9816 9822 #define SAS_PHY_PHYMASK_LEN ((roundup(SAS_PHY_NPHY, 4)) / 4)
9817 9823 #if (SAS_PHY_PHYMASK_LEN > SAS_PHY_NAME_LEN)
9818 9824 #define SAS_PHY_UA_LEN SAS_PHY_PHYMASK_LEN
9819 9825 #else
9820 9826 #define SAS_PHY_UA_LEN SAS_PHY_NAME_LEN
9821 9827 #endif
9822 9828 typedef struct impl_sas_physet { /* needed for name2phys destroy */
9823 9829 struct impl_sas_physet *physet_next;
9824 9830 char *physet_name;
9825 9831 bitset_t *physet_phys;
9826 9832 } impl_sas_physet_t;
9827 9833 typedef struct impl_sas_phymap {
9828 9834 dev_info_t *phymap_self;
9829 9835
9830 9836 kmutex_t phymap_lock;
9831 9837 damap_t *phymap_dam;
9832 9838 void *phymap_phy2name;
9833 9839 ddi_soft_state_bystr *phymap_name2phys; /* bitset */
9834 9840 ddi_soft_state_bystr *phymap_name2ua;
9835 9841 ddi_soft_state_bystr *phymap_ua2name;
9836 9842
9837 9843 /* Noisy phy information - ensure forward progress for noisy phys */
9838 9844 int phymap_phy_max; /* max phy# */
9839 9845 int phymap_reports; /* per period */
9840 9846 int phymap_reports_max; /* scales */
9841 9847 int phymap_phys_noisy; /* detected */
9842 9848
9843 9849 /* These are for callbacks to the consumer. */
9844 9850 sas_phymap_activate_cb_t phymap_acp;
9845 9851 sas_phymap_deactivate_cb_t phymap_dcp;
9846 9852 void *phymap_private;
9847 9853
9848 9854 struct impl_sas_physet *phymap_physets;
9849 9855 } impl_sas_phymap_t;
9850 9856
9851 9857 /* Detect noisy phy: max changes per stabilization period per phy. */
9852 9858 static int sas_phymap_phy_max_factor = 16;
9853 9859
9854 9860 /*
9855 9861 * Convert bitset into a unit-address string. The maximum string length would
9856 9862 * be the maximum number of phys, rounded up by 4 and divided by 4.
9857 9863 */
9858 9864 static void
9859 9865 sas_phymap_bitset2phymaskua(bitset_t *phys, char *buf)
9860 9866 {
9861 9867 char *ptr;
9862 9868 int grp;
9863 9869 int cur;
9864 9870 uint_t bit;
9865 9871
9866 9872 bit = roundup(SAS_PHY_NPHY, 4);
9867 9873 grp = 4;
9868 9874 ptr = buf;
9869 9875 cur = 0;
9870 9876 do {
9871 9877 bit -= 1;
9872 9878 grp -= 1;
9873 9879 if (bitset_in_set(phys, bit)) {
9874 9880 cur |= (1 << grp);
9875 9881 }
9876 9882 if (grp == 0) {
9877 9883 grp = 4;
9878 9884 if (cur || ptr != buf) {
9879 9885 *ptr++ = "0123456789abcdef"[cur];
9880 9886 *ptr = 0;
9881 9887 }
9882 9888 cur = 0;
9883 9889 }
9884 9890 } while (bit != 0);
9885 9891 if (ptr == buf) {
9886 9892 *ptr++ = '0';
9887 9893 *ptr = 0;
9888 9894 }
9889 9895 }
9890 9896
9891 9897 static int
9892 9898 sas_phymap_config(void *arg, damap_t *phydam, damap_id_t phyid)
9893 9899 {
9894 9900 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)arg;
9895 9901 char *context = damap_name(phymap->phymap_dam);
9896 9902 char *damn;
9897 9903 char *name;
9898 9904 bitset_t *phys;
9899 9905 char *ua;
9900 9906 void *ua_priv;
9901 9907
9902 9908 ASSERT(context);
9903 9909
9904 9910 mutex_enter(&phymap->phymap_lock);
9905 9911 phymap->phymap_reports = phymap->phymap_phys_noisy = 0;
9906 9912
9907 9913 /* Get the name ("local,remote" address string) from damap. */
9908 9914 damn = damap_id2addr(phydam, phyid);
9909 9915
9910 9916 /* Get the bitset of phys currently forming the port. */
9911 9917 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, damn);
9912 9918 if (phys == NULL) {
9913 9919 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: no phys",
9914 9920 context, damn));
9915 9921 mutex_exit(&phymap->phymap_lock);
9916 9922 return (DAM_FAILURE);
9917 9923 }
9918 9924
9919 9925 /* allocate, get, and initialize name index of name2ua map */
9920 9926 if (ddi_soft_state_bystr_zalloc(phymap->phymap_name2ua, damn) !=
9921 9927 DDI_SUCCESS) {
9922 9928 SCSI_HBA_LOG((_LOG_NF(WARN),
9923 9929 "%s: %s: failed name2ua alloc", context, damn));
9924 9930 mutex_exit(&phymap->phymap_lock);
9925 9931 return (DAM_FAILURE);
9926 9932 }
9927 9933 if (!(ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn))) {
9928 9934 SCSI_HBA_LOG((_LOG_NF(WARN),
9929 9935 "%s: %s: no name2ua", context, damn));
9930 9936 mutex_exit(&phymap->phymap_lock);
9931 9937 return (DAM_FAILURE);
9932 9938 }
9933 9939 sas_phymap_bitset2phymaskua(phys, ua); /* set ua */
9934 9940
9935 9941 /* see if phymask ua index already allocated in ua2name map */
9936 9942 if (name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua)) {
9937 9943 /*
9938 9944 * The 'phymask' sas_phymap_bitset2phymaskua ua is
9939 9945 * already in use. This means that original phys have
9940 9946 * formed into a new port, and that the original port
9941 9947 * still exists (it has migrated to some completely
9942 9948 * different set of phys). In this corner-case we use
9943 9949 * "local,remote" name as a 'temporary' unit address.
9944 9950 * Reset ua in name2ua map.
9945 9951 */
9946 9952 (void) strlcpy(ua, damn, SAS_PHY_NAME_LEN);
9947 9953 name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua);
9948 9954 if (name) {
9949 9955 /* The "local,remote" ua should be new... */
9950 9956 SCSI_HBA_LOG((_LOG_NF(WARN),
9951 9957 "%s: %s ua already configured",
9952 9958 context, ua));
9953 9959 mutex_exit(&phymap->phymap_lock);
9954 9960 return (DAM_SUCCESS);
9955 9961 }
9956 9962 }
9957 9963
9958 9964 /* allocate, get, and init ua index of ua2name map */
9959 9965 if (ddi_soft_state_bystr_zalloc(phymap->phymap_ua2name, ua) !=
9960 9966 DDI_SUCCESS) {
9961 9967 ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn);
9962 9968 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: failed ua2name alloc",
9963 9969 context, damn));
9964 9970 mutex_exit(&phymap->phymap_lock);
9965 9971 return (DAM_FAILURE);
9966 9972 }
9967 9973 name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua);
9968 9974 if (name == NULL) {
9969 9975 ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn);
9970 9976 SCSI_HBA_LOG((_LOG_NF(WARN),
9971 9977 "%s: %s: no ua2name", context, ua));
9972 9978 mutex_exit(&phymap->phymap_lock);
9973 9979 return (DAM_FAILURE);
9974 9980 }
9975 9981
9976 9982 /* set name in ua2name map */
9977 9983 (void) strlcpy(name, damn, SAS_PHY_NAME_LEN);
9978 9984
9979 9985 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
9980 9986 "%s: %s: ua %s: activate", context, damn, ua));
9981 9987
9982 9988 if (phymap->phymap_acp) {
9983 9989 /*
9984 9990 * drop our lock and invoke the activation callback
9985 9991 */
9986 9992 mutex_exit(&phymap->phymap_lock);
9987 9993 ua_priv = NULL;
9988 9994 (phymap->phymap_acp)(phymap->phymap_private, ua, &ua_priv);
9989 9995 mutex_enter(&phymap->phymap_lock);
9990 9996 damap_id_priv_set(phydam, phyid, ua_priv);
9991 9997 }
9992 9998 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
9993 9999 "%s: %s: ua %s: activate complete", context, damn, ua));
9994 10000 mutex_exit(&phymap->phymap_lock);
9995 10001 return (DAM_SUCCESS);
9996 10002 }
9997 10003
9998 10004 /*ARGSUSED*/
9999 10005 static int
10000 10006 sas_phymap_unconfig(void *arg, damap_t *phydam, damap_id_t phyid)
10001 10007 {
10002 10008 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)arg;
10003 10009 char *context = damap_name(phymap->phymap_dam);
10004 10010 char *damn;
10005 10011 char *ua;
10006 10012 void *ua_priv;
10007 10013
10008 10014 ASSERT(context);
10009 10015
10010 10016 mutex_enter(&phymap->phymap_lock);
10011 10017 phymap->phymap_reports = phymap->phymap_phys_noisy = 0;
10012 10018
10013 10019 /* Get the name ("local,remote" address string) from damap. */
10014 10020 damn = damap_id2addr(phydam, phyid);
10015 10021
10016 10022 if (!(ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, damn))) {
10017 10023 SCSI_HBA_LOG((_LOG_NF(WARN),
10018 10024 "%s: %s: no name2ua", context, damn));
10019 10025 mutex_exit(&phymap->phymap_lock);
10020 10026 return (DAM_FAILURE);
10021 10027 }
10022 10028
10023 10029 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
10024 10030 "%s: %s: ua %s: deactivate", context, damn, ua));
10025 10031 if (phymap->phymap_dcp) {
10026 10032 ua_priv = damap_id_priv_get(phydam, phyid);
10027 10033 mutex_exit(&phymap->phymap_lock);
10028 10034 (phymap->phymap_dcp)(phymap->phymap_private, ua, ua_priv);
10029 10035 mutex_enter(&phymap->phymap_lock);
10030 10036 }
10031 10037 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
10032 10038 "%s: %s: ua %s: deactivate complete", context, damn, ua));
10033 10039
10034 10040 /* delete ua<->name mappings */
10035 10041 ddi_soft_state_bystr_free(phymap->phymap_ua2name, ua);
10036 10042 ddi_soft_state_bystr_free(phymap->phymap_name2ua, damn);
10037 10043 mutex_exit(&phymap->phymap_lock);
10038 10044 return (DAM_SUCCESS);
10039 10045 }
10040 10046
10041 10047 int
10042 10048 sas_phymap_create(dev_info_t *self, int settle_usec,
10043 10049 sas_phymap_mode_t mode, void *mode_argument, void *phymap_priv,
10044 10050 sas_phymap_activate_cb_t activate_cb,
10045 10051 sas_phymap_deactivate_cb_t deactivate_cb,
10046 10052 sas_phymap_t **handlep)
10047 10053 {
10048 10054 _NOTE(ARGUNUSED(mode_argument));
10049 10055 char context[64];
10050 10056 impl_sas_phymap_t *phymap;
10051 10057
10052 10058 if (self == NULL || settle_usec == 0 || handlep == NULL)
10053 10059 return (DDI_FAILURE);
10054 10060
10055 10061 if (mode != PHYMAP_MODE_SIMPLE)
10056 10062 return (DDI_FAILURE);
10057 10063
10058 10064 phymap = kmem_zalloc(sizeof (*phymap), KM_SLEEP);
10059 10065 phymap->phymap_self = self;
10060 10066 phymap->phymap_reports_max = 1 * sas_phymap_phy_max_factor;
10061 10067 phymap->phymap_acp = activate_cb;
10062 10068 phymap->phymap_dcp = deactivate_cb;
10063 10069 phymap->phymap_private = phymap_priv;
10064 10070 mutex_init(&phymap->phymap_lock, NULL, MUTEX_DRIVER, NULL);
10065 10071
10066 10072 (void) snprintf(context, sizeof (context), "%s%d.phymap",
10067 10073 ddi_driver_name(self), ddi_get_instance(self));
10068 10074 SCSI_HBA_LOG((_LOGPHY, self, NULL, "%s", context));
10069 10075
10070 10076 if (ddi_soft_state_init(&phymap->phymap_phy2name,
10071 10077 SAS_PHY_NAME_LEN, SAS_PHY_NPHY) != 0)
10072 10078 goto fail;
10073 10079 if (ddi_soft_state_bystr_init(&phymap->phymap_name2phys,
10074 10080 sizeof (bitset_t), SAS_PHY_NPHY) != 0)
10075 10081 goto fail;
10076 10082
10077 10083 if (ddi_soft_state_bystr_init(&phymap->phymap_name2ua,
10078 10084 SAS_PHY_UA_LEN, SAS_PHY_NPHY) != 0)
10079 10085 goto fail;
10080 10086 if (ddi_soft_state_bystr_init(&phymap->phymap_ua2name,
10081 10087 SAS_PHY_NAME_LEN, SAS_PHY_NPHY) != 0)
10082 10088 goto fail;
10083 10089
10084 10090 if (damap_create(context, DAMAP_REPORT_PERADDR, DAMAP_SERIALCONFIG,
10085 10091 settle_usec, NULL, NULL, NULL,
10086 10092 phymap, sas_phymap_config, sas_phymap_unconfig,
10087 10093 &phymap->phymap_dam) != DAM_SUCCESS)
10088 10094 goto fail;
10089 10095
10090 10096
10091 10097 *handlep = (sas_phymap_t *)phymap;
10092 10098 return (DDI_SUCCESS);
10093 10099
10094 10100 fail: sas_phymap_destroy((sas_phymap_t *)phymap);
10095 10101 *handlep = NULL;
10096 10102 return (DDI_FAILURE);
10097 10103 }
10098 10104
10099 10105 void
10100 10106 sas_phymap_destroy(sas_phymap_t *handle)
10101 10107 {
10102 10108 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10103 10109 char *context;
10104 10110 struct impl_sas_physet *physet, *nphyset;
10105 10111 bitset_t *phys;
10106 10112 char *name;
10107 10113
10108 10114 context = phymap->phymap_dam ?
10109 10115 damap_name(phymap->phymap_dam) : "unknown";
10110 10116 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, "%s", context));
10111 10117
10112 10118 if (phymap->phymap_dam)
10113 10119 damap_destroy(phymap->phymap_dam);
10114 10120
10115 10121 /* free the bitsets of allocated physets */
10116 10122 for (physet = phymap->phymap_physets; physet; physet = nphyset) {
10117 10123 nphyset = physet->physet_next;
10118 10124 phys = physet->physet_phys;
10119 10125 name = physet->physet_name;
10120 10126
10121 10127 if (phys)
10122 10128 bitset_fini(phys);
10123 10129 if (name) {
10124 10130 ddi_soft_state_bystr_free(
10125 10131 phymap->phymap_name2phys, name);
10126 10132 strfree(name);
10127 10133 }
10128 10134 kmem_free(physet, sizeof (*physet));
10129 10135 }
10130 10136
10131 10137 /* free the maps */
10132 10138 if (phymap->phymap_ua2name)
10133 10139 ddi_soft_state_bystr_fini(&phymap->phymap_ua2name);
10134 10140 if (phymap->phymap_name2ua)
10135 10141 ddi_soft_state_bystr_fini(&phymap->phymap_name2ua);
10136 10142
10137 10143 if (phymap->phymap_name2phys)
10138 10144 ddi_soft_state_bystr_fini(&phymap->phymap_name2phys);
10139 10145 if (phymap->phymap_phy2name)
10140 10146 ddi_soft_state_fini(&phymap->phymap_phy2name);
10141 10147
10142 10148 mutex_destroy(&phymap->phymap_lock);
10143 10149 kmem_free(phymap, sizeof (*phymap));
10144 10150 }
10145 10151
10146 10152
10147 10153 int
10148 10154 sas_phymap_phy_add(sas_phymap_t *handle,
10149 10155 int phy, uint64_t local, uint64_t remote)
10150 10156 {
10151 10157 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10152 10158 char *context = damap_name(phymap->phymap_dam);
10153 10159 char port[SAS_PHY_NAME_LEN];
10154 10160 char *name;
10155 10161 int phy2name_allocated = 0;
10156 10162 bitset_t *phys;
10157 10163 struct impl_sas_physet *physet;
10158 10164 int rv;
10159 10165
10160 10166 /* Create the SAS port name from the local and remote addresses. */
10161 10167 (void) snprintf(port, SAS_PHY_NAME_LEN, SAS_PHY_NAME_FMT,
10162 10168 local, remote);
10163 10169
10164 10170 mutex_enter(&phymap->phymap_lock);
10165 10171 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, "%s: %s: add phy %d",
10166 10172 context, port, phy));
10167 10173
10168 10174 /* Check for conflict in phy2name map */
10169 10175 name = ddi_get_soft_state(phymap->phymap_phy2name, phy);
10170 10176 if (name) {
10171 10177 if (strcmp(name, port) != 0)
10172 10178 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: add phy %d: "
10173 10179 "already in %s", context, port, phy, name));
10174 10180 else
10175 10181 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: add phy %d: "
10176 10182 "duplicate add", context, port, phy));
10177 10183 mutex_exit(&phymap->phymap_lock);
10178 10184 return (DDI_FAILURE);
10179 10185 }
10180 10186
10181 10187 /* allocate, get, and initialize phy index of phy2name map */
10182 10188 if (ddi_soft_state_zalloc(
10183 10189 phymap->phymap_phy2name, phy) != DDI_SUCCESS) {
10184 10190 SCSI_HBA_LOG((_LOG_NF(WARN),
10185 10191 "%s: %s: failed phy2name alloc", context, port));
10186 10192 goto fail;
10187 10193 }
10188 10194 name = ddi_get_soft_state(phymap->phymap_phy2name, phy);
10189 10195 if (name == NULL) {
10190 10196 SCSI_HBA_LOG((_LOG_NF(WARN),
10191 10197 "%s: %s: no phy2name", context, port));
10192 10198 goto fail;
10193 10199 }
10194 10200 phy2name_allocated = 1;
10195 10201 (void) strlcpy(name, port, SAS_PHY_NAME_LEN); /* set name */
10196 10202
10197 10203 /* Find/alloc, initialize name index of name2phys map */
10198 10204 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, name);
10199 10205 if (phys == NULL) {
10200 10206 if (ddi_soft_state_bystr_zalloc(phymap->phymap_name2phys,
10201 10207 name) != DDI_SUCCESS) {
10202 10208 SCSI_HBA_LOG((_LOG_NF(WARN),
10203 10209 "%s: %s: failed name2phys alloc", context, name));
10204 10210 goto fail;
10205 10211 }
10206 10212 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, name);
10207 10213 if (phys == NULL) {
10208 10214 SCSI_HBA_LOG((_LOG_NF(WARN),
10209 10215 "%s: %s: no name2phys", context, name));
10210 10216 goto fail;
10211 10217 }
10212 10218
10213 10219 /* Initialize bitset of phys. */
10214 10220 bitset_init(phys);
10215 10221 bitset_resize(phys, SAS_PHY_NPHY);
10216 10222
10217 10223 /* Keep a list of information for destroy. */
10218 10224 physet = kmem_zalloc(sizeof (*physet), KM_SLEEP);
10219 10225 physet->physet_name = strdup(name);
10220 10226 physet->physet_phys = phys;
10221 10227 physet->physet_next = phymap->phymap_physets;
10222 10228 phymap->phymap_physets = physet;
10223 10229 }
10224 10230 ASSERT(phys);
10225 10231
10226 10232 /* Reflect 'add' in phys bitset. */
10227 10233 if (bitset_atomic_test_and_add(phys, phy) < 0) {
10228 10234 /* It is an error if the phy was already recorded. */
10229 10235 SCSI_HBA_LOG((_LOG_NF(WARN),
10230 10236 "%s: %s: phy bit %d already in port", context, name, phy));
10231 10237 goto fail;
10232 10238 }
10233 10239
10234 10240 /*
10235 10241 * Check to see if we have a new phy_max for this map, and if so
10236 10242 * scale phymap_reports_max to the new number of phys.
10237 10243 */
10238 10244 if (phy > phymap->phymap_phy_max) {
10239 10245 phymap->phymap_phy_max = phy + 1;
10240 10246 phymap->phymap_reports_max = phymap->phymap_phy_max *
10241 10247 sas_phymap_phy_max_factor;
10242 10248 }
10243 10249
10244 10250 /*
10245 10251 * If we have not reached phymap_reports_max, start/restart the
10246 10252 * activate timer. Otherwise, if phymap->phymap_reports add/rem reports
10247 10253 * ever exceeds phymap_reports_max due to noisy phys, then report the
10248 10254 * noise and force stabilization by stopping reports into the damap.
10249 10255 *
10250 10256 * The first config/unconfig callout out of the damap will reset
10251 10257 * phymap->phymap_reports.
10252 10258 */
10253 10259 rv = DDI_SUCCESS;
10254 10260 if (phymap->phymap_reports++ < phymap->phymap_reports_max) {
10255 10261 if (damap_addr_add(phymap->phymap_dam, name,
10256 10262 NULL, NULL, NULL) == DAM_SUCCESS) {
10257 10263 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
10258 10264 "%s: %s: damap_addr_add", context, name));
10259 10265 } else {
10260 10266 SCSI_HBA_LOG((_LOG_NF(WARN),
10261 10267 "%s: %s: damap_addr_add failed", context, name));
10262 10268 rv = DDI_FAILURE;
10263 10269 }
10264 10270 } else {
10265 10271 phymap->phymap_phys_noisy++;
10266 10272 if (phymap->phymap_phys_noisy == 1)
10267 10273 SCSI_HBA_LOG((_LOG_NF(WARN),
10268 10274 "%s: %s: noisy phys", context, name));
10269 10275 }
10270 10276 mutex_exit(&phymap->phymap_lock);
10271 10277 return (rv);
10272 10278
10273 10279 fail: if (phy2name_allocated)
10274 10280 ddi_soft_state_free(phymap->phymap_phy2name, phy);
10275 10281 mutex_exit(&phymap->phymap_lock);
10276 10282 return (DDI_FAILURE);
10277 10283 }
10278 10284
10279 10285 int
10280 10286 sas_phymap_phy_rem(sas_phymap_t *handle, int phy)
10281 10287 {
10282 10288 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10283 10289 char *context = damap_name(phymap->phymap_dam);
10284 10290 char *name;
10285 10291 bitset_t *phys;
10286 10292 int rv = DDI_FAILURE;
10287 10293
10288 10294 ASSERT(context);
10289 10295
10290 10296 mutex_enter(&phymap->phymap_lock);
10291 10297 phymap->phymap_reports++;
10292 10298
10293 10299 /* Find and free phy index of phy2name map */
10294 10300 name = ddi_get_soft_state(phymap->phymap_phy2name, phy);
10295 10301 if (name == NULL) {
10296 10302 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: rem phy %d: never added",
10297 10303 context, phy));
10298 10304 goto fail;
10299 10305 }
10300 10306 /* NOTE: always free phy index of phy2name map before return... */
10301 10307
10302 10308 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL, "%s: %s: rem phy %d",
10303 10309 context, name, phy));
10304 10310
10305 10311 /* Get bitset of phys currently associated with named port. */
10306 10312 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, name);
10307 10313 if (phys == NULL) {
10308 10314 SCSI_HBA_LOG((_LOG_NF(WARN), "%s: %s: name2phys failed",
10309 10315 context, name));
10310 10316 goto fail;
10311 10317 }
10312 10318
10313 10319 /* Reflect 'rem' in phys bitset. */
10314 10320 if (bitset_atomic_test_and_del(phys, phy) < 0) {
10315 10321 /* It is an error if the phy wasn't one of the port's phys. */
10316 10322 SCSI_HBA_LOG((_LOG_NF(WARN),
10317 10323 "%s: %s: phy bit %d not in port", context, name, phy));
10318 10324 goto fail;
10319 10325 }
10320 10326
10321 10327 /* If this was the last phy in the port, start the deactivate timer. */
10322 10328 if (bitset_is_null(phys) &&
10323 10329 (phymap->phymap_reports++ < phymap->phymap_reports_max)) {
10324 10330 if (damap_addr_del(phymap->phymap_dam, name) == DAM_SUCCESS) {
10325 10331 SCSI_HBA_LOG((_LOGPHY, phymap->phymap_self, NULL,
10326 10332 "%s: %s: damap_addr_del", context, name));
10327 10333 } else {
10328 10334 SCSI_HBA_LOG((_LOG_NF(WARN),
10329 10335 "%s: %s: damap_addr_del failure", context, name));
10330 10336 goto fail;
10331 10337 }
10332 10338 }
10333 10339 rv = DDI_SUCCESS;
10334 10340
10335 10341 /* free phy index of phy2name map */
10336 10342 fail: if (name)
10337 10343 ddi_soft_state_free(phymap->phymap_phy2name, phy); /* free */
10338 10344 mutex_exit(&phymap->phymap_lock);
10339 10345 return (rv);
10340 10346 }
10341 10347
10342 10348 char *
10343 10349 sas_phymap_lookup_ua(sas_phymap_t *handle, uint64_t local, uint64_t remote)
10344 10350 {
10345 10351 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10346 10352 char *context = damap_name(phymap->phymap_dam);
10347 10353 char name[SAS_PHY_NAME_LEN];
10348 10354 char *ua;
10349 10355
10350 10356 ASSERT(context);
10351 10357
10352 10358 (void) snprintf(name, SAS_PHY_NAME_LEN, SAS_PHY_NAME_FMT,
10353 10359 local, remote);
10354 10360
10355 10361 mutex_enter(&phymap->phymap_lock);
10356 10362 ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, name);
10357 10363 SCSI_HBA_LOG((_LOG(3), phymap->phymap_self, NULL,
10358 10364 "%s: %s: ua %s", context, name, ua ? ua : "NULL"));
10359 10365 mutex_exit(&phymap->phymap_lock);
10360 10366 return (ua);
10361 10367 }
10362 10368
10363 10369 void *
10364 10370 sas_phymap_lookup_uapriv(sas_phymap_t *handle, char *ua)
10365 10371 {
10366 10372 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10367 10373 char *context = damap_name(phymap->phymap_dam);
10368 10374 char *name;
10369 10375 damap_id_t phyid;
10370 10376 void *ua_priv = NULL;
10371 10377
10372 10378 ASSERT(context);
10373 10379
10374 10380 mutex_enter(&phymap->phymap_lock);
10375 10381 name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua);
10376 10382 if (name) {
10377 10383 phyid = damap_lookup(phymap->phymap_dam, name);
10378 10384 if (phyid != NODAM) {
10379 10385 ua_priv = damap_id_priv_get(phymap->phymap_dam, phyid);
10380 10386 damap_id_rele(phymap->phymap_dam, phyid);
10381 10387 }
10382 10388 }
10383 10389
10384 10390 SCSI_HBA_LOG((_LOG(3), phymap->phymap_self, NULL,
10385 10391 "%s: %s: ua %s ua_priv %p", context, name,
10386 10392 ua ? ua : "NULL", ua_priv));
10387 10393 mutex_exit(&phymap->phymap_lock);
10388 10394 return (ua_priv);
10389 10395 }
10390 10396
10391 10397 int
10392 10398 sas_phymap_uahasphys(sas_phymap_t *handle, char *ua)
10393 10399 {
10394 10400 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10395 10401 char *name;
10396 10402 bitset_t *phys;
10397 10403 int n = 0;
10398 10404
10399 10405 mutex_enter(&phymap->phymap_lock);
10400 10406 name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua);
10401 10407 if (name) {
10402 10408 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, name);
10403 10409 if (phys)
10404 10410 n = bitset_is_null(phys) ? 0 : 1;
10405 10411 }
10406 10412 mutex_exit(&phymap->phymap_lock);
10407 10413 return (n);
10408 10414 }
10409 10415
10410 10416 sas_phymap_phys_t *
10411 10417 sas_phymap_ua2phys(sas_phymap_t *handle, char *ua)
10412 10418 {
10413 10419 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10414 10420 char *name;
10415 10421 bitset_t *phys;
10416 10422 bitset_t *cphys = NULL;
10417 10423
10418 10424 mutex_enter(&phymap->phymap_lock);
10419 10425 name = ddi_soft_state_bystr_get(phymap->phymap_ua2name, ua);
10420 10426 if (name == NULL)
10421 10427 goto fail;
10422 10428
10423 10429 phys = ddi_soft_state_bystr_get(phymap->phymap_name2phys, name);
10424 10430 if (phys == NULL)
10425 10431 goto fail;
10426 10432
10427 10433 /* dup the phys and return */
10428 10434 cphys = kmem_alloc(sizeof (*cphys), KM_SLEEP);
10429 10435 bitset_init(cphys);
10430 10436 bitset_resize(cphys, SAS_PHY_NPHY);
10431 10437 bitset_copy(phys, cphys);
10432 10438
10433 10439 fail: mutex_exit(&phymap->phymap_lock);
10434 10440 return ((sas_phymap_phys_t *)cphys);
10435 10441 }
10436 10442
10437 10443 int
10438 10444 sas_phymap_phys_next(sas_phymap_phys_t *phys)
10439 10445 {
10440 10446 bitset_t *cphys = (bitset_t *)phys;
10441 10447 int phy;
10442 10448
10443 10449 phy = bitset_find(cphys);
10444 10450 if (phy != -1)
10445 10451 bitset_del(cphys, phy);
10446 10452 return (phy);
10447 10453 }
10448 10454
10449 10455 void
10450 10456 sas_phymap_phys_free(sas_phymap_phys_t *phys)
10451 10457 {
10452 10458 bitset_t *cphys = (bitset_t *)phys;
10453 10459
10454 10460 if (cphys) {
10455 10461 bitset_fini(cphys);
10456 10462 kmem_free(cphys, sizeof (*cphys));
10457 10463 }
10458 10464 }
10459 10465
10460 10466 char *
10461 10467 sas_phymap_phy2ua(sas_phymap_t *handle, int phy)
10462 10468 {
10463 10469 impl_sas_phymap_t *phymap = (impl_sas_phymap_t *)handle;
10464 10470 char *name;
10465 10471 char *ua;
10466 10472 char *rua = NULL;
10467 10473
10468 10474 mutex_enter(&phymap->phymap_lock);
10469 10475 name = ddi_get_soft_state(phymap->phymap_phy2name, phy);
10470 10476 if (name == NULL)
10471 10477 goto fail;
10472 10478 ua = ddi_soft_state_bystr_get(phymap->phymap_name2ua, name);
10473 10479 if (ua == NULL)
10474 10480 goto fail;
10475 10481
10476 10482 /* dup the ua and return */
10477 10483 rua = strdup(ua);
10478 10484
10479 10485 fail: mutex_exit(&phymap->phymap_lock);
10480 10486 return (rua);
10481 10487 }
10482 10488
10483 10489 void
10484 10490 sas_phymap_ua_free(char *ua)
10485 10491 {
10486 10492 if (ua)
10487 10493 strfree(ua);
10488 10494 }
|
↓ open down ↓ |
7376 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX