1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2023 Tintri by DDN, Inc. All rights reserved.
14 * Copyright 2021 RackTop Systems, Inc.
15 */
16
17 /*
18 * This file contains all routines necessary to interface with SCSA trans.
19 */
20 #include <smartpqi.h>
21
22 /*
23 * []------------------------------------------------------------------[]
24 * | Forward declarations for SCSA trans routines. |
25 * []------------------------------------------------------------------[]
26 */
27 static int pqi_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
28 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
29 static void pqi_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
30 scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
31 static int pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
32 static int pqi_scsi_reset(struct scsi_address *ap, int level);
33 static int pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
34 static int pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
35 static int pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value,
36 int tgtonly);
37 static struct scsi_pkt *pqi_init_pkt(struct scsi_address *ap,
38 struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, int tgtlen,
39 int flags, int (*callback)(), caddr_t arg);
40 static void pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
41 static void pqi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
42 static void pqi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
43 static int pqi_reset_notify(struct scsi_address *ap, int flag,
44 void (*callback)(caddr_t), caddr_t arg);
45 static int pqi_quiesce(dev_info_t *dip);
46 static int pqi_unquiesce(dev_info_t *dip);
47 static int pqi_bus_config(dev_info_t *pdip, uint_t flag,
48 ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
49
50 /* ---- Support method declaration ---- */
51 static int config_one(dev_info_t *pdip, pqi_state_t *s, pqi_device_t *,
52 dev_info_t **childp);
53 static void abort_all(struct scsi_address *ap, pqi_state_t *s);
54 static int cmd_ext_alloc(pqi_cmd_t *cmd, int kf);
55 static void cmd_ext_free(pqi_cmd_t *cmd);
56 static boolean_t is_physical_dev(pqi_device_t *d);
57 static void cmd_timeout_scan(void *);
58
59 boolean_t
smartpqi_register_hba(pqi_state_t * s)60 smartpqi_register_hba(pqi_state_t *s)
61 {
62 scsi_hba_tran_t *tran;
63 int flags;
64 char iport_str[16];
65 int instance = ddi_get_instance(s->s_dip);
66
67 tran = scsi_hba_tran_alloc(s->s_dip, SCSI_HBA_CANSLEEP);
68 if (tran == NULL)
69 return (B_FALSE);
70 s->s_tran = tran;
71
72 tran->tran_hba_private = s;
73 tran->tran_tgt_private = NULL;
74
75 tran->tran_tgt_init = pqi_scsi_tgt_init;
76 tran->tran_tgt_free = pqi_scsi_tgt_free;
77 tran->tran_tgt_probe = scsi_hba_probe;
78
79 tran->tran_start = pqi_start;
80 tran->tran_reset = pqi_scsi_reset;
81 tran->tran_abort = pqi_scsi_abort;
82 tran->tran_getcap = pqi_scsi_getcap;
83 tran->tran_setcap = pqi_scsi_setcap;
84 tran->tran_bus_config = pqi_bus_config;
85
86 tran->tran_init_pkt = pqi_init_pkt;
87 tran->tran_destroy_pkt = pqi_destroy_pkt;
88 tran->tran_dmafree = pqi_dmafree;
89 tran->tran_sync_pkt = pqi_sync_pkt;
90
91 tran->tran_reset_notify = pqi_reset_notify;
92 tran->tran_quiesce = pqi_quiesce;
93 tran->tran_unquiesce = pqi_unquiesce;
94 tran->tran_bus_reset = NULL;
95
96 tran->tran_add_eventcall = NULL;
97 tran->tran_get_eventcookie = NULL;
98 tran->tran_post_event = NULL;
99 tran->tran_remove_eventcall = NULL;
100 tran->tran_bus_config = pqi_bus_config;
101 tran->tran_interconnect_type = INTERCONNECT_SAS;
102
103 /*
104 * scsi_vhci needs to have "initiator-port" set, but doesn't
105 * seem to care what it's set to. iSCSI uses the InitiatorName
106 * whereas mpt_sas uses the WWN port id, but this HBA doesn't
107 * have such a value. So, for now the instance number will be used.
108 */
109 (void) snprintf(iport_str, sizeof (iport_str), "0x%x", instance);
110 if (ddi_prop_update_string(DDI_DEV_T_NONE, s->s_dip,
111 SCSI_ADDR_PROP_INITIATOR_PORT, iport_str) != DDI_PROP_SUCCESS) {
112 cmn_err(CE_WARN, "%s: Failed to create prop (%s) on %d\n",
113 __func__, SCSI_ADDR_PROP_INITIATOR_PORT, instance);
114 }
115
116 flags = SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB;
117 if (scsi_hba_attach_setup(s->s_dip, &s->s_msg_dma_attr, tran,
118 flags) != DDI_SUCCESS) {
119 dev_err(s->s_dip, CE_NOTE, "scsi_hba_attach_setup failed");
120 scsi_hba_tran_free(s->s_tran);
121 s->s_tran = NULL;
122 return (B_FALSE);
123 }
124
125 if (!s->s_disable_mpxio) {
126 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, s->s_dip, 0) !=
127 MDI_SUCCESS) {
128 cmn_err(CE_WARN, "%s: Failed to register with mpxio",
129 __func__);
130 s->s_disable_mpxio = B_TRUE;
131 }
132 }
133
134 s->s_cmd_timeout = timeout(cmd_timeout_scan, s,
135 CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC));
136
137 return (B_TRUE);
138 }
139
140 void
smartpqi_unregister_hba(pqi_state_t * s)141 smartpqi_unregister_hba(pqi_state_t *s)
142 {
143 if (!s->s_disable_mpxio)
144 (void) mdi_phci_unregister(s->s_dip, 0);
145
146 if (s->s_cmd_timeout != NULL) {
147 (void) untimeout(s->s_cmd_timeout);
148 s->s_cmd_timeout = NULL;
149 }
150
151 if (s->s_tran == NULL)
152 return;
153 scsi_hba_tran_free(s->s_tran);
154 s->s_tran = NULL;
155 }
156
157 static int
pqi_scsi_tgt_init(dev_info_t * hba_dip __unused,dev_info_t * tgt_dip,scsi_hba_tran_t * hba_tran,struct scsi_device * sd)158 pqi_scsi_tgt_init(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip,
159 scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
160 {
161 pqi_device_t *d;
162 pqi_state_t *s = hba_tran->tran_hba_private;
163 mdi_pathinfo_t *pip;
164 int type;
165 char *ua;
166
167 if ((ua = scsi_device_unit_address(sd)) == NULL) {
168 return (DDI_FAILURE);
169 }
170
171 if ((d = pqi_find_target_ua(s, ua)) == NULL) {
172 return (DDI_FAILURE);
173 }
174
175 scsi_device_hba_private_set(sd, d);
176
177 type = mdi_get_component_type(tgt_dip);
178 if (type == MDI_COMPONENT_CLIENT) {
179 char wwid_str[64];
180
181 if ((pip = (mdi_pathinfo_t *)sd->sd_private) == NULL)
182 return (DDI_NOT_WELL_FORMED);
183
184 (void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64,
185 d->pd_wwid);
186 (void) mdi_prop_update_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
187 wwid_str);
188 }
189
190 return (DDI_SUCCESS);
191 }
192
193 static void
pqi_scsi_tgt_free(dev_info_t * hba_dip __unused,dev_info_t * tgt_dip __unused,scsi_hba_tran_t * hba_tran __unused,struct scsi_device * sd __unused)194 pqi_scsi_tgt_free(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip __unused,
195 scsi_hba_tran_t *hba_tran __unused, struct scsi_device *sd __unused)
196 {
197 }
198
199 /*
200 * Notes:
201 * - transport the command to the addressed SCSI target/lun device
202 * - normal operation is to schedule the command to be transported,
203 * and return TRAN_ACCEPT if this is successful.
204 * - if NO_INTR, tran_start must poll device for command completion
205 */
206 static int
pqi_start(struct scsi_address * ap,struct scsi_pkt * pkt)207 pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
208 {
209 boolean_t poll = ((pkt->pkt_flags & FLAG_NOINTR) != 0);
210 int rc;
211 pqi_cmd_t *cmd = PKT2CMD(pkt);
212 pqi_state_t *s = ap->a_hba_tran->tran_hba_private;
213
214 ASSERT3P(cmd->pc_pkt, ==, pkt);
215 ASSERT3P(cmd->pc_softc, ==, s);
216
217 if (pqi_is_offline(s) || !cmd->pc_device->pd_online)
218 return (TRAN_FATAL_ERROR);
219
220 /*
221 * Reinitialize some fields because the packet may have been
222 * resubmitted.
223 */
224 pkt->pkt_reason = CMD_CMPLT;
225 pkt->pkt_state = 0;
226 pkt->pkt_statistics = 0;
227
228 /* ---- Zero status byte ---- */
229 *(pkt->pkt_scbp) = 0;
230
231 if ((cmd->pc_flags & PQI_FLAG_DMA_VALID) != 0) {
232 ASSERT(cmd->pc_dma_count);
233 pkt->pkt_resid = cmd->pc_dma_count;
234
235 /* ---- Sync consistent packets first (only write data) ---- */
236 if (((cmd->pc_flags & PQI_FLAG_IO_IOPB) != 0) ||
237 ((cmd->pc_flags & PQI_FLAG_IO_READ) == 0)) {
238 (void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0,
239 DDI_DMA_SYNC_FORDEV);
240 }
241 }
242
243 mutex_enter(&s->s_mutex);
244 if (HBA_IS_QUIESCED(s) && !poll) {
245 mutex_exit(&s->s_mutex);
246 return (TRAN_BUSY);
247 }
248 mutex_exit(&s->s_mutex);
249
250 rc = pqi_transport_command(s, cmd);
251
252 if (poll) {
253 boolean_t qnotify;
254
255 if (rc == TRAN_ACCEPT) {
256 uint32_t old_state;
257 int timeo;
258
259 timeo = pkt->pkt_time ? pkt->pkt_time :
260 SCSI_POLL_TIMEOUT;
261 timeo *= MILLISEC / 2;
262 old_state = pqi_disable_intr(s);
263 do {
264 drv_usecwait(MILLISEC / 2);
265 pqi_process_io_intr(s, &s->s_queue_groups[0]);
266 if (--timeo == 0) {
267 pkt->pkt_state |= STAT_TIMEOUT;
268 pkt->pkt_reason = CMD_TIMEOUT;
269 break;
270 }
271 } while (pkt->pkt_state == 0);
272 pqi_enable_intr(s, old_state);
273 }
274
275 scsi_hba_pkt_comp(pkt);
276
277 mutex_enter(&s->s_mutex);
278 qnotify = HBA_QUIESCED_PENDING(s);
279 mutex_exit(&s->s_mutex);
280
281 if (qnotify)
282 pqi_quiesced_notify(s);
283 }
284
285 return (rc);
286 }
287
288 static int
pqi_scsi_reset(struct scsi_address * ap,int level)289 pqi_scsi_reset(struct scsi_address *ap, int level)
290 {
291 pqi_device_t *d;
292 pqi_state_t *s;
293 int rval = FALSE;
294
295 s = ap->a_hba_tran->tran_hba_private;
296 switch (level) {
297 case RESET_TARGET:
298 case RESET_LUN:
299 if ((d = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
300 break;
301
302 pqi_lun_reset(s, d);
303 rval = TRUE;
304 break;
305
306 case RESET_BUS:
307 case RESET_ALL:
308 mutex_enter(&s->s_mutex);
309 for (d = list_head(&s->s_devnodes); d != NULL;
310 d = list_next(&s->s_devnodes, d)) {
311 pqi_lun_reset(s, d);
312 }
313 mutex_exit(&s->s_mutex);
314 rval = TRUE;
315 break;
316 }
317 return (rval);
318 }
319
320 /*
321 * abort handling:
322 *
323 * Notes:
324 * - if pkt is not NULL, abort just that command
325 * - if pkt is NULL, abort all outstanding commands for target
326 */
327 static int
pqi_scsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)328 pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
329 {
330 boolean_t qnotify = B_FALSE;
331 pqi_state_t *s = ADDR2PQI(ap);
332
333 if (pkt != NULL) {
334 /* ---- Abort single command ---- */
335 pqi_cmd_t *cmd = PKT2CMD(pkt);
336
337 mutex_enter(&cmd->pc_device->pd_mutex);
338 (void) pqi_fail_cmd(cmd, CMD_ABORTED, STAT_ABORTED);
339 mutex_exit(&cmd->pc_device->pd_mutex);
340 } else {
341 abort_all(ap, s);
342 }
343 qnotify = HBA_QUIESCED_PENDING(s);
344
345 if (qnotify)
346 pqi_quiesced_notify(s);
347 return (1);
348 }
349
350 /*
351 * capability handling:
352 * (*tran_getcap). Get the capability named, and return its value.
353 */
354 static int
pqi_scsi_getcap(struct scsi_address * ap,char * cap,int tgtonly __unused)355 pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly __unused)
356 {
357 pqi_state_t *s = ap->a_hba_tran->tran_hba_private;
358
359 if (cap == NULL)
360 return (-1);
361 switch (scsi_hba_lookup_capstr(cap)) {
362 case SCSI_CAP_LUN_RESET:
363 return ((s->s_flags & PQI_HBA_LUN_RESET_CAP) != 0);
364 case SCSI_CAP_ARQ:
365 return ((s->s_flags & PQI_HBA_AUTO_REQUEST_SENSE) != 0);
366 case SCSI_CAP_UNTAGGED_QING:
367 return (1);
368 default:
369 return (-1);
370 }
371 }
372
373 /*
374 * (*tran_setcap). Set the capability named to the value given.
375 */
376 static int
pqi_scsi_setcap(struct scsi_address * ap,char * cap,int value,int tgtonly __unused)377 pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value,
378 int tgtonly __unused)
379 {
380 pqi_state_t *s = ADDR2PQI(ap);
381 int rval = FALSE;
382
383 if (cap == NULL)
384 return (-1);
385
386 switch (scsi_hba_lookup_capstr(cap)) {
387 case SCSI_CAP_ARQ:
388 if (value)
389 s->s_flags |= PQI_HBA_AUTO_REQUEST_SENSE;
390 else
391 s->s_flags &= ~PQI_HBA_AUTO_REQUEST_SENSE;
392 rval = 1;
393 break;
394
395 case SCSI_CAP_LUN_RESET:
396 if (value)
397 s->s_flags |= PQI_HBA_LUN_RESET_CAP;
398 else
399 s->s_flags &= ~PQI_HBA_LUN_RESET_CAP;
400 break;
401
402 default:
403 break;
404 }
405
406 return (rval);
407 }
408
409 int
pqi_cache_constructor(void * buf,void * un,int flags)410 pqi_cache_constructor(void *buf, void *un, int flags)
411 {
412 pqi_cmd_t *c = (pqi_cmd_t *)buf;
413 pqi_state_t *s = un;
414 int (*callback)(caddr_t);
415
416 bzero(c, sizeof (*c));
417 c->pc_softc = s;
418 callback = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
419
420 /* ---- Allocate a DMA handle for data transfers ---- */
421 if (ddi_dma_alloc_handle(s->s_dip, &s->s_msg_dma_attr, callback,
422 NULL, &c->pc_dmahdl) != DDI_SUCCESS) {
423 dev_err(s->s_dip, CE_WARN, "Failed to alloc dma handle");
424 return (-1);
425 }
426
427 return (0);
428 }
429
430 void
pqi_cache_destructor(void * buf,void * un __unused)431 pqi_cache_destructor(void *buf, void *un __unused)
432 {
433 pqi_cmd_t *cmd = buf;
434 if (cmd->pc_dmahdl != NULL) {
435 (void) ddi_dma_unbind_handle(cmd->pc_dmahdl);
436 ddi_dma_free_handle(&cmd->pc_dmahdl);
437 cmd->pc_dmahdl = NULL;
438 }
439 }
440
441 /*
442 * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
443 *
444 * One of three possibilities:
445 * - allocate scsi_pkt
446 * - allocate scsi_pkt and DMA resources
447 * - allocate DMA resources to an already-allocated pkt
448 */
449 static struct scsi_pkt *
pqi_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)450 pqi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
451 struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
452 int (*callback)(), caddr_t arg)
453 {
454 pqi_cmd_t *cmd;
455 pqi_state_t *s;
456 int kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
457 boolean_t is_new = B_FALSE;
458 int rc;
459 int i;
460 pqi_device_t *devp;
461
462 s = ap->a_hba_tran->tran_hba_private;
463
464 if (pkt == NULL) {
465 ddi_dma_handle_t saved_dmahdl;
466 pqi_cmd_action_t saved_action;
467
468 if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
469 return (NULL);
470 if ((cmd = kmem_cache_alloc(s->s_cmd_cache, kf)) == NULL)
471 return (NULL);
472
473 is_new = B_TRUE;
474 saved_dmahdl = cmd->pc_dmahdl;
475 saved_action = cmd->pc_last_action;
476
477 (void) memset(cmd, 0, sizeof (*cmd));
478 mutex_init(&cmd->pc_mutex, NULL, MUTEX_DRIVER, NULL);
479
480 cmd->pc_dmahdl = saved_dmahdl;
481 cmd->pc_last_action = saved_action;
482
483 cmd->pc_device = devp;
484 cmd->pc_pkt = &cmd->pc_cached_pkt;
485 cmd->pc_softc = s;
486 cmd->pc_tgtlen = tgtlen;
487 cmd->pc_statuslen = statuslen;
488 cmd->pc_cmdlen = cmdlen;
489 cmd->pc_dma_count = 0;
490
491 pkt = cmd->pc_pkt;
492 pkt->pkt_ha_private = cmd;
493 pkt->pkt_address = *ap;
494 pkt->pkt_scbp = (uint8_t *)&cmd->pc_cmd_scb;
495 pkt->pkt_cdbp = cmd->pc_cdb;
496 pkt->pkt_private = (opaque_t)cmd->pc_tgt_priv;
497 if (pkt->pkt_time == 0)
498 pkt->pkt_time = SCSI_POLL_TIMEOUT;
499
500 if (cmdlen > sizeof (cmd->pc_cdb) ||
501 statuslen > sizeof (cmd->pc_cmd_scb) ||
502 tgtlen > sizeof (cmd->pc_tgt_priv)) {
503 if (cmd_ext_alloc(cmd, kf) != DDI_SUCCESS) {
504 dev_err(s->s_dip, CE_WARN,
505 "extent allocation failed");
506 goto out;
507 }
508 }
509 } else {
510 cmd = PKT2CMD(pkt);
511 cmd->pc_flags &= PQI_FLAGS_PERSISTENT;
512 }
513
514 /* ---- Handle partial DMA transfer ---- */
515 if (cmd->pc_nwin > 0) {
516 if (++cmd->pc_winidx >= cmd->pc_nwin)
517 return (NULL);
518 if (ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx,
519 &cmd->pc_dma_offset, &cmd->pc_dma_len, &cmd->pc_dmac,
520 &cmd->pc_dmaccount) == DDI_FAILURE)
521 return (NULL);
522 goto handle_dma_cookies;
523 }
524
525 /* ---- Setup data buffer ---- */
526 if (bp != NULL && bp->b_bcount > 0 &&
527 (cmd->pc_flags & PQI_FLAG_DMA_VALID) == 0) {
528 int dma_flags;
529
530 ASSERT(cmd->pc_dmahdl != NULL);
531
532 if ((bp->b_flags & B_READ) != 0) {
533 cmd->pc_flags |= PQI_FLAG_IO_READ;
534 dma_flags = DDI_DMA_READ;
535 } else {
536 cmd->pc_flags &= ~PQI_FLAG_IO_READ;
537 dma_flags = DDI_DMA_WRITE;
538 }
539 if ((flags & PKT_CONSISTENT) != 0) {
540 cmd->pc_flags |= PQI_FLAG_IO_IOPB;
541 dma_flags |= DDI_DMA_CONSISTENT;
542 }
543 if ((flags & PKT_DMA_PARTIAL) != 0) {
544 dma_flags |= DDI_DMA_PARTIAL;
545 }
546 rc = ddi_dma_buf_bind_handle(cmd->pc_dmahdl, bp,
547 dma_flags, callback, arg, &cmd->pc_dmac,
548 &cmd->pc_dmaccount);
549
550 if (rc == DDI_DMA_PARTIAL_MAP) {
551 (void) ddi_dma_numwin(cmd->pc_dmahdl, &cmd->pc_nwin);
552 cmd->pc_winidx = 0;
553 (void) ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx,
554 &cmd->pc_dma_offset, &cmd->pc_dma_len,
555 &cmd->pc_dmac, &cmd->pc_dmaccount);
556 } else if (rc != 0 && rc != DDI_DMA_MAPPED) {
557 switch (rc) {
558 case DDI_DMA_NORESOURCES:
559 bioerror(bp, 0);
560 break;
561 case DDI_DMA_BADATTR:
562 case DDI_DMA_NOMAPPING:
563 bioerror(bp, EFAULT);
564 break;
565 case DDI_DMA_TOOBIG:
566 default:
567 bioerror(bp, EINVAL);
568 break;
569 }
570 goto out;
571 }
572
573 handle_dma_cookies:
574 ASSERT(cmd->pc_dmaccount > 0);
575 if (cmd->pc_dmaccount >
576 (sizeof (cmd->pc_cached_cookies) /
577 sizeof (ddi_dma_cookie_t))) {
578 dev_err(s->s_dip, CE_WARN,
579 "invalid cookie count: %d", cmd->pc_dmaccount);
580 goto out;
581 }
582 if (cmd->pc_dmaccount >
583 (s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t))) {
584 dev_err(s->s_dip, CE_WARN,
585 "Cookie(0x%x) verses SG(0x%" PRIx64 ") mismatch",
586 cmd->pc_dmaccount,
587 s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t));
588 goto out;
589 }
590
591 cmd->pc_flags |= PQI_FLAG_DMA_VALID;
592 cmd->pc_dma_count = cmd->pc_dmac.dmac_size;
593 cmd->pc_cached_cookies[0] = cmd->pc_dmac;
594
595 for (i = 1; i < cmd->pc_dmaccount; i++) {
596 ddi_dma_nextcookie(cmd->pc_dmahdl, &cmd->pc_dmac);
597 cmd->pc_cached_cookies[i] = cmd->pc_dmac;
598 cmd->pc_dma_count += cmd->pc_dmac.dmac_size;
599 }
600
601 pkt->pkt_resid = bp->b_bcount - cmd->pc_dma_count;
602 }
603
604 return (pkt);
605
606 out:
607 if (is_new == B_TRUE)
608 pqi_destroy_pkt(ap, pkt);
609 return (NULL);
610 }
611
612 /*
613 * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
614 *
615 * Notes:
616 * - also frees DMA resources if allocated
617 * - implicit DMA synchonization
618 */
619 static void
pqi_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)620 pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
621 {
622 pqi_cmd_t *c = PKT2CMD(pkt);
623 pqi_state_t *s = ADDR2PQI(ap);
624
625 if ((c->pc_flags & PQI_FLAG_DMA_VALID) != 0) {
626 c->pc_flags &= ~PQI_FLAG_DMA_VALID;
627 (void) ddi_dma_unbind_handle(c->pc_dmahdl);
628 }
629 cmd_ext_free(c);
630
631 kmem_cache_free(s->s_cmd_cache, c);
632 }
633
634 /*
635 * tran_dmafree(9E) - deallocate DMA resources allocated for command
636 */
637 static void
pqi_dmafree(struct scsi_address * ap __unused,struct scsi_pkt * pkt)638 pqi_dmafree(struct scsi_address *ap __unused, struct scsi_pkt *pkt)
639 {
640 pqi_cmd_t *cmd = PKT2CMD(pkt);
641
642 if (cmd->pc_flags & PQI_FLAG_DMA_VALID) {
643 cmd->pc_flags &= ~PQI_FLAG_DMA_VALID;
644 (void) ddi_dma_unbind_handle(cmd->pc_dmahdl);
645 }
646 }
647
648 /*
649 * tran_sync_pkt(9E) - explicit DMA synchronization
650 */
651 static void
pqi_sync_pkt(struct scsi_address * ap __unused,struct scsi_pkt * pkt)652 pqi_sync_pkt(struct scsi_address *ap __unused, struct scsi_pkt *pkt)
653 {
654 pqi_cmd_t *cmd = PKT2CMD(pkt);
655
656 if (cmd->pc_dmahdl != NULL) {
657 (void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0,
658 (cmd->pc_flags & PQI_FLAG_IO_READ) ? DDI_DMA_SYNC_FORCPU :
659 DDI_DMA_SYNC_FORDEV);
660 }
661 }
662
663 static int
pqi_reset_notify(struct scsi_address * ap,int flag,void (* callback)(caddr_t),caddr_t arg)664 pqi_reset_notify(struct scsi_address *ap, int flag,
665 void (*callback)(caddr_t), caddr_t arg)
666 {
667 pqi_state_t *s = ADDR2PQI(ap);
668
669 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
670 &s->s_mutex, &s->s_reset_notify_listf));
671 }
672
673 /*
674 * Device / Hotplug control
675 */
676 static int
pqi_quiesce(dev_info_t * dip)677 pqi_quiesce(dev_info_t *dip)
678 {
679 pqi_state_t *s;
680 scsi_hba_tran_t *tran;
681
682 if ((tran = ddi_get_driver_private(dip)) == NULL ||
683 (s = TRAN2PQI(tran)) == NULL)
684 return (-1);
685
686 mutex_enter(&s->s_mutex);
687 if (!HBA_IS_QUIESCED(s))
688 s->s_flags |= PQI_HBA_QUIESCED;
689
690 if (s->s_cmd_queue_len != 0) {
691 /* ---- Outstanding commands present, wait ---- */
692 s->s_flags |= PQI_HBA_QUIESCED_PENDING;
693 cv_wait(&s->s_quiescedvar, &s->s_mutex);
694 ASSERT0(s->s_cmd_queue_len);
695 }
696 mutex_exit(&s->s_mutex);
697
698 return (0);
699 }
700
701 static int
pqi_unquiesce(dev_info_t * dip)702 pqi_unquiesce(dev_info_t *dip)
703 {
704 pqi_state_t *s;
705 scsi_hba_tran_t *tran;
706
707 if ((tran = ddi_get_driver_private(dip)) == NULL ||
708 (s = TRAN2PQI(tran)) == NULL)
709 return (-1);
710
711 mutex_enter(&s->s_mutex);
712 if (!HBA_IS_QUIESCED(s)) {
713 mutex_exit(&s->s_mutex);
714 return (0);
715 }
716 ASSERT0(s->s_cmd_queue_len);
717 s->s_flags &= ~PQI_HBA_QUIESCED;
718 mutex_exit(&s->s_mutex);
719
720 return (0);
721 }
722
723 static int
pqi_bus_config(dev_info_t * pdip,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)724 pqi_bus_config(dev_info_t *pdip, uint_t flag,
725 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
726 {
727 scsi_hba_tran_t *tran;
728 pqi_state_t *s;
729 int ret = NDI_FAILURE;
730 pqi_device_t *d;
731 char *ua;
732
733 tran = ddi_get_driver_private(pdip);
734 s = tran->tran_hba_private;
735 if (pqi_is_offline(s))
736 return (NDI_FAILURE);
737
738 ndi_devi_enter(scsi_vhci_dip);
739 ndi_devi_enter(pdip);
740 switch (op) {
741 case BUS_CONFIG_ONE:
742 if ((ua = strrchr((char *)arg, '@')) != NULL) {
743 ua++;
744 d = pqi_find_target_ua(s, ua);
745 if (d != NULL)
746 ret = config_one(pdip, s, d, childp);
747 } else {
748 dev_err(s->s_dip, CE_WARN, "Couldn't decode %s",
749 (char *)arg);
750 }
751 flag |= NDI_MDI_FALLBACK;
752 break;
753
754 case BUS_CONFIG_DRIVER:
755 case BUS_CONFIG_ALL:
756 ret = pqi_config_all(pdip, s);
757 break;
758 default:
759 ret = NDI_FAILURE;
760 }
761 if (ret == NDI_SUCCESS)
762 ret = ndi_busop_bus_config(pdip, flag, op, arg, childp, 0);
763 ndi_devi_exit(pdip);
764 ndi_devi_exit(scsi_vhci_dip);
765
766 return (ret);
767 }
768
769 pqi_device_t *
pqi_find_target_ua(pqi_state_t * s,char * ua)770 pqi_find_target_ua(pqi_state_t *s, char *ua)
771 {
772 pqi_device_t *d;
773
774 mutex_enter(&s->s_mutex);
775 for (d = list_head(&s->s_devnodes); d != NULL;
776 d = list_next(&s->s_devnodes, d)) {
777 if (d->pd_online && strcmp(ua, d->pd_unit_address) == 0)
778 break;
779 }
780 mutex_exit(&s->s_mutex);
781 return (d);
782 }
783
784 int
pqi_config_all(dev_info_t * pdip,pqi_state_t * s)785 pqi_config_all(dev_info_t *pdip, pqi_state_t *s)
786 {
787 pqi_device_t *d;
788
789 /*
790 * Make sure we bring the available devices into play first. These
791 * might be brand new devices just hotplugged into the system or
792 * they could be devices previously offlined because either they
793 * were pulled from an enclosure or a cable to the enclosure was
794 * pulled.
795 */
796 /* ---- XXX Grab s_mutex ---- */
797 for (d = list_head(&s->s_devnodes); d != NULL;
798 d = list_next(&s->s_devnodes, d)) {
799 if (d->pd_online)
800 (void) config_one(pdip, s, d, NULL);
801 }
802
803 /*
804 * Now deal with devices that we had previously known about, but are
805 * no longer available.
806 */
807 for (d = list_head(&s->s_devnodes); d != NULL;
808 d = list_next(&s->s_devnodes, d)) {
809 if (!d->pd_online)
810 (void) config_one(pdip, s, d, NULL);
811 }
812
813 return (NDI_SUCCESS);
814 }
815
816 void
pqi_quiesced_notify(pqi_state_t * s)817 pqi_quiesced_notify(pqi_state_t *s)
818 {
819 mutex_enter(&s->s_mutex);
820 if (s->s_cmd_queue_len == 0 &&
821 (s->s_flags & PQI_HBA_QUIESCED_PENDING) != 0) {
822 s->s_flags &= ~PQI_HBA_QUIESCED_PENDING;
823 cv_broadcast(&s->s_quiescedvar);
824 }
825 mutex_exit(&s->s_mutex);
826 }
827
828 /*
829 * []------------------------------------------------------------------[]
830 * | Support routines used only by the trans_xxx routines |
831 * []------------------------------------------------------------------[]
832 */
833 #ifdef DEBUG
834 int pqi_force_timeout;
835 #endif /* DEBUG */
836
837 static void
cmd_timeout_drive(pqi_device_t * d)838 cmd_timeout_drive(pqi_device_t *d)
839 {
840 uint32_t timed_out_cnt = 0;
841 pqi_cmd_t *c, *next_c;
842 hrtime_t now = gethrtime();
843
844 mutex_enter(&d->pd_mutex);
845
846 rescan:
847 c = list_head(&d->pd_cmd_list);
848 while (c != NULL) {
849 next_c = list_next(&d->pd_cmd_list, c);
850 #ifdef DEBUG
851 if (c->pc_expiration < now || pqi_force_timeout != 0) {
852 pqi_force_timeout = 0;
853 #else
854 if (c->pc_expiration < now) {
855 #endif /* DEBUG */
856 struct scsi_pkt *pkt = CMD2PKT(c);
857
858 if (pkt != NULL) {
859 pkt->pkt_reason = CMD_TIMEOUT;
860 pkt->pkt_statistics = STAT_TIMEOUT;
861 }
862 ASSERT(c->pc_io_rqst != NULL);
863 /*
864 * If the i/o has not been serviced yet,
865 * mark the i/o as timed out and clear it out
866 */
867 if (pqi_timeout_io(c->pc_io_rqst)) {
868 (void) pqi_cmd_action_nolock(c,
869 PQI_CMD_TIMEOUT);
870 timed_out_cnt++;
871 /*
872 * We dropped pd_mutex so the cmd
873 * list could have changed, restart the
874 * scan of the cmds. This will terminate
875 * since timed out cmds are removed from
876 * the list.
877 */
878 goto rescan;
879 }
880 }
881 c = next_c;
882 }
883
884 d->pd_timedout += timed_out_cnt;
885 mutex_exit(&d->pd_mutex);
886 }
887
888 static void
889 cmd_timeout_scan(void *v)
890 {
891 pqi_state_t *s = v;
892 pqi_device_t *d;
893
894 mutex_enter(&s->s_mutex);
895
896 for (d = list_head(&s->s_devnodes); d != NULL;
897 d = list_next(&s->s_devnodes, d)) {
898 cmd_timeout_drive(d);
899 }
900 cmd_timeout_drive(&s->s_special_device);
901
902 mutex_exit(&s->s_mutex);
903 s->s_cmd_timeout = timeout(cmd_timeout_scan, s,
904 CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC));
905 }
906
907 static void
908 abort_all(struct scsi_address *ap, pqi_state_t *s __unused)
909 {
910 pqi_device_t *devp;
911
912 if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL)
913 return;
914
915 pqi_fail_drive_cmds(devp, CMD_ABORTED);
916 }
917
918 static boolean_t
919 create_phys_lun(pqi_state_t *s, pqi_device_t *d,
920 struct scsi_inquiry *inq, dev_info_t **childp)
921 {
922 char **compatible = NULL;
923 char *nodename = NULL;
924 int ncompatible = 0;
925 dev_info_t *dip;
926
927 /* ---- At this point we have a new device not in our list ---- */
928 scsi_hba_nodename_compatible_get(inq, NULL,
929 inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
930 if (nodename == NULL)
931 return (B_FALSE);
932
933 if (ndi_devi_alloc(s->s_dip, nodename, DEVI_SID_NODEID, &dip) !=
934 NDI_SUCCESS) {
935 dev_err(s->s_dip, CE_WARN, "failed to alloc device instance");
936 goto free_nodename;
937 }
938
939 d->pd_dip = dip;
940 d->pd_pip = NULL;
941
942 if (ndi_prop_update_int64(DDI_DEV_T_NONE, dip, LUN64_PROP,
943 d->pd_lun) != DDI_PROP_SUCCESS) {
944 goto free_devi;
945 }
946
947 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, COMPAT_PROP,
948 compatible, ncompatible) != DDI_PROP_SUCCESS) {
949 goto free_devi;
950 }
951
952 if (d->pd_wwid != 0) {
953 char wwn_str[20];
954 (void) snprintf(wwn_str, 20, "w%016" PRIx64, d->pd_wwid);
955 if (ndi_prop_update_string(DDI_DEV_T_NONE, dip,
956 SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS) {
957 goto free_devi;
958 }
959 } else {
960 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, TARGET_PROP,
961 d->pd_target) != DDI_PROP_SUCCESS) {
962 goto free_devi;
963 }
964 }
965
966 if (d->pd_guid != NULL) {
967 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, NDI_GUID,
968 d->pd_guid) != DDI_PROP_SUCCESS) {
969 goto free_devi;
970 }
971 }
972
973 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "pm-capable", 1) !=
974 DDI_PROP_SUCCESS) {
975 goto free_devi;
976 }
977
978 if (ndi_devi_online(dip, NDI_ONLINE_ATTACH) != NDI_SUCCESS)
979 goto free_devi;
980
981 if (childp != NULL)
982 *childp = dip;
983
984 scsi_hba_nodename_compatible_free(nodename, compatible);
985
986 return (B_TRUE);
987
988 free_devi:
989 ndi_prop_remove_all(dip);
990 (void) ndi_devi_free(dip);
991 d->pd_dip = NULL;
992 free_nodename:
993 scsi_hba_nodename_compatible_free(nodename, compatible);
994 return (B_FALSE);
995 }
996
997 static boolean_t
998 create_virt_lun(pqi_state_t *s, pqi_device_t *d, struct scsi_inquiry *inq,
999 dev_info_t **childp)
1000 {
1001 char *nodename;
1002 char **compatible;
1003 int ncompatible;
1004 int rval;
1005 mdi_pathinfo_t *pip = NULL;
1006 char *guid_ptr;
1007 char wwid_str[17];
1008 dev_info_t *lun_dip;
1009 char *old_guid;
1010
1011 if (d->pd_pip_offlined != NULL) {
1012 lun_dip = mdi_pi_get_client(d->pd_pip_offlined);
1013 ASSERT(lun_dip != NULL);
1014
1015 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
1016 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
1017 MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
1018 if (strncmp(d->pd_guid, old_guid,
1019 strlen(d->pd_guid)) == 0) {
1020 /* ---- Same path came back online ---- */
1021 (void) ddi_prop_free(old_guid);
1022 if (mdi_pi_online(d->pd_pip_offlined, 0) ==
1023 DDI_SUCCESS) {
1024 d->pd_pip = d->pd_pip_offlined;
1025 d->pd_pip_offlined = NULL;
1026 return (B_TRUE);
1027 } else {
1028 return (B_FALSE);
1029 }
1030 } else {
1031 /* ---- Different device in slot ---- */
1032 (void) ddi_prop_free(old_guid);
1033 if (mdi_pi_offline(d->pd_pip_offlined, 0) !=
1034 DDI_SUCCESS) {
1035 return (B_FALSE);
1036 }
1037 if (mdi_pi_free(d->pd_pip_offlined, 0) !=
1038 MDI_SUCCESS) {
1039 return (B_FALSE);
1040 }
1041 d->pd_pip_offlined = NULL;
1042 }
1043 } else {
1044 dev_err(s->s_dip, CE_WARN, "Can't get client-guid "
1045 "property for lun %lx", d->pd_wwid);
1046 return (B_FALSE);
1047 }
1048 }
1049
1050 scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
1051 &nodename, &compatible, &ncompatible);
1052 if (nodename == NULL)
1053 return (B_FALSE);
1054
1055 if (d->pd_guid != NULL) {
1056 guid_ptr = d->pd_guid;
1057 } else {
1058 (void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64,
1059 d->pd_wwid);
1060 guid_ptr = wwid_str;
1061 }
1062 rval = mdi_pi_alloc_compatible(s->s_dip, nodename, guid_ptr,
1063 d->pd_unit_address, compatible, ncompatible, 0, &pip);
1064 if (rval == MDI_SUCCESS) {
1065 mdi_pi_set_phci_private(pip, (caddr_t)d);
1066
1067 if (mdi_prop_update_string(pip, MDI_GUID, guid_ptr) !=
1068 DDI_SUCCESS) {
1069 dev_err(s->s_dip, CE_WARN,
1070 "unable to create property (MDI_GUID) for %s",
1071 guid_ptr);
1072 goto cleanup;
1073 }
1074
1075 /*
1076 * For MPxIO, we actually don't really need to care
1077 * about the LUN or target property, because nothing
1078 * really uses them.
1079 */
1080 if (mdi_prop_update_int64(pip, LUN64_PROP, d->pd_lun) !=
1081 DDI_SUCCESS) {
1082 dev_err(s->s_dip, CE_WARN,
1083 "unable to create property (%s) for %s",
1084 LUN64_PROP, guid_ptr);
1085 goto cleanup;
1086 }
1087
1088 if (mdi_prop_update_string_array(pip, COMPAT_PROP,
1089 compatible, ncompatible) != DDI_SUCCESS) {
1090 dev_err(s->s_dip, CE_WARN,
1091 "unable to create property (%s) for %s",
1092 COMPAT_PROP, guid_ptr);
1093 goto cleanup;
1094 }
1095
1096 if (mdi_pi_online(pip, 0) == MDI_NOT_SUPPORTED)
1097 goto cleanup;
1098
1099 d->pd_dip = NULL;
1100 d->pd_pip = pip;
1101 }
1102
1103 scsi_hba_nodename_compatible_free(nodename, compatible);
1104 if (childp != NULL)
1105 *childp = mdi_pi_get_client(pip);
1106 return (B_TRUE);
1107 cleanup:
1108 scsi_hba_nodename_compatible_free(nodename, compatible);
1109 d->pd_pip = NULL;
1110 d->pd_dip = NULL;
1111 (void) mdi_prop_remove(pip, NULL);
1112 (void) mdi_pi_free(pip, 0);
1113 return (B_FALSE);
1114 }
1115
1116 static int
1117 config_one(dev_info_t *pdip, pqi_state_t *s, pqi_device_t *d,
1118 dev_info_t **childp)
1119 {
1120 struct scsi_inquiry inq;
1121 boolean_t rval = B_FALSE;
1122
1123 /* ---- Inquiry target ---- */
1124 if (!d->pd_online ||
1125 pqi_scsi_inquiry(s, d, 0, &inq, sizeof (inq)) == B_FALSE) {
1126 pqi_fail_drive_cmds(d, CMD_DEV_GONE);
1127
1128 if (d->pd_dip != NULL) {
1129 (void) ndi_devi_offline(d->pd_dip,
1130 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
1131 d->pd_dip = NULL;
1132 } else if (d->pd_pip != NULL) {
1133 (void) mdi_pi_offline(d->pd_pip, 0);
1134 d->pd_pip_offlined = d->pd_pip;
1135 d->pd_pip = NULL;
1136 }
1137 return (NDI_FAILURE);
1138 } else if (d->pd_dip != NULL) {
1139 if (childp != NULL)
1140 *childp = d->pd_dip;
1141 return (NDI_SUCCESS);
1142 } else if (d->pd_pip != NULL) {
1143 if (childp != NULL)
1144 *childp = mdi_pi_get_client(d->pd_pip);
1145 return (NDI_SUCCESS);
1146 }
1147
1148 d->pd_parent = pdip;
1149 if ((!s->s_disable_mpxio) && is_physical_dev(d))
1150 rval = create_virt_lun(s, d, &inq, childp);
1151
1152 if (rval == B_FALSE)
1153 rval = create_phys_lun(s, d, &inq, childp);
1154
1155 return ((rval == B_TRUE) ? NDI_SUCCESS : NDI_FAILURE);
1156 }
1157
1158 static void
1159 cmd_ext_free(pqi_cmd_t *cmd)
1160 {
1161 struct scsi_pkt *pkt = CMD2PKT(cmd);
1162
1163 if ((cmd->pc_flags & PQI_FLAG_CDB_EXT) != 0) {
1164 kmem_free(pkt->pkt_cdbp, cmd->pc_cmdlen);
1165 cmd->pc_flags &= ~PQI_FLAG_CDB_EXT;
1166 }
1167 if ((cmd->pc_flags & PQI_FLAG_SCB_EXT) != 0) {
1168 kmem_free(pkt->pkt_scbp, cmd->pc_statuslen);
1169 cmd->pc_flags &= ~PQI_FLAG_SCB_EXT;
1170 }
1171 if ((cmd->pc_flags & PQI_FLAG_PRIV_EXT) != 0) {
1172 kmem_free(pkt->pkt_private, cmd->pc_tgtlen);
1173 cmd->pc_flags &= ~PQI_FLAG_PRIV_EXT;
1174 }
1175 }
1176
1177 static int
1178 cmd_ext_alloc(pqi_cmd_t *cmd, int kf)
1179 {
1180 struct scsi_pkt *pkt = CMD2PKT(cmd);
1181 void *buf;
1182
1183 if (cmd->pc_cmdlen > sizeof (cmd->pc_cdb)) {
1184 if ((buf = kmem_zalloc(cmd->pc_cmdlen, kf)) == NULL)
1185 return (DDI_FAILURE);
1186 pkt->pkt_cdbp = buf;
1187 cmd->pc_flags |= PQI_FLAG_CDB_EXT;
1188 }
1189
1190 if (cmd->pc_statuslen > sizeof (cmd->pc_cmd_scb)) {
1191 if ((buf = kmem_zalloc(cmd->pc_statuslen, kf)) == NULL)
1192 goto out;
1193 pkt->pkt_scbp = buf;
1194 cmd->pc_flags |= PQI_FLAG_SCB_EXT;
1195 }
1196
1197 if (cmd->pc_tgtlen > sizeof (cmd->pc_tgt_priv)) {
1198 if ((buf = kmem_zalloc(cmd->pc_tgtlen, kf)) == NULL)
1199 goto out;
1200 pkt->pkt_private = buf;
1201 cmd->pc_flags |= PQI_FLAG_PRIV_EXT;
1202 }
1203
1204 return (DDI_SUCCESS);
1205
1206 out:
1207 cmd_ext_free(cmd);
1208
1209 return (DDI_FAILURE);
1210 }
1211
1212 static boolean_t
1213 is_physical_dev(pqi_device_t *d)
1214 {
1215 return (d->pd_phys_dev ? B_TRUE : B_FALSE);
1216 }
1217