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 2016 Nexenta Systems, Inc.
14  * Copyright 2022 RackTop Systems, Inc.
15  */
16 
17 #include <sys/atomic.h>
18 #include <sys/cmn_err.h>
19 #include <sys/cpuvar.h>
20 #include <sys/ddi.h>
21 #include <sys/id32.h>
22 #include <sys/kmem.h>
23 #include <sys/list.h>
24 #include <sys/modctl.h>
25 #include <sys/pci.h>
26 #include <sys/scsi/scsi.h>
27 #include <sys/sunddi.h>
28 #include <sys/sysmacros.h>
29 #include <sys/types.h>
30 #include <sys/note.h>
31 
32 #include "pvscsi.h"
33 #include "pvscsi_var.h"
34 
35 /* we can support any of the interrupt types */
36 int pvscsi_intr_types = \
37 	DDI_INTR_TYPE_MSIX|DDI_INTR_TYPE_MSI|DDI_INTR_TYPE_FIXED;
38 int pvscsi_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_PER_RING;
39 int pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
40 static int pvscsi_hz;
41 
42 static int pvscsi_abort(struct scsi_address *, struct scsi_pkt *);
43 static void pvscsi_timeout(void *);
44 static void pvscsi_setup_rings(pvscsi_softc_t *);
45 static void pvscsi_complete_cmds(pvscsi_softc_t *, pvscsi_cmd_t *);
46 static boolean_t pvscsi_cmd_init(pvscsi_softc_t *, pvscsi_cmd_t *, int);
47 static void pvscsi_cmd_fini(pvscsi_cmd_t *);
48 
49 /* HBA DMA attributes */
50 static ddi_dma_attr_t pvscsi_dma_attr = {
51 	.dma_attr_version =	DMA_ATTR_V0,
52 	.dma_attr_addr_lo =	0,
53 	.dma_attr_addr_hi =	0xFFFFFFFFFFFFFFFFull,
54 	.dma_attr_count_max =	0xFFFFFFFFFFFFFFFFull,
55 	.dma_attr_align =	PAGE_SIZE,
56 	.dma_attr_burstsizes =	1,
57 	.dma_attr_minxfer =	1,
58 	.dma_attr_maxxfer =	0xFFFFFFFFFFFFFFFFull,
59 	.dma_attr_seg =		0xFFFFFFFFFFFFFFFFull,
60 	.dma_attr_sgllen =	1,
61 	.dma_attr_granular =	1,
62 	.dma_attr_flags =	0
63 };
64 
65 /* DMA attributes for buffer I/O */
66 static ddi_dma_attr_t pvscsi_io_dma_attr = {
67 	.dma_attr_version =	DMA_ATTR_V0,
68 	.dma_attr_addr_lo =	0,
69 	.dma_attr_addr_hi =	0xFFFFFFFFFFFFFFFFull,
70 	.dma_attr_count_max =	0x7FFFFFFFll,
71 	.dma_attr_align =	1,
72 	.dma_attr_burstsizes =	1,
73 	.dma_attr_minxfer =	1,
74 	.dma_attr_maxxfer =	PAGE_SIZE * PVSCSI_MAX_SG_SIZE,
75 	.dma_attr_seg =		0xFFFFFFFFFFFFFFFFull,
76 	.dma_attr_sgllen =	PVSCSI_MAX_SG_SIZE,
77 	.dma_attr_granular =	1,
78 	.dma_attr_flags =	0
79 };
80 
81 /*
82  * The structures are always little endian (VMware only runs
83  * on little endian CPUs), but we only run on LE processors,
84  * and NEVERSWAP avoids needing to use DDI accessor functions.
85  * (It would be incredibly bizarre to have a VMware guest running
86  * with a different endianness than the hypervisor.)
87  */
88 static ddi_device_acc_attr_t pvscsi_mmio_attr = {
89 	.devacc_attr_version =		DDI_DEVICE_ATTR_V1,
90 	.devacc_attr_endian_flags =	DDI_NEVERSWAP_ACC,
91 	.devacc_attr_dataorder =	DDI_STRICTORDER_ACC,
92 	.devacc_attr_access =		DDI_DEFAULT_ACC
93 };
94 
95 static ddi_device_acc_attr_t pvscsi_dma_attrs = {
96 	.devacc_attr_version =		DDI_DEVICE_ATTR_V1,
97 	.devacc_attr_endian_flags =	DDI_NEVERSWAP_ACC,
98 	.devacc_attr_dataorder =	DDI_STRICTORDER_ACC,
99 	.devacc_attr_access =		DDI_DEFAULT_ACC,
100 };
101 
102 static void
pvscsi_add_to_queue(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)103 pvscsi_add_to_queue(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
104 {
105 	pvscsi_cmd_t	*r;
106 	list_t		*l;
107 
108 	/*
109 	 * We insert in order of expiration, with the earliest
110 	 * expirations at the front.  This logic assumes that most
111 	 * commands will have the same timeout, and is optimized
112 	 * to minimize walking the list.  It allows timeouts to
113 	 * run without looking at more than one node that has not
114 	 * yet expired.
115 	 */
116 	ASSERT(mutex_owned(&pvs->lock));
117 
118 	l = &pvs->cmd_queue;
119 	for (r = list_tail(l); r != NULL; r = list_prev(l, r)) {
120 		/* this subtraction is safe if lbolt wraps */
121 		if (((cmd->start + cmd->timeout) -
122 		    (r->start + r->timeout)) >= 0) {
123 			list_insert_after(l, r, cmd);
124 			return;
125 		}
126 	}
127 
128 	list_insert_head(l, cmd);
129 }
130 
131 static uint32_t
pvscsi_reg_read(pvscsi_softc_t * pvs,uint32_t offset)132 pvscsi_reg_read(pvscsi_softc_t *pvs, uint32_t offset)
133 {
134 	uint32_t	ret;
135 
136 	ASSERT((offset & (sizeof (uint32_t) - 1)) == 0);
137 
138 	ret = ddi_get32(pvs->mmio_handle,
139 	    (uint32_t *)(pvs->mmio_base + offset));
140 
141 	return (ret);
142 }
143 
144 static void
pvscsi_reg_write(pvscsi_softc_t * pvs,uint32_t offset,uint32_t value)145 pvscsi_reg_write(pvscsi_softc_t *pvs, uint32_t offset, uint32_t value)
146 {
147 	ASSERT((offset & (sizeof (uint32_t) - 1)) == 0);
148 
149 	ddi_put32(pvs->mmio_handle, (uint32_t *)(pvs->mmio_base + offset),
150 	    value);
151 }
152 
153 static void
pvscsi_write_cmd_desc(pvscsi_softc_t * pvs,uint32_t cmd,void * desc,size_t len)154 pvscsi_write_cmd_desc(pvscsi_softc_t *pvs, uint32_t cmd, void *desc, size_t len)
155 {
156 	len /= sizeof (uint32_t);
157 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_COMMAND, cmd);
158 	ddi_rep_put32(pvs->mmio_handle, (uint32_t *)desc,
159 	    (uint32_t *)(pvs->mmio_base + PVSCSI_REG_OFFSET_COMMAND_DATA),
160 	    len, DDI_DEV_NO_AUTOINCR);
161 }
162 
163 static uint32_t
pvscsi_read_intr_status(pvscsi_softc_t * pvs)164 pvscsi_read_intr_status(pvscsi_softc_t *pvs)
165 {
166 	return (pvscsi_reg_read(pvs, PVSCSI_REG_OFFSET_INTR_STATUS));
167 }
168 
169 static void
pvscsi_write_intr_status(pvscsi_softc_t * pvs,uint32_t val)170 pvscsi_write_intr_status(pvscsi_softc_t *pvs, uint32_t val)
171 {
172 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_STATUS, val);
173 }
174 
175 static pvscsi_cmd_t *
pvscsi_reclaim_cmds(pvscsi_softc_t * pvs)176 pvscsi_reclaim_cmds(pvscsi_softc_t *pvs)
177 {
178 	pvscsi_cmd_t	*head = NULL;
179 	pvscsi_cmd_t	**tail = &head;
180 	pvscsi_cmd_t	*cmd;
181 
182 	ASSERT(mutex_owned(&pvs->lock));
183 	while ((cmd = list_remove_head(&pvs->cmd_queue)) != NULL) {
184 		list_remove(&pvs->cmd_queue, cmd);
185 		*tail = cmd;
186 		tail = &cmd->next_cmd;
187 		*tail = NULL;
188 		cmd->host_status = BTSTAT_BUSRESET;
189 	}
190 	return (head);
191 }
192 
193 static void
pvscsi_stop_hba(pvscsi_softc_t * pvs)194 pvscsi_stop_hba(pvscsi_softc_t *pvs)
195 {
196 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
197 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK, 0);
198 	/* read interrupt status to flush PCI write buffers */
199 	(void) pvscsi_read_intr_status(pvs);
200 }
201 
202 static void
pvscsi_start_hba(pvscsi_softc_t * pvs)203 pvscsi_start_hba(pvscsi_softc_t *pvs)
204 {
205 	pvscsi_setup_rings(pvs);
206 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_INTR_MASK,
207 	    PVSCSI_INTR_CMPL_MASK | PVSCSI_INTR_MSG_MASK);
208 }
209 
210 static void
pvscsi_reset_bus(pvscsi_softc_t * pvs)211 pvscsi_reset_bus(pvscsi_softc_t *pvs)
212 {
213 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_RESET_BUS, NULL, 0);
214 }
215 
216 /*
217  * pvscsi_restart_hba resets the HBA, and reconfigures it.  It also
218  * completes all commands that have not been already completed with
219  * a reset.
220  */
221 static void
pvscsi_restart_hba(pvscsi_softc_t * pvs)222 pvscsi_restart_hba(pvscsi_softc_t *pvs)
223 {
224 	pvscsi_cmd_t	*cmd;
225 
226 	mutex_enter(&pvs->lock);
227 	pvscsi_stop_hba(pvs);
228 	cmd = pvscsi_reclaim_cmds(pvs);
229 	pvscsi_start_hba(pvs);
230 	mutex_exit(&pvs->lock);
231 
232 	/* run the completions from the reclaimed commands */
233 	pvscsi_complete_cmds(pvs, cmd);
234 }
235 
236 static void
pvscsi_submit_nonrw_io(pvscsi_softc_t * pvs)237 pvscsi_submit_nonrw_io(pvscsi_softc_t *pvs)
238 {
239 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_KICK_NON_RW_IO, 0);
240 }
241 
242 static void
pvscsi_submit_rw_io(pvscsi_softc_t * pvs)243 pvscsi_submit_rw_io(pvscsi_softc_t *pvs)
244 {
245 	pvscsi_reg_write(pvs, PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
246 }
247 
248 static pvscsi_cmd_t *
pvscsi_process_comp_ring(pvscsi_softc_t * pvs)249 pvscsi_process_comp_ring(pvscsi_softc_t *pvs)
250 {
251 	pvscsi_cmd_t	**pnext_cmd;
252 	pvscsi_cmd_t	*cmd;
253 	pvscsi_cmd_t	*head = NULL;
254 	struct PVSCSIRingsState *sdesc = RINGS_STATE(pvs);
255 	uint32_t	cmp_ne = sdesc->cmpNumEntriesLog2;
256 
257 	ASSERT(mutex_owned(&pvs->lock));
258 
259 	pnext_cmd = &head;
260 
261 	(void) ddi_dma_sync(pvs->state_buf.dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
262 
263 	while (sdesc->cmpConsIdx != sdesc->cmpProdIdx) {
264 		struct PVSCSIRingCmpDesc *cdesc;
265 
266 		(void) ddi_dma_sync(pvs->cmp_ring_buf.dmah, 0, 0,
267 		    DDI_DMA_SYNC_FORKERNEL);
268 
269 		cdesc = CMP_RING(pvs) + (sdesc->cmpConsIdx & MASK(cmp_ne));
270 
271 		if ((cmd = id32_lookup((uint32_t)cdesc->context)) != NULL) {
272 			cmd->next_cmd = NULL;
273 
274 			/* Save command status for further processing */
275 			cmd->host_status = cdesc->hostStatus;
276 			cmd->scsi_status = cdesc->scsiStatus;
277 			cmd->transferred = cdesc->dataLen;
278 
279 			*pnext_cmd = cmd;
280 			pnext_cmd = &cmd->next_cmd;
281 
282 			list_remove(&pvs->cmd_queue, cmd);
283 		}
284 
285 		sdesc->cmpConsIdx++;
286 	}
287 	(void) ddi_dma_sync(pvs->state_buf.dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
288 
289 	return (head);
290 }
291 
292 static pvscsi_msg_t *
pvscsi_process_msg_ring(pvscsi_softc_t * pvs)293 pvscsi_process_msg_ring(pvscsi_softc_t *pvs)
294 {
295 	pvscsi_msg_t	*msg;
296 	struct PVSCSIRingsState *sdesc = RINGS_STATE(pvs);
297 	struct PVSCSIRingMsgDesc *mdesc;
298 	struct PVSCSIMsgDescDevStatusChanged *desc;
299 	uint32_t	msg_ne = sdesc->msgNumEntriesLog2;
300 
301 	(void) ddi_dma_sync(pvs->state_buf.dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
302 
303 	if (sdesc->msgProdIdx == sdesc->msgConsIdx) {
304 		return (NULL);
305 	}
306 
307 	(void) ddi_dma_sync(pvs->msg_ring_buf.dmah, 0, 0,
308 	    DDI_DMA_SYNC_FORKERNEL);
309 
310 	mdesc = MSG_RING(pvs) + (sdesc->msgConsIdx & MASK(msg_ne));
311 
312 	switch (mdesc->type) {
313 	case PVSCSI_MSG_DEV_ADDED:
314 	case PVSCSI_MSG_DEV_REMOVED:
315 		desc = (struct PVSCSIMsgDescDevStatusChanged *)mdesc;
316 		msg = kmem_alloc(sizeof (pvscsi_msg_t), KM_NOSLEEP);
317 		if (msg == NULL)
318 			return (NULL);
319 		msg->pvs = pvs;
320 		msg->type = mdesc->type;
321 		msg->target = desc->target;
322 		msg->lun = desc->lun[1]; /* T10 format */
323 		break;
324 	default:
325 		dev_err(pvs->dip, CE_WARN, "!unknown msg type: %d",
326 		    mdesc->type);
327 		return (NULL);
328 	}
329 
330 	sdesc->msgConsIdx++;
331 	(void) ddi_dma_sync(pvs->state_buf.dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
332 	return (msg);
333 }
334 
335 static void
pvscsi_handle_msg(void * arg)336 pvscsi_handle_msg(void *arg)
337 {
338 	pvscsi_msg_t	*msg = arg;
339 	pvscsi_softc_t	*pvs = msg->pvs;
340 	char		addr[8];
341 
342 	(void) snprintf(addr, sizeof (addr), "%x", msg->target);
343 
344 	if (msg->lun == 0) {
345 		switch (msg->type) {
346 		case PVSCSI_MSG_DEV_ADDED:
347 			(void) scsi_hba_tgtmap_tgt_add(pvs->tgtmap,
348 			    SCSI_TGT_SCSI_DEVICE, addr, NULL);
349 			break;
350 		case PVSCSI_MSG_DEV_REMOVED:
351 			(void) scsi_hba_tgtmap_tgt_remove(pvs->tgtmap,
352 			    SCSI_TGT_SCSI_DEVICE, addr);
353 			break;
354 		}
355 	} else {
356 		scsi_hba_tgtmap_scan_luns(pvs->tgtmap, addr);
357 	}
358 	kmem_free(msg, sizeof (pvscsi_msg_t));
359 }
360 
361 static void
pvscsi_abort_cmd(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)362 pvscsi_abort_cmd(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
363 {
364 	struct PVSCSICmdDescAbortCmd	acmd;
365 
366 	bzero(&acmd, sizeof (acmd));
367 	acmd.target = cmd->target;
368 	acmd.context = cmd->ctx;
369 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_ABORT_CMD, &acmd, sizeof (acmd));
370 }
371 
372 static void
pvscsi_map_buffers(pvscsi_cmd_t * cmd,struct PVSCSIRingReqDesc * rdesc)373 pvscsi_map_buffers(pvscsi_cmd_t *cmd, struct PVSCSIRingReqDesc *rdesc)
374 {
375 	struct scsi_pkt *pkt = cmd->pkt;
376 
377 	rdesc->dataLen = 0;
378 	rdesc->dataAddr = 0;
379 	if (pkt == NULL || pkt->pkt_numcookies == 0) {
380 		return;
381 	}
382 
383 	pkt->pkt_resid = 0;
384 
385 	if (pkt->pkt_numcookies > 1) {
386 		size_t	len = 0;
387 		struct PVSCSISGElement *sgl = cmd->sgl;
388 
389 		for (uint_t i = 0; i < pkt->pkt_numcookies; i++) {
390 			sgl[i].addr = pkt->pkt_cookies[i].dmac_laddress;
391 			sgl[i].length = pkt->pkt_cookies[i].dmac_size;
392 			sgl[i].flags = 0;
393 			len += pkt->pkt_cookies[i].dmac_size;
394 		}
395 		rdesc->flags |= PVSCSI_FLAG_CMD_WITH_SG_LIST;
396 		rdesc->dataAddr = cmd->sgl_pa;
397 		rdesc->dataLen = len;
398 		(void) ddi_dma_sync(cmd->sgl_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
399 	} else {
400 		rdesc->flags = 0;
401 		rdesc->dataAddr = pkt->pkt_cookies[0].dmac_laddress;
402 		rdesc->dataLen = pkt->pkt_cookies[0].dmac_size;
403 	}
404 	pkt->pkt_resid = rdesc->dataLen;
405 }
406 
407 static void
pvscsi_comp_cmd(pvscsi_cmd_t * cmd)408 pvscsi_comp_cmd(pvscsi_cmd_t *cmd)
409 {
410 	struct scsi_pkt	*pkt = cmd->pkt;
411 	uint8_t		status = cmd->scsi_status;
412 
413 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
414 	    STATE_GOT_STATUS);
415 	if (pkt->pkt_numcookies > 0) {
416 		pkt->pkt_state |= STATE_XFERRED_DATA;
417 	}
418 	pkt->pkt_reason = CMD_CMPLT;
419 	pkt->pkt_resid -= cmd->transferred;
420 	*(pkt->pkt_scbp) = status;
421 
422 	if (status == STATUS_CHECK) {
423 		/*
424 		 * Our virtual HBA *always* does ARQ, and it never
425 		 * is more than 20 bytes, so no need to try to handle
426 		 * extended versions of it.
427 		 */
428 		struct scsi_arq_status *ars = (void *)(pkt->pkt_scbp);
429 		int		len = min(pkt->pkt_scblen, SENSE_LENGTH);
430 
431 		pkt->pkt_state |= STATE_ARQ_DONE;
432 		ars->sts_rqpkt_resid = 0;
433 		bcopy(cmd->arq_sense, &ars->sts_sensedata, len);
434 		ars->sts_rqpkt_reason = CMD_CMPLT;
435 		*(uint8_t *)&ars->sts_rqpkt_status = STATUS_GOOD;
436 		ars->sts_rqpkt_state = STATE_GOT_BUS |
437 		    STATE_GOT_TARGET | STATE_SENT_CMD |
438 		    STATE_XFERRED_DATA | STATE_GOT_STATUS;
439 	}
440 }
441 
442 static void
pvscsi_set_status(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)443 pvscsi_set_status(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
444 {
445 	struct scsi_pkt	*pkt = cmd->pkt;
446 	uint32_t	host_status = cmd->host_status;
447 
448 	switch (host_status) {
449 	case BTSTAT_SUCCESS:
450 	case BTSTAT_LINKED_COMMAND_COMPLETED:
451 	case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
452 		pvscsi_comp_cmd(cmd);
453 		break;
454 	case BTSTAT_DATARUN:
455 		pkt->pkt_reason = CMD_DATA_OVR;
456 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
457 		    STATE_SENT_CMD | STATE_GOT_STATUS |
458 		    STATE_XFERRED_DATA);
459 		pkt->pkt_resid -= cmd->transferred;
460 		break;
461 	case BTSTAT_SELTIMEO:
462 		pkt->pkt_reason = CMD_DEV_GONE;
463 		pkt->pkt_state |= STATE_GOT_BUS;
464 		break;
465 	case BTSTAT_TAGREJECT:
466 		pkt->pkt_reason = CMD_TAG_REJECT;
467 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
468 		    STATE_SENT_CMD | STATE_GOT_STATUS);
469 		break;
470 	case BTSTAT_BADMSG:
471 		pkt->pkt_reason = CMD_BADMSG;
472 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
473 		    STATE_SENT_CMD | STATE_GOT_STATUS);
474 		break;
475 	case BTSTAT_SENTRST:
476 	case BTSTAT_RECVRST:
477 		pkt->pkt_reason = CMD_RESET;
478 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
479 		    STATE_SENT_CMD | STATE_GOT_STATUS);
480 		pkt->pkt_statistics |= STAT_DEV_RESET;
481 		pkt->pkt_resid -= cmd->transferred;
482 		break;
483 	case BTSTAT_BUSRESET:
484 		pkt->pkt_reason = CMD_RESET;
485 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
486 		    STATE_SENT_CMD | STATE_GOT_STATUS);
487 		pkt->pkt_statistics |= STAT_BUS_RESET;
488 		pkt->pkt_resid -= cmd->transferred;
489 		break;
490 	case BTSTAT_ABORTQUEUE:
491 		if (cmd->expired) {
492 			pkt->pkt_reason = CMD_TIMEOUT;
493 			pkt->pkt_statistics |= STAT_TIMEOUT;
494 		} else {
495 			pkt->pkt_reason = CMD_ABORTED;
496 			pkt->pkt_statistics |= STAT_ABORTED;
497 		}
498 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
499 		    STATE_SENT_CMD | STATE_GOT_STATUS);
500 		pkt->pkt_resid -= cmd->transferred;
501 		break;
502 	case BTSTAT_HAHARDWARE:
503 	case BTSTAT_INVPHASE:
504 	case BTSTAT_HATIMEOUT:
505 	case BTSTAT_NORESPONSE:
506 	case BTSTAT_DISCONNECT:
507 	case BTSTAT_HASOFTWARE:
508 	case BTSTAT_BUSFREE:
509 	case BTSTAT_SENSFAILED:
510 	case BTSTAT_DATA_UNDERRUN:
511 		pkt->pkt_reason = CMD_TRAN_ERR;
512 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
513 		    STATE_SENT_CMD | STATE_GOT_STATUS);
514 		pkt->pkt_resid -= cmd->transferred;
515 		break;
516 	default:
517 		dev_err(pvs->dip, CE_WARN,
518 		    "!unknown host status code: %d", host_status);
519 		pkt->pkt_reason = CMD_TRAN_ERR;
520 		pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
521 		    STATE_SENT_CMD | STATE_GOT_STATUS);
522 		break;
523 	}
524 }
525 
526 /*
527  * pvscsi_complete_cmds processes a linked list of
528  * commands that have been completed.  This is done
529  * without acquiring any locks.
530  */
531 static void
pvscsi_complete_cmds(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)532 pvscsi_complete_cmds(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
533 {
534 	struct scsi_pkt	*pkt;
535 
536 	while (cmd != NULL) {
537 		pvscsi_cmd_t	*next = cmd->next_cmd;
538 
539 		cmd->next_cmd = NULL;
540 
541 		if (((pkt = cmd->pkt) == NULL) || (cmd->poll)) {
542 			atomic_or_8(&cmd->done, 1);
543 		} else {
544 			pvscsi_set_status(pvs, cmd);
545 			scsi_hba_pkt_comp(pkt);
546 		}
547 
548 		cmd = next;
549 	}
550 }
551 
552 static void
pvscsi_dev_reset(pvscsi_softc_t * pvs,int target,int lun)553 pvscsi_dev_reset(pvscsi_softc_t *pvs, int target, int lun)
554 {
555 	struct PVSCSICmdDescResetDevice cmd = { 0 };
556 
557 	cmd.target = target;
558 	cmd.lun[1] = lun & 0xff;
559 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_RESET_DEVICE, &cmd, sizeof (cmd));
560 }
561 
562 static boolean_t
pvscsi_poll_cmd_until(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd,clock_t usec)563 pvscsi_poll_cmd_until(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd, clock_t usec)
564 {
565 	while (usec > 0) {
566 		pvscsi_cmd_t	*done;
567 		if (cmd->done) {
568 			return (B_TRUE);
569 		}
570 		mutex_enter(&pvs->lock);
571 		done = pvscsi_process_comp_ring(pvs);
572 		mutex_exit(&pvs->lock);
573 
574 		pvscsi_complete_cmds(pvs, done);
575 		drv_usecwait(10);
576 		usec -= 10;
577 	}
578 
579 	return (B_FALSE);
580 }
581 
582 static void
pvscsi_poll_cmd(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)583 pvscsi_poll_cmd(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
584 {
585 	if (pvscsi_poll_cmd_until(pvs, cmd, drv_hztousec(cmd->timeout))) {
586 		return;
587 	}
588 
589 	/* now we try an abort first */
590 	pvscsi_abort_cmd(pvs, cmd);
591 	if (pvscsi_poll_cmd_until(pvs, cmd, 2)) {
592 		return;
593 	}
594 	/* well that failed... try reset */
595 	pvscsi_dev_reset(pvs, cmd->target, cmd->lun);
596 	if (pvscsi_poll_cmd_until(pvs, cmd, 2)) {
597 		return;
598 	}
599 	/* still trying... reset the bus */
600 	pvscsi_reset_bus(pvs);
601 	if (pvscsi_poll_cmd_until(pvs, cmd, 2)) {
602 		return;
603 	}
604 	/* full up adapter reset -- be brutal */
605 	pvscsi_restart_hba(pvs);
606 }
607 
608 static void
pvscsi_abort_all(pvscsi_softc_t * pvs,pvscsi_device_t * pd)609 pvscsi_abort_all(pvscsi_softc_t *pvs, pvscsi_device_t *pd)
610 {
611 	pvscsi_cmd_t	*cmd;
612 
613 	mutex_enter(&pvs->lock);
614 	list_t *l = &pvs->cmd_queue;
615 	for (cmd = list_head(l); cmd != NULL; cmd = list_next(l, cmd)) {
616 		if ((pd->target == cmd->target) && (pd->lun == cmd->lun)) {
617 			pvscsi_abort_cmd(pvs, cmd);
618 		}
619 	}
620 	mutex_exit(&pvs->lock);
621 }
622 
623 static int
pvscsi_transport_command(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd)624 pvscsi_transport_command(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
625 {
626 	struct PVSCSIRingReqDesc	*rdesc;
627 	struct PVSCSIRingsState		*sdesc = RINGS_STATE(pvs);
628 	uint32_t			req_ne = sdesc->reqNumEntriesLog2;
629 
630 	cmd->done = 0;
631 	cmd->expired = 0;
632 
633 	mutex_enter(&pvs->lock);
634 
635 	if ((sdesc->reqProdIdx - sdesc->cmpConsIdx) >= (1 << req_ne)) {
636 		mutex_exit(&pvs->lock);
637 		return (TRAN_BUSY);
638 	}
639 
640 	rdesc = REQ_RING(pvs) + (sdesc->reqProdIdx & MASK(req_ne));
641 
642 	rdesc->bus = 0;
643 	rdesc->target = cmd->target;
644 	bzero(rdesc->lun, sizeof (rdesc->lun));
645 	/* Matches other implementations; can pvscsi support luns > 255? */
646 	rdesc->lun[1] = cmd->lun & 0xff;
647 
648 	bzero(cmd->arq_sense, sizeof (cmd->arq_sense));
649 	rdesc->context = cmd->ctx;
650 	rdesc->senseLen = sizeof (cmd->arq_sense);
651 	rdesc->senseAddr = cmd->arq_pa;
652 	rdesc->tag = cmd->tag;
653 	rdesc->vcpuHint = CPU->cpu_id;
654 	rdesc->cdbLen = cmd->cdblen;
655 	rdesc->flags = cmd->dma_dir;
656 	bcopy(cmd->cdb, rdesc->cdb, cmd->cdblen);
657 	pvscsi_map_buffers(cmd, rdesc);
658 
659 	(void) ddi_dma_sync(pvs->req_ring_buf.dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
660 
661 	sdesc->reqProdIdx++;
662 	(void) ddi_dma_sync(pvs->state_buf.dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
663 
664 	pvscsi_add_to_queue(pvs, cmd);
665 
666 	switch (cmd->cdb[0]) {
667 	case SCMD_READ:
668 	case SCMD_WRITE:
669 	case SCMD_READ_G1:
670 	case SCMD_WRITE_G1:
671 	case SCMD_READ_G4:
672 	case SCMD_WRITE_G4:
673 	case SCMD_READ_G5:
674 	case SCMD_WRITE_G5:
675 		pvscsi_submit_rw_io(pvs);
676 		break;
677 	default:
678 		pvscsi_submit_nonrw_io(pvs);
679 		break;
680 	}
681 
682 	if (pvs->timeout == 0) {
683 		/* drivers above should supply, but give a default */
684 		pvs->timeout = timeout(pvscsi_timeout, pvs, pvscsi_hz * 8);
685 	}
686 	mutex_exit(&pvs->lock);
687 
688 	return (TRAN_ACCEPT);
689 }
690 
691 static int
pvscsi_setup_dma_buffer(pvscsi_softc_t * pvs,size_t length,pvscsi_dma_buf_t * buf)692 pvscsi_setup_dma_buffer(pvscsi_softc_t *pvs, size_t length,
693     pvscsi_dma_buf_t *buf)
694 {
695 	if ((ddi_dma_alloc_handle(pvs->dip, &pvscsi_dma_attr,
696 	    DDI_DMA_SLEEP, NULL, &buf->dmah)) != DDI_SUCCESS) {
697 		dev_err(pvs->dip, CE_WARN, "!failed to alloc DMA handle");
698 		return (DDI_FAILURE);
699 	}
700 
701 	if ((ddi_dma_mem_alloc(buf->dmah, length, &pvscsi_dma_attrs,
702 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &buf->addr,
703 	    &length, &buf->acch)) != DDI_SUCCESS) {
704 		dev_err(pvs->dip, CE_WARN, "!failed to alloc DMA memory");
705 		return (DDI_FAILURE);
706 	}
707 
708 	if ((ddi_dma_addr_bind_handle(buf->dmah, NULL, buf->addr,
709 	    length, DDI_DMA_CONSISTENT | DDI_DMA_RDWR, DDI_DMA_SLEEP,
710 	    NULL, NULL, NULL)) != DDI_SUCCESS) {
711 		dev_err(pvs->dip, CE_WARN, "!failed to bind DMA buffer");
712 		return (DDI_FAILURE);
713 	}
714 
715 	buf->pa = ddi_dma_cookie_one(buf->dmah)->dmac_laddress;
716 
717 	return (DDI_SUCCESS);
718 }
719 
720 static void
pvscsi_free_dma_buffer(pvscsi_dma_buf_t * buf)721 pvscsi_free_dma_buffer(pvscsi_dma_buf_t *buf)
722 {
723 	if (buf->pa != 0) {
724 		(void) ddi_dma_unbind_handle(buf->dmah);
725 	}
726 	if (buf->acch != NULL) {
727 		ddi_dma_mem_free(&buf->acch);
728 	}
729 	if (buf->dmah != NULL) {
730 		ddi_dma_free_handle(&buf->dmah);
731 	}
732 }
733 
734 static int
pvscsi_allocate_rings(pvscsi_softc_t * pvs)735 pvscsi_allocate_rings(pvscsi_softc_t *pvs)
736 {
737 	/* allocate DMA buffer for rings state */
738 	if (pvscsi_setup_dma_buffer(pvs, PAGE_SIZE, &pvs->state_buf) !=
739 	    DDI_SUCCESS) {
740 		return (DDI_FAILURE);
741 	}
742 
743 	/* allocate DMA buffer for request ring */
744 	pvs->req_pages = MIN(pvscsi_ring_pages, PVSCSI_MAX_NUM_PAGES_REQ_RING);
745 	pvs->req_depth = pvs->req_pages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
746 	if (pvscsi_setup_dma_buffer(pvs, pvs->req_pages * PAGE_SIZE,
747 	    &pvs->req_ring_buf) != DDI_SUCCESS) {
748 		return (DDI_FAILURE);
749 	}
750 
751 	/* allocate completion ring */
752 	pvs->cmp_pages = MIN(pvscsi_ring_pages, PVSCSI_MAX_NUM_PAGES_CMP_RING);
753 	if (pvscsi_setup_dma_buffer(pvs, pvs->cmp_pages * PAGE_SIZE,
754 	    &pvs->cmp_ring_buf) != DDI_SUCCESS) {
755 		return (DDI_FAILURE);
756 	}
757 
758 	/* allocate message ring */
759 	pvs->msg_pages = MIN(pvscsi_msg_ring_pages,
760 	    PVSCSI_MAX_NUM_PAGES_MSG_RING);
761 	if (pvscsi_setup_dma_buffer(pvs, pvs->msg_pages * PAGE_SIZE,
762 	    &pvs->msg_ring_buf) != DDI_SUCCESS) {
763 		return (DDI_FAILURE);
764 	}
765 
766 	return (DDI_SUCCESS);
767 }
768 
769 static void
pvscsi_free_rings(pvscsi_softc_t * pvs)770 pvscsi_free_rings(pvscsi_softc_t *pvs)
771 {
772 	pvscsi_free_dma_buffer(&pvs->msg_ring_buf);
773 	pvscsi_free_dma_buffer(&pvs->cmp_ring_buf);
774 	pvscsi_free_dma_buffer(&pvs->req_ring_buf);
775 	pvscsi_free_dma_buffer(&pvs->state_buf);
776 }
777 
778 static void
pvscsi_setup_rings(pvscsi_softc_t * pvs)779 pvscsi_setup_rings(pvscsi_softc_t *pvs)
780 {
781 	int		i;
782 	struct PVSCSICmdDescSetupMsgRing cmd_msg = { 0 };
783 	struct PVSCSICmdDescSetupRings cmd = { 0 };
784 	uint64_t	base;
785 
786 	cmd.ringsStatePPN = pvs->state_buf.pa >> PAGE_SHIFT;
787 	cmd.reqRingNumPages = pvs->req_pages;
788 	cmd.cmpRingNumPages = pvs->cmp_pages;
789 
790 	/* Setup request ring */
791 	base = pvs->req_ring_buf.pa;
792 	for (i = 0; i < pvs->req_pages; i++) {
793 		cmd.reqRingPPNs[i] = base >> PAGE_SHIFT;
794 		base += PAGE_SIZE;
795 	}
796 
797 	/* Setup completion ring */
798 	base = pvs->cmp_ring_buf.pa;
799 	for (i = 0; i < pvs->cmp_pages; i++) {
800 		cmd.cmpRingPPNs[i] = base >> PAGE_SHIFT;
801 		base += PAGE_SIZE;
802 	}
803 
804 	bzero(RINGS_STATE(pvs), PAGE_SIZE);
805 	bzero(REQ_RING(pvs), pvs->req_pages * PAGE_SIZE);
806 	bzero(CMP_RING(pvs), pvs->cmp_pages * PAGE_SIZE);
807 
808 	/* Issue SETUP command */
809 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_SETUP_RINGS, &cmd, sizeof (cmd));
810 
811 	/* Setup message ring */
812 	cmd_msg.numPages = pvs->msg_pages;
813 	base = pvs->msg_ring_buf.pa;
814 
815 	for (i = 0; i < pvs->msg_pages; i++) {
816 		cmd_msg.ringPPNs[i] = base >> PAGE_SHIFT;
817 		base += PAGE_SIZE;
818 	}
819 	bzero(MSG_RING(pvs), pvs->msg_pages * PAGE_SIZE);
820 
821 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_SETUP_MSG_RING, &cmd_msg,
822 	    sizeof (cmd_msg));
823 }
824 
825 static int
pvscsi_setup_io(pvscsi_softc_t * pvs)826 pvscsi_setup_io(pvscsi_softc_t *pvs)
827 {
828 	int		offset, rcount, rn, type;
829 	int		ret = DDI_FAILURE;
830 	off_t		regsize;
831 	pci_regspec_t	*regs;
832 	uint_t		regs_length;
833 
834 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pvs->dip,
835 	    DDI_PROP_DONTPASS, "reg", (int **)&regs,
836 	    &regs_length) != DDI_PROP_SUCCESS) {
837 		dev_err(pvs->dip, CE_WARN, "!failed to lookup 'reg' property");
838 		return (DDI_FAILURE);
839 	}
840 
841 	rcount = regs_length * sizeof (int) / sizeof (pci_regspec_t);
842 
843 	for (offset = PCI_CONF_BASE0; offset <= PCI_CONF_BASE5; offset += 4) {
844 		for (rn = 0; rn < rcount; ++rn) {
845 			if (PCI_REG_REG_G(regs[rn].pci_phys_hi) == offset) {
846 				type = regs[rn].pci_phys_hi & PCI_ADDR_MASK;
847 				break;
848 			}
849 		}
850 
851 		if (rn >= rcount)
852 			continue;
853 
854 		if (type != PCI_ADDR_IO) {
855 			if (ddi_dev_regsize(pvs->dip, rn,
856 			    &regsize) != DDI_SUCCESS) {
857 				dev_err(pvs->dip, CE_WARN,
858 				    "!failed to get size of reg %d", rn);
859 				goto out;
860 			}
861 			if (regsize == PVSCSI_MEM_SPACE_SIZE) {
862 				if (ddi_regs_map_setup(pvs->dip, rn,
863 				    &pvs->mmio_base, 0, 0,
864 				    &pvscsi_mmio_attr,
865 				    &pvs->mmio_handle) != DDI_SUCCESS) {
866 					dev_err(pvs->dip, CE_WARN,
867 					    "!failed to map MMIO BAR");
868 					goto out;
869 				}
870 				ret = DDI_SUCCESS;
871 				break;
872 			}
873 		}
874 	}
875 
876 out:
877 	ddi_prop_free(regs);
878 
879 	return (ret);
880 }
881 
882 static int
pvscsi_enable_intrs(pvscsi_softc_t * pvs)883 pvscsi_enable_intrs(pvscsi_softc_t *pvs)
884 {
885 	int	i, rc, intr_caps;
886 
887 	if ((rc = ddi_intr_get_cap(pvs->intr_handles[0], &intr_caps)) !=
888 	    DDI_SUCCESS) {
889 		dev_err(pvs->dip, CE_WARN, "!failed to get interrupt caps");
890 		return (DDI_FAILURE);
891 	}
892 
893 	if ((intr_caps & DDI_INTR_FLAG_BLOCK) != 0) {
894 		if ((rc = ddi_intr_block_enable(pvs->intr_handles,
895 		    pvs->intr_cnt)) != DDI_SUCCESS) {
896 			dev_err(pvs->dip, CE_WARN,
897 			    "!failed to enable interrupt block");
898 		}
899 	} else {
900 		for (i = 0; i < pvs->intr_cnt; i++) {
901 			if ((rc = ddi_intr_enable(pvs->intr_handles[i])) ==
902 			    DDI_SUCCESS)
903 				continue;
904 			dev_err(pvs->dip, CE_WARN,
905 			    "!failed to enable interrupt");
906 			while (--i >= 0)
907 				(void) ddi_intr_disable(pvs->intr_handles[i]);
908 			break;
909 		}
910 	}
911 
912 	return (rc);
913 }
914 
915 static uint32_t
pvscsi_intr(caddr_t arg1,caddr_t arg2)916 pvscsi_intr(caddr_t arg1, caddr_t arg2)
917 {
918 	pvscsi_softc_t	*pvs = (pvscsi_softc_t *)arg1;
919 	uint32_t	status;
920 	pvscsi_cmd_t	*cmd;
921 	pvscsi_msg_t	*msg;
922 	uint32_t	rv = DDI_INTR_CLAIMED;
923 	_NOTE(ARGUNUSED(arg2));
924 
925 	mutex_enter(&pvs->lock);
926 	status = pvscsi_read_intr_status(pvs);
927 	if ((status & PVSCSI_INTR_ALL_SUPPORTED) != 0) {
928 		pvscsi_write_intr_status(pvs, status);
929 	} else if (pvs->intr_type == DDI_INTR_TYPE_FIXED) {
930 		rv = DDI_INTR_UNCLAIMED;
931 	}
932 	if (pvs->detach) {
933 		mutex_exit(&pvs->lock);
934 		return (rv);
935 	}
936 	cmd = pvscsi_process_comp_ring(pvs);
937 	msg = pvscsi_process_msg_ring(pvs);
938 
939 	/*
940 	 * Do this under the lock, so that we won't dispatch
941 	 * if we are detaching
942 	 */
943 	if (msg != NULL) {
944 		if (ddi_taskq_dispatch(pvs->tq, pvscsi_handle_msg, msg,
945 		    DDI_NOSLEEP) != DDI_SUCCESS) {
946 			dev_err(pvs->dip, CE_WARN,
947 			    "!failed to dispatch discovery");
948 		}
949 	}
950 	mutex_exit(&pvs->lock);
951 
952 	pvscsi_complete_cmds(pvs, cmd);
953 
954 	return (rv);
955 }
956 
957 static void
pvscsi_free_intrs(pvscsi_softc_t * pvs)958 pvscsi_free_intrs(pvscsi_softc_t *pvs)
959 {
960 	for (int i = 0; i < pvs->intr_cnt; i++) {
961 		(void) ddi_intr_disable(pvs->intr_handles[i]);
962 		(void) ddi_intr_remove_handler(pvs->intr_handles[i]);
963 		(void) ddi_intr_free(pvs->intr_handles[i]);
964 	}
965 	pvs->intr_cnt = 0;
966 }
967 
968 static int
pvscsi_register_isr(pvscsi_softc_t * pvs,int type)969 pvscsi_register_isr(pvscsi_softc_t *pvs, int type)
970 {
971 	int	navail, nactual;
972 	int	i;
973 
974 	if (ddi_intr_get_navail(pvs->dip, type, &navail) != DDI_SUCCESS ||
975 	    navail == 0) {
976 		dev_err(pvs->dip, CE_WARN,
977 		    "!failed to get number of available interrupts of type %d",
978 		    type);
979 		return (DDI_FAILURE);
980 	}
981 	navail = MIN(navail, PVSCSI_MAX_INTRS);
982 
983 	if (ddi_intr_alloc(pvs->dip, pvs->intr_handles, type, 0, navail,
984 	    &nactual, DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS || nactual == 0) {
985 		dev_err(pvs->dip, CE_WARN, "!failed to allocate %d interrupts",
986 		    navail);
987 		return (DDI_FAILURE);
988 	}
989 
990 	pvs->intr_cnt = nactual;
991 
992 	if (ddi_intr_get_pri(pvs->intr_handles[0], (uint_t *)&pvs->intr_pri) !=
993 	    DDI_SUCCESS) {
994 		dev_err(pvs->dip, CE_WARN, "!failed to get interrupt priority");
995 		pvscsi_free_intrs(pvs);
996 		return (DDI_FAILURE);
997 	}
998 
999 	for (i = 0; i < nactual; i++) {
1000 		if (ddi_intr_add_handler(pvs->intr_handles[i], pvscsi_intr,
1001 		    (caddr_t)pvs, NULL) != DDI_SUCCESS) {
1002 			dev_err(pvs->dip, CE_WARN,
1003 			    "!failed to add intr handler");
1004 			pvscsi_free_intrs(pvs);
1005 			return (DDI_FAILURE);
1006 		}
1007 	}
1008 
1009 	pvs->intr_type = type;
1010 	return (DDI_SUCCESS);
1011 }
1012 
1013 static int
pvscsi_setup_isr(pvscsi_softc_t * pvs)1014 pvscsi_setup_isr(pvscsi_softc_t *pvs)
1015 {
1016 	int	types;
1017 
1018 	if (ddi_intr_get_supported_types(pvs->dip, &types) != DDI_SUCCESS) {
1019 		dev_err(pvs->dip, CE_WARN, "!failed to get interrupt types");
1020 		return (DDI_FAILURE);
1021 	}
1022 
1023 	types &= pvscsi_intr_types;
1024 	if (types == 0) {
1025 		dev_err(pvs->dip, CE_WARN, "!no supported interrupt types");
1026 		return (DDI_FAILURE);
1027 	}
1028 
1029 
1030 	if (((types & DDI_INTR_TYPE_MSIX) != 0) &&
1031 	    (pvscsi_register_isr(pvs, DDI_INTR_TYPE_MSIX) == DDI_SUCCESS)) {
1032 		return (DDI_SUCCESS);
1033 	}
1034 	if (((types & DDI_INTR_TYPE_MSI) != 0) &&
1035 	    (pvscsi_register_isr(pvs, DDI_INTR_TYPE_MSI) == DDI_SUCCESS)) {
1036 		return (DDI_SUCCESS);
1037 	}
1038 	if (((types & DDI_INTR_TYPE_FIXED) != 0) &&
1039 	    (pvscsi_register_isr(pvs, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS)) {
1040 		return (DDI_SUCCESS);
1041 	}
1042 
1043 	dev_err(pvs->dip, CE_WARN, "!failed installing any interrupt handler");
1044 	return (DDI_FAILURE);
1045 }
1046 
1047 
1048 static void
pvscsi_timeout(void * arg)1049 pvscsi_timeout(void *arg)
1050 {
1051 	pvscsi_softc_t	*pvs;
1052 	pvscsi_cmd_t	*cmd;
1053 	pvscsi_cmd_t	*reclaimed = NULL;
1054 	list_t		*l;
1055 	clock_t		now;
1056 
1057 	pvs = arg;
1058 	l = &pvs->cmd_queue;
1059 	now = ddi_get_lbolt();
1060 
1061 	mutex_enter(&pvs->lock);
1062 	if (pvs->timeout == 0) {
1063 		mutex_exit(&pvs->lock);
1064 		return;
1065 	}
1066 
1067 	for (cmd = list_head(l); cmd != NULL; cmd = list_next(l, cmd)) {
1068 		clock_t	overdue;
1069 
1070 		/* polling takes care of it's own timeouts */
1071 		if (cmd->poll) {
1072 			continue;
1073 		}
1074 
1075 		overdue = now - (cmd->start + cmd->timeout);
1076 
1077 		/*
1078 		 * We keep the list of requests sorted by expiration
1079 		 * time, so we hopefully won't need to walk through
1080 		 * many of these.  This check is safe if lbolt wraps.
1081 		 */
1082 		if (overdue <= 0) {
1083 			break;
1084 		}
1085 
1086 		/* first we try aborting */
1087 		if (!cmd->expired) {
1088 			atomic_or_8(&cmd->expired, 1);
1089 			dev_err(pvs->dip, CE_WARN, "!cmd timed out (%lds)",
1090 			    drv_hztousec(cmd->timeout)/1000000);
1091 			continue;
1092 		}
1093 
1094 		/* if we're less than 2 seconds overdue, wait for abort */
1095 		if (overdue <= pvscsi_hz * 2) {
1096 			continue;
1097 		}
1098 
1099 		/* next it's a reset of the device */
1100 		if (overdue <= pvscsi_hz * 8) {
1101 			pvscsi_dev_reset(pvs, cmd->target, cmd->lun);
1102 			break;
1103 		}
1104 
1105 		/* next it's a reset of the bus */
1106 		if (overdue <= pvscsi_hz * 16) {
1107 			pvscsi_reset_bus(pvs);
1108 			break;
1109 		}
1110 
1111 		/* finally it's a reset of the entire adapter */
1112 		dev_err(pvs->dip, CE_WARN, "!adapter hung? restarting...");
1113 		mutex_enter(&pvs->lock);
1114 		pvscsi_stop_hba(pvs);
1115 		reclaimed = pvscsi_reclaim_cmds(pvs);
1116 		pvscsi_start_hba(pvs);
1117 		mutex_exit(&pvs->lock);
1118 		break;
1119 	}
1120 
1121 	/* see if reset or abort completed anything */
1122 	cmd = pvscsi_process_comp_ring(pvs);
1123 
1124 	/* reschedule us if we still have requests pending */
1125 	if (!list_is_empty(l)) {
1126 		pvs->timeout = timeout(pvscsi_timeout, pvs, pvscsi_hz);
1127 	}
1128 
1129 	mutex_exit(&pvs->lock);
1130 
1131 	/* if we had things that got completed, then do the callbacks */
1132 	pvscsi_complete_cmds(pvs, reclaimed);
1133 	pvscsi_complete_cmds(pvs, cmd);
1134 }
1135 
1136 static int
pvscsi_start(struct scsi_address * ap,struct scsi_pkt * pkt)1137 pvscsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1138 {
1139 	pvscsi_cmd_t		*cmd = pkt->pkt_ha_private;
1140 	struct scsi_device	*sd;
1141 	pvscsi_device_t		*pd;
1142 	pvscsi_softc_t		*pvs;
1143 	int			rc;
1144 	boolean_t		poll;
1145 
1146 	/* make sure the packet is sane */
1147 	if ((pkt->pkt_numcookies > PVSCSI_MAX_SG_SIZE) ||
1148 	    ((pkt->pkt_dma_flags & DDI_DMA_RDWR) == DDI_DMA_RDWR) ||
1149 	    (pkt->pkt_cdblen > sizeof (cmd->cdb)) ||
1150 	    ((sd = scsi_address_device(ap)) == NULL) ||
1151 	    ((pd = scsi_device_hba_private_get(sd)) == NULL) ||
1152 	    ((pvs = pd->pvs) == NULL))  {
1153 		return (TRAN_BADPKT);
1154 	}
1155 
1156 	ASSERT(cmd->pkt == pkt);
1157 
1158 	poll = cmd->poll = ((pkt->pkt_flags & FLAG_NOINTR) != 0);
1159 
1160 	if (pkt->pkt_flags & (FLAG_HTAG|FLAG_HEAD)) {
1161 		cmd->tag = MSG_HEAD_QTAG;
1162 	} else if (pkt->pkt_flags & FLAG_OTAG) {
1163 		cmd->tag = MSG_ORDERED_QTAG;
1164 	} else { /* also FLAG_STAG */
1165 		cmd->tag = MSG_SIMPLE_QTAG;
1166 	}
1167 
1168 	bcopy(pkt->pkt_cdbp, cmd->cdb, pkt->pkt_cdblen);
1169 	cmd->cdblen = pkt->pkt_cdblen;
1170 	bzero(&cmd->cmd_scb, sizeof (cmd->cmd_scb));
1171 
1172 	/*
1173 	 * Reinitialize some fields because the packet may
1174 	 * have been resubmitted.
1175 	 */
1176 	pkt->pkt_reason = CMD_CMPLT;
1177 	pkt->pkt_state = 0;
1178 	pkt->pkt_statistics = 0;
1179 
1180 	/* Zero status byte - but only if present */
1181 	if (pkt->pkt_scblen > 0) {
1182 		*(pkt->pkt_scbp) = 0;
1183 	}
1184 
1185 	if (pkt->pkt_numcookies > 0) {
1186 		if (pkt->pkt_dma_flags & DDI_DMA_READ) {
1187 			cmd->dma_dir = PVSCSI_FLAG_CMD_DIR_TOHOST;
1188 		} else if (pkt->pkt_dma_flags & DDI_DMA_WRITE) {
1189 			cmd->dma_dir = PVSCSI_FLAG_CMD_DIR_TODEVICE;
1190 		} else {
1191 			cmd->dma_dir = 0;
1192 		}
1193 	}
1194 
1195 	cmd->target = pd->target;
1196 	cmd->lun = pd->lun;
1197 	cmd->start = ddi_get_lbolt();
1198 	cmd->timeout = pkt->pkt_time * pvscsi_hz;
1199 
1200 	rc = pvscsi_transport_command(pvs, cmd);
1201 
1202 	if (poll && rc == TRAN_ACCEPT) {
1203 		pvscsi_poll_cmd(pvs, cmd);
1204 		pvscsi_set_status(pvs, cmd);
1205 	}
1206 
1207 	return (rc);
1208 }
1209 
1210 
1211 static int
pvscsi_parse_ua(const char * ua,int * target,int * lun)1212 pvscsi_parse_ua(const char *ua, int *target, int *lun)
1213 {
1214 	char *end;
1215 	long num;
1216 	if (((ddi_strtol(ua, &end, 16, &num)) != 0) ||
1217 	    ((*end != ',') && (*end != 0))) {
1218 		return (DDI_FAILURE);
1219 	}
1220 	*target = (int)num;
1221 	if (*end == 0) {
1222 		*lun = 0;
1223 		return (DDI_SUCCESS);
1224 	}
1225 	end++;
1226 	if ((ddi_strtol(end, &end, 16, &num) != 0) || (*end != 0)) {
1227 		return (DDI_FAILURE);
1228 	}
1229 	*lun = (int)num;
1230 	return (DDI_SUCCESS);
1231 }
1232 
1233 static uint32_t
pvscsi_max_targets(pvscsi_softc_t * pvs)1234 pvscsi_max_targets(pvscsi_softc_t *pvs)
1235 {
1236 	pvscsi_dma_buf_t			db;
1237 	struct PVSCSIConfigPageController	cpc;
1238 	struct PVSCSICmdDescConfigCmd		cmd;
1239 
1240 	bzero(&db, sizeof (db));
1241 
1242 	/* NB: config pages fit in a single page */
1243 	if (pvscsi_setup_dma_buffer(pvs, PAGE_SIZE, &db) != DDI_SUCCESS) {
1244 		dev_err(pvs->dip, CE_WARN,
1245 		    "!failed to setup config page DMA");
1246 		return (PVSCSI_MAXTGTS);
1247 	}
1248 
1249 	bzero(&cmd, sizeof (cmd));
1250 	cmd.configPageAddress = PVSCSI_CONFIG_CONTROLLER_ADDRESS;
1251 	cmd.configPageAddress <<= 32;
1252 	cmd.configPageNum = PVSCSI_CONFIG_PAGE_CONTROLLER;
1253 	cmd.cmpAddr = db.pa;
1254 
1255 	pvscsi_write_cmd_desc(pvs, PVSCSI_CMD_CONFIG, &cmd, sizeof (cmd));
1256 	(void) ddi_dma_sync(db.dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL);
1257 	bcopy(db.addr, &cpc, sizeof (cpc));
1258 	pvscsi_free_dma_buffer(&db);
1259 
1260 
1261 	if ((cpc.header.scsiStatus == STATUS_GOOD) &&
1262 	    (cpc.header.hostStatus == BTSTAT_SUCCESS) &&
1263 	    (cpc.numPhys > 0)) {
1264 		return (cpc.numPhys);
1265 	}
1266 
1267 	dev_err(pvs->dip, CE_WARN, "!failed to determine max targets");
1268 	return (PVSCSI_MAXTGTS);
1269 }
1270 
1271 static boolean_t
pvscsi_probe_target(pvscsi_softc_t * pvs,int target)1272 pvscsi_probe_target(pvscsi_softc_t *pvs, int target)
1273 {
1274 	pvscsi_cmd_t		cmd;
1275 
1276 	if (!pvscsi_cmd_init(pvs, &cmd, KM_SLEEP)) {
1277 		pvscsi_cmd_fini(&cmd);
1278 		return (B_FALSE);
1279 	}
1280 	/* NB: CDB 0 is a TUR which is perfect for our needs */
1281 	bzero(cmd.cdb, sizeof (cmd.cdb));
1282 	cmd.poll = B_TRUE;
1283 	cmd.dma_dir = 0;
1284 	cmd.target = target;
1285 	cmd.lun = 0;
1286 	cmd.start = ddi_get_lbolt();
1287 	cmd.timeout = pvscsi_hz;
1288 
1289 	if (pvscsi_transport_command(pvs, &cmd) != TRAN_ACCEPT) {
1290 		pvscsi_cmd_fini(&cmd);
1291 		return (B_FALSE);
1292 	}
1293 	pvscsi_poll_cmd(pvs, &cmd);
1294 
1295 	switch (cmd.host_status) {
1296 	case BTSTAT_SUCCESS:
1297 	case BTSTAT_LINKED_COMMAND_COMPLETED:
1298 	case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
1299 		/* We don't care about the actual SCSI status */
1300 		pvscsi_cmd_fini(&cmd);
1301 		return (B_TRUE);
1302 	}
1303 
1304 	pvscsi_cmd_fini(&cmd);
1305 	return (B_FALSE);
1306 }
1307 
1308 static int
pvscsi_tgt_init(dev_info_t * dip,dev_info_t * child,scsi_hba_tran_t * tran,struct scsi_device * sd)1309 pvscsi_tgt_init(dev_info_t *dip, dev_info_t *child, scsi_hba_tran_t *tran,
1310     struct scsi_device *sd)
1311 {
1312 	/*
1313 	 * Assumption: the HBA framework only asks us to have a single
1314 	 * target initialized per address at any given time.
1315 	 */
1316 	pvscsi_device_t	*pd;
1317 	pvscsi_softc_t	*pvs;
1318 	const char	*ua;
1319 
1320 	if (((scsi_hba_iport_unit_address(dip)) == NULL) ||
1321 	    ((pvs = tran->tran_hba_private) == NULL) ||
1322 	    ((ua = scsi_device_unit_address(sd)) == NULL)) {
1323 		return (DDI_FAILURE);
1324 	}
1325 
1326 	/* parse the unit address */
1327 	pd = kmem_zalloc(sizeof (*pd), KM_SLEEP);
1328 	if (pvscsi_parse_ua(ua, &pd->target, &pd->lun) != DDI_SUCCESS) {
1329 		kmem_free(pd, sizeof (*pd));
1330 		return (DDI_FAILURE);
1331 	}
1332 	pd->pvs = pvs;
1333 	scsi_device_hba_private_set(sd, pd);
1334 
1335 	mutex_enter(&pvs->lock);
1336 	list_insert_tail(&pvs->devices, pd);
1337 	mutex_exit(&pvs->lock);
1338 	return (DDI_SUCCESS);
1339 }
1340 
1341 static void
pvscsi_tgt_free(dev_info_t * dip,dev_info_t * child,scsi_hba_tran_t * tran,struct scsi_device * sd)1342 pvscsi_tgt_free(dev_info_t *dip, dev_info_t *child, scsi_hba_tran_t *tran,
1343     struct scsi_device *sd)
1344 {
1345 	pvscsi_device_t	*pd;
1346 	pvscsi_softc_t	*pvs;
1347 
1348 	if (((scsi_hba_iport_unit_address(dip)) == NULL) ||
1349 	    ((pvs = tran->tran_hba_private) == NULL) ||
1350 	    ((pd = scsi_device_hba_private_get(sd)) == NULL)) {
1351 		return;
1352 	}
1353 	scsi_device_hba_private_set(sd, NULL);
1354 	mutex_enter(&pvs->lock);
1355 	list_remove(&pvs->devices, pd);
1356 	mutex_exit(&pvs->lock);
1357 
1358 	kmem_free(pd, sizeof (*pd));
1359 }
1360 
1361 static int
pvscsi_reset(struct scsi_address * ap,int level)1362 pvscsi_reset(struct scsi_address *ap, int level)
1363 {
1364 	struct scsi_device	*sd;
1365 	pvscsi_device_t		*pd;
1366 	pvscsi_softc_t		*pvs;
1367 	pvscsi_cmd_t		*cmd;
1368 
1369 	if (((sd = scsi_address_device(ap)) == NULL) ||
1370 	    ((pd = scsi_device_hba_private_get(sd)) == NULL) ||
1371 	    ((pvs = pd->pvs) == NULL))  {
1372 		return (0);
1373 	}
1374 	switch (level) {
1375 	case RESET_ALL:
1376 	case RESET_BUS:
1377 		pvscsi_reset_bus(pvs);
1378 		break;
1379 	case RESET_TARGET:
1380 		/* reset both the lun and lun 0 */
1381 		pvscsi_dev_reset(pvs, pd->target, pd->lun);
1382 		pvscsi_dev_reset(pvs, pd->target, 0);
1383 		break;
1384 	case RESET_LUN:
1385 		pvscsi_dev_reset(pvs, pd->target, pd->lun);
1386 		break;
1387 	default:
1388 		return (0);
1389 	}
1390 
1391 	/* reset may have caused some completions */
1392 	mutex_enter(&pvs->lock);
1393 	cmd = pvscsi_process_comp_ring(pvs);
1394 	mutex_exit(&pvs->lock);
1395 
1396 	pvscsi_complete_cmds(pvs, cmd);
1397 	return (1);
1398 }
1399 
1400 static int
pvscsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)1401 pvscsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1402 {
1403 	struct scsi_device	*sd;
1404 	pvscsi_device_t		*pd;
1405 	pvscsi_softc_t		*pvs;
1406 	pvscsi_cmd_t		*cmd;
1407 
1408 	if (pkt != NULL) {
1409 		/* abort single command */
1410 		cmd = pkt->pkt_ha_private;
1411 		pvs = cmd->pvs;
1412 		pvscsi_abort_cmd(pvs, cmd);
1413 	} else if ((ap != NULL) &&
1414 	    ((sd = scsi_address_device(ap)) != NULL) &&
1415 	    ((pd = scsi_device_hba_private_get(sd)) != NULL) &&
1416 	    ((pvs = pd->pvs) != NULL)) {
1417 		/* abort all commands on the bus */
1418 		pvscsi_abort_all(pvs, pd);
1419 	} else {
1420 		return (0);
1421 	}
1422 
1423 	/* abort may have caused some completions */
1424 	mutex_enter(&pvs->lock);
1425 	cmd = pvscsi_process_comp_ring(pvs);
1426 	mutex_exit(&pvs->lock);
1427 
1428 	pvscsi_complete_cmds(pvs, cmd);
1429 
1430 	return (1);
1431 }
1432 
1433 static int
pvscsi_getcap(struct scsi_address * ap,char * cap,int whom)1434 pvscsi_getcap(struct scsi_address *ap, char *cap, int whom)
1435 {
1436 	_NOTE(ARGUNUSED(ap));
1437 	_NOTE(ARGUNUSED(whom));
1438 
1439 	if (cap == NULL) {
1440 		return (-1);
1441 	}
1442 
1443 	switch (scsi_hba_lookup_capstr(cap)) {
1444 	case SCSI_CAP_ARQ:
1445 	case SCSI_CAP_UNTAGGED_QING:
1446 	case SCSI_CAP_TAGGED_QING:
1447 		return (1);
1448 	default:
1449 		return (-1);
1450 	}
1451 }
1452 
1453 static int
pvscsi_setcap(struct scsi_address * ap,char * cap,int value,int whom)1454 pvscsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1455 {
1456 	_NOTE(ARGUNUSED(ap));
1457 	_NOTE(ARGUNUSED(value));
1458 	_NOTE(ARGUNUSED(whom));
1459 
1460 	if (cap == NULL) {
1461 		return (-1);
1462 	}
1463 
1464 	switch (scsi_hba_lookup_capstr(cap)) {
1465 	case SCSI_CAP_ARQ:
1466 	case SCSI_CAP_UNTAGGED_QING:
1467 	case SCSI_CAP_TAGGED_QING:
1468 		return (0); /* not changeable */
1469 	default:
1470 		return (-1);
1471 	}
1472 }
1473 
1474 static void
pvscsi_cmd_fini(pvscsi_cmd_t * cmd)1475 pvscsi_cmd_fini(pvscsi_cmd_t *cmd)
1476 {
1477 	if (cmd->arq_pa != 0) {
1478 		(void) ddi_dma_unbind_handle(cmd->arq_dmah);
1479 		cmd->arq_dmah = NULL;
1480 	}
1481 	if (cmd->arq_dmah != NULL) {
1482 		ddi_dma_free_handle(&cmd->arq_dmah);
1483 		cmd->arq_dmah = NULL;
1484 	}
1485 	if (cmd->sgl_pa != 0) {
1486 		(void) ddi_dma_unbind_handle(cmd->sgl_dmah);
1487 		cmd->sgl_pa = 0;
1488 	}
1489 	if (cmd->sgl_acch != NULL) {
1490 		ddi_dma_mem_free(&cmd->sgl_acch);
1491 		cmd->sgl_acch = NULL;
1492 		cmd->sgl = NULL;
1493 	}
1494 	if (cmd->sgl_dmah != NULL) {
1495 		ddi_dma_free_handle(&cmd->sgl_dmah);
1496 		cmd->sgl_dmah = NULL;
1497 	}
1498 	if (cmd->ctx != 0) {
1499 		id32_free(cmd->ctx);
1500 		cmd->ctx = 0;
1501 	}
1502 }
1503 
1504 static void
pvscsi_pkt_dtor(struct scsi_pkt * pkt,scsi_hba_tran_t * tran)1505 pvscsi_pkt_dtor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
1506 {
1507 	pvscsi_cmd_t	*cmd = pkt->pkt_ha_private;
1508 	pvscsi_cmd_fini(cmd);
1509 }
1510 
1511 static boolean_t
pvscsi_cmd_init(pvscsi_softc_t * pvs,pvscsi_cmd_t * cmd,int sleep)1512 pvscsi_cmd_init(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd, int sleep)
1513 {
1514 	int		(*cb)(caddr_t);
1515 	size_t		len;
1516 	caddr_t		kaddr;
1517 
1518 	cb = sleep == KM_SLEEP ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
1519 
1520 	bzero(cmd, sizeof (*cmd));
1521 	cmd->ctx = id32_alloc(cmd, sleep);
1522 	if (cmd->ctx == 0) {
1523 		dev_err(pvs->dip, CE_WARN,
1524 		    "!failed to allocate 32-bit context id");
1525 		return (B_FALSE);
1526 	}
1527 
1528 	/* allocate DMA resources for scatter/gather list */
1529 	if (ddi_dma_alloc_handle(pvs->dip, &pvscsi_dma_attr, cb, NULL,
1530 	    &cmd->sgl_dmah) != DDI_SUCCESS) {
1531 		dev_err(pvs->dip, CE_WARN,
1532 		    "!failed to allocate DMA handle for SG list");
1533 		return (B_FALSE);
1534 	}
1535 	if (ddi_dma_mem_alloc(cmd->sgl_dmah, PAGE_SIZE, &pvscsi_dma_attrs,
1536 	    DDI_DMA_CONSISTENT, cb, NULL, &kaddr, &len, &cmd->sgl_acch) !=
1537 	    DDI_SUCCESS) {
1538 		dev_err(pvs->dip, CE_WARN,
1539 		    "!failed to allocate DMA memory for SG list");
1540 		return (B_FALSE);
1541 	}
1542 	cmd->sgl = (void *)kaddr;
1543 	if (ddi_dma_addr_bind_handle(cmd->sgl_dmah, NULL, kaddr,
1544 	    PAGE_SIZE, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, cb, NULL,
1545 	    NULL, NULL) != DDI_DMA_MAPPED) {
1546 		dev_err(pvs->dip, CE_WARN, "!failed to bind SGL list");
1547 		return (B_FALSE);
1548 	}
1549 	cmd->sgl_pa = ddi_dma_cookie_one(cmd->sgl_dmah)->dmac_laddress;
1550 
1551 	/* allocate DMA resource for auto-sense-request */
1552 	if (ddi_dma_alloc_handle(pvs->dip, &pvscsi_dma_attr,
1553 	    cb, NULL, &cmd->arq_dmah) != DDI_SUCCESS) {
1554 		dev_err(pvs->dip, CE_WARN,
1555 		    "!failed to allocate DMA handle for ARQ buffer");
1556 		return (B_FALSE);
1557 	}
1558 
1559 	if (ddi_dma_addr_bind_handle(cmd->arq_dmah, NULL,
1560 	    (void *)cmd->arq_sense, SENSE_LENGTH,
1561 	    DDI_DMA_READ | DDI_DMA_CONSISTENT, cb, NULL,
1562 	    NULL, NULL) != DDI_DMA_MAPPED) {
1563 		dev_err(pvs->dip, CE_WARN, "!failed to bind ARQ buffer");
1564 		return (B_FALSE);
1565 	}
1566 	cmd->arq_pa = ddi_dma_cookie_one(cmd->arq_dmah)->dmac_laddress;
1567 	return (B_TRUE);
1568 }
1569 
1570 static int
pvscsi_pkt_ctor(struct scsi_pkt * pkt,scsi_hba_tran_t * tran,int sleep)1571 pvscsi_pkt_ctor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, int sleep)
1572 {
1573 	pvscsi_cmd_t	*cmd = pkt->pkt_ha_private;
1574 	pvscsi_softc_t	*pvs = tran->tran_hba_private;
1575 
1576 	if (!pvscsi_cmd_init(pvs, cmd, sleep)) {
1577 		pvscsi_pkt_dtor(pkt, tran);
1578 		return (-1);
1579 	}
1580 	cmd->pkt = pkt;
1581 	return (0);
1582 }
1583 
1584 static void
pvscsi_teardown_pkt(struct scsi_pkt * pkt)1585 pvscsi_teardown_pkt(struct scsi_pkt *pkt)
1586 {
1587 	_NOTE(ARGUNUSED(pkt));
1588 	/* nothing to do */
1589 }
1590 
1591 static int
pvscsi_setup_pkt(struct scsi_pkt * pkt,int (* cb)(caddr_t),caddr_t arg)1592 pvscsi_setup_pkt(struct scsi_pkt *pkt, int (*cb)(caddr_t), caddr_t arg)
1593 {
1594 	/* all work is done in start */
1595 	return (0);
1596 }
1597 
1598 static int
pvscsi_hba_setup(pvscsi_softc_t * pvs)1599 pvscsi_hba_setup(pvscsi_softc_t *pvs)
1600 {
1601 	scsi_hba_tran_t	*tran;
1602 
1603 	tran = scsi_hba_tran_alloc(pvs->dip, SCSI_HBA_CANSLEEP);
1604 	ASSERT(tran != NULL);
1605 
1606 	tran->tran_hba_private = pvs;
1607 	tran->tran_start = pvscsi_start;
1608 	tran->tran_reset = pvscsi_reset;
1609 	tran->tran_abort = pvscsi_abort;
1610 	tran->tran_getcap = pvscsi_getcap;
1611 	tran->tran_setcap = pvscsi_setcap;
1612 	tran->tran_pkt_constructor = pvscsi_pkt_ctor;
1613 	tran->tran_pkt_destructor = pvscsi_pkt_dtor;
1614 	tran->tran_setup_pkt = pvscsi_setup_pkt;
1615 	tran->tran_teardown_pkt = pvscsi_teardown_pkt;
1616 	tran->tran_tgt_init = pvscsi_tgt_init;
1617 	tran->tran_tgt_free = pvscsi_tgt_free;
1618 	tran->tran_hba_len = sizeof (pvscsi_cmd_t);
1619 
1620 	tran->tran_interconnect_type = INTERCONNECT_PARALLEL;
1621 
1622 	if (scsi_hba_attach_setup(pvs->dip, &pvscsi_io_dma_attr, tran,
1623 	    SCSI_HBA_HBA | SCSI_HBA_TRAN_CDB | SCSI_HBA_TRAN_SCB |
1624 	    SCSI_HBA_ADDR_COMPLEX) !=
1625 	    DDI_SUCCESS) {
1626 		scsi_hba_tran_free(tran);
1627 		dev_err(pvs->dip, CE_WARN, "!failed to attach HBA");
1628 		return (DDI_FAILURE);
1629 	}
1630 
1631 	pvs->tran = tran;
1632 	return (DDI_SUCCESS);
1633 }
1634 
1635 static void
pvscsi_teardown(pvscsi_softc_t * pvs)1636 pvscsi_teardown(pvscsi_softc_t *pvs)
1637 {
1638 	timeout_id_t	tid;
1639 
1640 	pvscsi_stop_hba(pvs);
1641 
1642 	if (pvs->tq != NULL) {
1643 		ddi_taskq_destroy(pvs->tq);
1644 	}
1645 	mutex_enter(&pvs->lock);
1646 	tid = pvs->timeout;
1647 	pvs->timeout = 0;
1648 	mutex_exit(&pvs->lock);
1649 
1650 	if (tid != 0) {
1651 		(void) untimeout(tid);
1652 	}
1653 
1654 	pvscsi_free_intrs(pvs);
1655 	pvscsi_free_rings(pvs);
1656 
1657 	if (pvs->mmio_handle != NULL) {
1658 		ddi_regs_map_free(&pvs->mmio_handle);
1659 	}
1660 
1661 	if (pvs->tran != NULL) {
1662 		scsi_hba_tran_free(pvs->tran);
1663 	}
1664 	mutex_destroy(&pvs->lock);
1665 	list_destroy(&pvs->cmd_queue);
1666 	list_destroy(&pvs->devices);
1667 
1668 	kmem_free(pvs, sizeof (*pvs));
1669 }
1670 
1671 static int
pvscsi_iport_attach(dev_info_t * dip)1672 pvscsi_iport_attach(dev_info_t *dip)
1673 {
1674 	scsi_hba_tran_t	*tran;
1675 	dev_info_t	*parent;
1676 	pvscsi_softc_t	*pvs;
1677 	char		*ua;
1678 	uint32_t	max_targets;
1679 
1680 	if (((parent = ddi_get_parent(dip)) == NULL) ||
1681 	    ((tran = ddi_get_driver_private(parent)) == NULL) ||
1682 	    ((pvs = tran->tran_hba_private) == NULL) ||
1683 	    ((ua = scsi_hba_iport_unit_address(dip)) == NULL) ||
1684 	    (strcmp(ua, "iport0") != 0)) {
1685 		return (DDI_FAILURE);
1686 	}
1687 
1688 	/* store our softc on the iport private tran */
1689 	tran = ddi_get_driver_private(dip);
1690 	tran->tran_hba_private = pvs;
1691 
1692 	/* setup the target map - allow 100ms for settle / sync times */
1693 	if (scsi_hba_tgtmap_create(dip, SCSI_TM_PERADDR, 100000,
1694 	    100000, pvs, NULL, NULL, &pvs->tgtmap) != DDI_SUCCESS) {
1695 		dev_err(pvs->dip, CE_WARN, "!failed to create target map");
1696 		return (DDI_FAILURE);
1697 	}
1698 
1699 	/* reset hardware and setup the rings */
1700 	mutex_enter(&pvs->lock);
1701 	pvs->detach = B_FALSE; /* in case of reattach */
1702 	pvscsi_start_hba(pvs);
1703 
1704 	max_targets = pvs->max_targets = pvscsi_max_targets(pvs);
1705 	mutex_exit(&pvs->lock);
1706 
1707 	for (uint32_t i = 0; i < max_targets; i++) {
1708 		char addr[8];
1709 		if (pvscsi_probe_target(pvs, i)) {
1710 			(void) snprintf(addr, sizeof (addr), "%x", i);
1711 			(void) scsi_hba_tgtmap_tgt_add(pvs->tgtmap,
1712 			    SCSI_TGT_SCSI_DEVICE, addr, NULL);
1713 		}
1714 	}
1715 
1716 	return (DDI_SUCCESS);
1717 }
1718 
1719 static int
pvscsi_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1720 pvscsi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1721 {
1722 	pvscsi_softc_t	*pvs;
1723 
1724 	if (cmd != DDI_ATTACH) {
1725 		return (DDI_FAILURE);
1726 	}
1727 
1728 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1729 		return (pvscsi_iport_attach(dip));
1730 	}
1731 
1732 	pvs = kmem_zalloc(sizeof (*pvs), KM_SLEEP);
1733 
1734 	/* Setup HBA instance */
1735 	pvs->dip = dip;
1736 
1737 	/*
1738 	 * mutex initialization - note that we always run below
1739 	 * lock level, so we can get by without interrupt priorities
1740 	 */
1741 	mutex_init(&pvs->lock, NULL, MUTEX_DRIVER, NULL);
1742 	list_create(&pvs->cmd_queue, sizeof (pvscsi_cmd_t),
1743 	    offsetof(pvscsi_cmd_t, queue_node));
1744 	list_create(&pvs->devices, sizeof (pvscsi_device_t),
1745 	    offsetof(pvscsi_device_t, node));
1746 
1747 	if ((pvscsi_setup_io(pvs)) != DDI_SUCCESS) {
1748 		dev_err(pvs->dip, CE_WARN, "!failed to setup I/O region");
1749 		pvscsi_teardown(pvs);
1750 		return (DDI_FAILURE);
1751 	}
1752 
1753 	pvscsi_stop_hba(pvs);
1754 
1755 	if ((pvscsi_allocate_rings(pvs)) != DDI_SUCCESS) {
1756 		dev_err(pvs->dip, CE_WARN, "!failed to allocate DMA rings");
1757 		pvscsi_teardown(pvs);
1758 		return (DDI_FAILURE);
1759 	}
1760 
1761 	if (pvscsi_setup_isr(pvs) != DDI_SUCCESS) {
1762 		dev_err(pvs->dip, CE_WARN, "!failed to setup ISR");
1763 		pvscsi_teardown(pvs);
1764 		return (DDI_FAILURE);
1765 	}
1766 
1767 	/* enable interrupts */
1768 	if (pvscsi_enable_intrs(pvs) != DDI_SUCCESS) {
1769 		dev_err(pvs->dip, CE_WARN, "!failed to enable interrupts");
1770 		pvscsi_teardown(pvs);
1771 		return (DDI_FAILURE);
1772 	}
1773 
1774 	pvs->tq = ddi_taskq_create(dip, "iport", 1, TASKQ_DEFAULTPRI, 0);
1775 	if (pvs->tq == NULL) {
1776 		dev_err(pvs->dip, CE_WARN, "!failed creating tq");
1777 		pvscsi_teardown(pvs);
1778 		return (DDI_FAILURE);
1779 	}
1780 	if (pvscsi_hba_setup(pvs) != DDI_SUCCESS) {
1781 		dev_err(pvs->dip, CE_WARN, "!failed to setup HBA");
1782 		pvscsi_teardown(pvs);
1783 		return (DDI_FAILURE);
1784 	}
1785 
1786 	if (scsi_hba_iport_register(dip, "iport0") != 0) {
1787 		dev_err(pvs->dip, CE_WARN, "failed to register iport");
1788 		/* detach cannot fail since we didn't setup the iport */
1789 		(void) scsi_hba_detach(dip);
1790 		pvscsi_teardown(pvs);
1791 		return (DDI_FAILURE);
1792 	}
1793 
1794 	return (DDI_SUCCESS);
1795 }
1796 
1797 static int
pvscsi_iport_detach(dev_info_t * dip)1798 pvscsi_iport_detach(dev_info_t *dip)
1799 {
1800 	pvscsi_softc_t	*pvs;
1801 	scsi_hba_tran_t	*tran;
1802 	const char	*ua;
1803 	pvscsi_cmd_t	*reclaimed;
1804 
1805 	if (((ua = scsi_hba_iport_unit_address(dip)) == NULL) ||
1806 	    (strcmp(ua, "iport0") != 0) ||
1807 	    ((tran = ddi_get_driver_private(dip)) == NULL) ||
1808 	    ((pvs = tran->tran_hba_private) == NULL)) {
1809 		return (DDI_FAILURE);
1810 	}
1811 
1812 	/* stop the HBA */
1813 	mutex_enter(&pvs->lock);
1814 	pvs->detach = B_TRUE;
1815 	pvscsi_stop_hba(pvs);
1816 	mutex_exit(&pvs->lock);
1817 
1818 	/* drain the taskq - nothing else will post to it */
1819 	ddi_taskq_wait(pvs->tq);
1820 
1821 	/* reset the HBA */
1822 	mutex_enter(&pvs->lock);
1823 	reclaimed = pvscsi_reclaim_cmds(pvs);
1824 	mutex_exit(&pvs->lock);
1825 
1826 	/*
1827 	 * If we had any commands, complete them so we can
1828 	 * reclaim the resources.  There really should not be any.
1829 	 */
1830 	pvscsi_complete_cmds(pvs, reclaimed);
1831 
1832 	scsi_hba_tgtmap_destroy(pvs->tgtmap);
1833 	pvs->tgtmap = NULL;
1834 
1835 	return (DDI_SUCCESS);
1836 }
1837 
1838 static int
pvscsi_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1839 pvscsi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1840 {
1841 	pvscsi_softc_t	*pvs;
1842 	scsi_hba_tran_t	*tran;
1843 
1844 	if (cmd != DDI_DETACH) {
1845 		return (DDI_FAILURE);
1846 	}
1847 
1848 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1849 		return (pvscsi_iport_detach(dip));
1850 	}
1851 
1852 	if (((tran = ddi_get_driver_private(dip)) == NULL) ||
1853 	    ((pvs = tran->tran_hba_private) == NULL)) {
1854 		/* this can only mean we aren't attached yet */
1855 		return (DDI_SUCCESS);
1856 	}
1857 	if (scsi_hba_detach(dip) != DDI_SUCCESS) {
1858 		return (DDI_FAILURE);
1859 	}
1860 
1861 	pvscsi_teardown(pvs);
1862 
1863 	return (DDI_SUCCESS);
1864 }
1865 
1866 static int
pvscsi_quiesce(dev_info_t * dip)1867 pvscsi_quiesce(dev_info_t *dip)
1868 {
1869 	scsi_hba_tran_t	*tran;
1870 	pvscsi_softc_t	*pvs;
1871 
1872 	if (((tran = ddi_get_driver_private(dip)) == NULL) ||
1873 	    ((pvs = tran->tran_hba_private) == NULL)) {
1874 		return (DDI_SUCCESS);
1875 	}
1876 
1877 	pvscsi_stop_hba(pvs);
1878 
1879 	return (DDI_SUCCESS);
1880 }
1881 
1882 static struct dev_ops pvscsi_ops = {
1883 	.devo_rev =	DEVO_REV,
1884 	.devo_refcnt =	0,
1885 	.devo_getinfo =	nodev,
1886 	.devo_identify = nulldev,
1887 	.devo_probe =	nulldev,
1888 	.devo_attach =	pvscsi_attach,
1889 	.devo_detach =	pvscsi_detach,
1890 	.devo_reset =	nodev,
1891 	.devo_cb_ops =	NULL,
1892 	.devo_bus_ops =	NULL,
1893 	.devo_power =	NULL,
1894 	.devo_quiesce =	pvscsi_quiesce
1895 };
1896 
1897 #define	PVSCSI_IDENT "VMware PVSCSI"
1898 
1899 static struct modldrv modldrv = {
1900 	&mod_driverops,
1901 	PVSCSI_IDENT,
1902 	&pvscsi_ops,
1903 };
1904 
1905 static struct modlinkage modlinkage = {
1906 	MODREV_1,
1907 	&modldrv,
1908 	NULL
1909 };
1910 
1911 int
_init(void)1912 _init(void)
1913 {
1914 	int	ret;
1915 
1916 	/* get HZ - DDI compliant */
1917 	pvscsi_hz = drv_usectohz(1000000);
1918 
1919 	if ((ret = scsi_hba_init(&modlinkage)) != 0) {
1920 		cmn_err(CE_WARN, "!scsi_hba_init() failed");
1921 		return (ret);
1922 	}
1923 
1924 	if ((ret = mod_install(&modlinkage)) != 0) {
1925 		cmn_err(CE_WARN, "!mod_install() failed");
1926 		scsi_hba_fini(&modlinkage);
1927 	}
1928 
1929 	return (ret);
1930 }
1931 
1932 int
_info(struct modinfo * modinfop)1933 _info(struct modinfo *modinfop)
1934 {
1935 	return (mod_info(&modlinkage, modinfop));
1936 }
1937 
1938 int
_fini(void)1939 _fini(void)
1940 {
1941 	int	ret;
1942 
1943 	if ((ret = mod_remove(&modlinkage)) == 0) {
1944 		scsi_hba_fini(&modlinkage);
1945 	}
1946 
1947 	return (ret);
1948 }
1949