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 */
15
16 #include <sys/atomic.h>
17 #include <sys/cmn_err.h>
18 #include <sys/conf.h>
19 #include <sys/cpuvar.h>
20 #include <sys/ddi.h>
21 #include <sys/errno.h>
22 #include <sys/fs/dv_node.h>
23 #include <sys/kmem.h>
24 #include <sys/kmem_impl.h>
25 #include <sys/list.h>
26 #include <sys/modctl.h>
27 #include <sys/pci.h>
28 #include <sys/scsi/scsi.h>
29 #include <sys/sunddi.h>
30 #include <sys/sysmacros.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33
34 #include "pvscsi.h"
35 #include "pvscsi_var.h"
36
37 int pvscsi_enable_msi = 1;
38 int pvscsi_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_PER_RING;
39 int pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
40
41 static int pvscsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
42
107 static void
108 pvscsi_add_to_queue(pvscsi_cmd_t *cmd)
109 {
110 pvscsi_softc_t *pvs = cmd->cmd_pvs;
111
112 ASSERT(pvs != NULL);
113 ASSERT(mutex_owned(&pvs->mutex));
114 ASSERT(!list_link_active(&(cmd)->cmd_queue_node));
115
116 list_insert_tail(&pvs->cmd_queue, cmd);
117 pvs->cmd_queue_len++;
118 }
119
120 static void
121 pvscsi_remove_from_queue(pvscsi_cmd_t *cmd)
122 {
123 pvscsi_softc_t *pvs = cmd->cmd_pvs;
124
125 ASSERT(pvs != NULL);
126 ASSERT(mutex_owned(&pvs->mutex));
127 ASSERT(list_link_active(&cmd->cmd_queue_node));
128 ASSERT(pvs->cmd_queue_len > 0);
129
130 if (list_link_active(&cmd->cmd_queue_node)) {
131 list_remove(&pvs->cmd_queue, cmd);
132 pvs->cmd_queue_len--;
133 }
134 }
135
136 static uint64_t
137 pvscsi_map_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_ctx_t *io_ctx)
138 {
139 return (io_ctx - pvs->cmd_ctx + 1);
140 }
141
142 static pvscsi_cmd_ctx_t *
143 pvscsi_lookup_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
144 {
145 pvscsi_cmd_ctx_t *ctx, *end;
146
147 end = &pvs->cmd_ctx[pvs->req_depth];
148 for (ctx = pvs->cmd_ctx; ctx < end; ctx++) {
149 if (ctx->cmd == cmd)
150 return (ctx);
343 dev_info_t *dip;
344 int inqrc;
345 int ncompatible = 0;
346 pvscsi_device_t *devnode;
347 struct scsi_inquiry inq;
348
349 ASSERT(DEVI_BUSY_OWNED(pdip));
350
351 /* Inquiry target */
352 inqrc = pvscsi_inquiry_target(pvs, target, &inq);
353
354 /* Find devnode */
355 for (devnode = list_head(&pvs->devnodes); devnode != NULL;
356 devnode = list_next(&pvs->devnodes, devnode)) {
357 if (devnode->target == target)
358 break;
359 }
360
361 if (devnode != NULL) {
362 if (inqrc != 0) {
363 /* Target disappeared, drop devnode */
364 if (i_ddi_devi_attached(devnode->pdip)) {
365 char *devname;
366 /* Get full devname */
367 devname = kmem_alloc(MAXPATHLEN, KM_SLEEP);
368 (void) ddi_deviname(devnode->pdip, devname);
369 /* Clean cache and name */
370 (void) devfs_clean(devnode->parent, devname + 1,
371 DV_CLEAN_FORCE);
372 kmem_free(devname, MAXPATHLEN);
373 }
374
375 (void) ndi_devi_offline(devnode->pdip, NDI_DEVI_REMOVE);
376
377 list_remove(&pvs->devnodes, devnode);
378 kmem_free(devnode, sizeof (*devnode));
379 } else if (childp != NULL) {
380 /* Target exists */
381 *childp = devnode->pdip;
382 }
383 return (NDI_SUCCESS);
384 } else if (inqrc != 0) {
385 /* Target doesn't exist */
386 return (NDI_FAILURE);
387 }
388
389 scsi_hba_nodename_compatible_get(&inq, NULL, inq.inq_dtype, NULL,
390 &nodename, &compatible, &ncompatible);
391 if (nodename == NULL)
392 goto free_nodename;
393
394 if (ndi_devi_alloc(pdip, nodename, DEVI_SID_NODEID,
395 &dip) != NDI_SUCCESS) {
396 dev_err(pvs->dip, CE_WARN, "!failed to alloc device instance");
|
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 2018 Nexenta Systems, Inc.
14 */
15
16 #include <sys/atomic.h>
17 #include <sys/cmn_err.h>
18 #include <sys/conf.h>
19 #include <sys/cpuvar.h>
20 #include <sys/ddi.h>
21 #include <sys/errno.h>
22 #include <sys/kmem.h>
23 #include <sys/kmem_impl.h>
24 #include <sys/list.h>
25 #include <sys/modctl.h>
26 #include <sys/pci.h>
27 #include <sys/scsi/scsi.h>
28 #include <sys/sunddi.h>
29 #include <sys/sysmacros.h>
30 #include <sys/time.h>
31 #include <sys/types.h>
32
33 #include "pvscsi.h"
34 #include "pvscsi_var.h"
35
36 int pvscsi_enable_msi = 1;
37 int pvscsi_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_PER_RING;
38 int pvscsi_msg_ring_pages = PVSCSI_DEFAULT_NUM_PAGES_MSG_RING;
39
40 static int pvscsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
41
106 static void
107 pvscsi_add_to_queue(pvscsi_cmd_t *cmd)
108 {
109 pvscsi_softc_t *pvs = cmd->cmd_pvs;
110
111 ASSERT(pvs != NULL);
112 ASSERT(mutex_owned(&pvs->mutex));
113 ASSERT(!list_link_active(&(cmd)->cmd_queue_node));
114
115 list_insert_tail(&pvs->cmd_queue, cmd);
116 pvs->cmd_queue_len++;
117 }
118
119 static void
120 pvscsi_remove_from_queue(pvscsi_cmd_t *cmd)
121 {
122 pvscsi_softc_t *pvs = cmd->cmd_pvs;
123
124 ASSERT(pvs != NULL);
125 ASSERT(mutex_owned(&pvs->mutex));
126
127 if (list_link_active(&cmd->cmd_queue_node)) {
128 ASSERT(pvs->cmd_queue_len > 0);
129 list_remove(&pvs->cmd_queue, cmd);
130 pvs->cmd_queue_len--;
131 }
132 }
133
134 static uint64_t
135 pvscsi_map_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_ctx_t *io_ctx)
136 {
137 return (io_ctx - pvs->cmd_ctx + 1);
138 }
139
140 static pvscsi_cmd_ctx_t *
141 pvscsi_lookup_ctx(pvscsi_softc_t *pvs, pvscsi_cmd_t *cmd)
142 {
143 pvscsi_cmd_ctx_t *ctx, *end;
144
145 end = &pvs->cmd_ctx[pvs->req_depth];
146 for (ctx = pvs->cmd_ctx; ctx < end; ctx++) {
147 if (ctx->cmd == cmd)
148 return (ctx);
341 dev_info_t *dip;
342 int inqrc;
343 int ncompatible = 0;
344 pvscsi_device_t *devnode;
345 struct scsi_inquiry inq;
346
347 ASSERT(DEVI_BUSY_OWNED(pdip));
348
349 /* Inquiry target */
350 inqrc = pvscsi_inquiry_target(pvs, target, &inq);
351
352 /* Find devnode */
353 for (devnode = list_head(&pvs->devnodes); devnode != NULL;
354 devnode = list_next(&pvs->devnodes, devnode)) {
355 if (devnode->target == target)
356 break;
357 }
358
359 if (devnode != NULL) {
360 if (inqrc != 0) {
361 (void) ndi_devi_offline(devnode->pdip,
362 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
363 list_remove(&pvs->devnodes, devnode);
364 kmem_free(devnode, sizeof (*devnode));
365 } else if (childp != NULL) {
366 /* Target exists */
367 *childp = devnode->pdip;
368 }
369 return (NDI_SUCCESS);
370 } else if (inqrc != 0) {
371 /* Target doesn't exist */
372 return (NDI_FAILURE);
373 }
374
375 scsi_hba_nodename_compatible_get(&inq, NULL, inq.inq_dtype, NULL,
376 &nodename, &compatible, &ncompatible);
377 if (nodename == NULL)
378 goto free_nodename;
379
380 if (ndi_devi_alloc(pdip, nodename, DEVI_SID_NODEID,
381 &dip) != NDI_SUCCESS) {
382 dev_err(pvs->dip, CE_WARN, "!failed to alloc device instance");
|