Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/perseant-stdc-iso10646]: src/sys/dev/scsipi 2975092



details:   https://anonhg.NetBSD.org/src/rev/3855efb16596
branches:  perseant-stdc-iso10646
changeset: 850625:3855efb16596
user:      christos <christos%NetBSD.org@localhost>
date:      Fri Jul 14 17:50:12 2017 +0000

description:
2975092

diffstat:

 sys/dev/scsipi/scsipi_base.c |  2678 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 2678 insertions(+), 0 deletions(-)

diffs (truncated from 2682 to 300 lines):

diff -r 1ae1518222ac -r 3855efb16596 sys/dev/scsipi/scsipi_base.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/scsipi/scsipi_base.c      Fri Jul 14 17:50:12 2017 +0000
@@ -0,0 +1,2678 @@
+/*     $NetBSD: scsipi_base.c,v 1.178.2.2 2017/07/14 17:50:12 christos Exp $   */
+
+/*-
+ * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.178.2.2 2017/07/14 17:50:12 christos Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_scsi.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/uio.h>
+#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/proc.h>
+#include <sys/kthread.h>
+#include <sys/hash.h>
+#include <sys/atomic.h>
+
+#include <dev/scsipi/scsi_spc.h>
+#include <dev/scsipi/scsipi_all.h>
+#include <dev/scsipi/scsipi_disk.h>
+#include <dev/scsipi/scsipiconf.h>
+#include <dev/scsipi/scsipi_base.h>
+
+#include <dev/scsipi/scsi_all.h>
+#include <dev/scsipi/scsi_message.h>
+
+#include <machine/param.h>
+
+static int     scsipi_complete(struct scsipi_xfer *);
+static void    scsipi_request_sense(struct scsipi_xfer *);
+static int     scsipi_enqueue(struct scsipi_xfer *);
+static void    scsipi_run_queue(struct scsipi_channel *chan);
+
+static void    scsipi_completion_thread(void *);
+
+static void    scsipi_get_tag(struct scsipi_xfer *);
+static void    scsipi_put_tag(struct scsipi_xfer *);
+
+static int     scsipi_get_resource(struct scsipi_channel *);
+static void    scsipi_put_resource(struct scsipi_channel *);
+
+static void    scsipi_async_event_max_openings(struct scsipi_channel *,
+                   struct scsipi_max_openings *);
+static void    scsipi_async_event_channel_reset(struct scsipi_channel *);
+
+static void    scsipi_channel_freeze_locked(struct scsipi_channel *, int);
+
+static void    scsipi_adapter_lock(struct scsipi_adapter *adapt);
+static void    scsipi_adapter_unlock(struct scsipi_adapter *adapt);
+
+static struct pool scsipi_xfer_pool;
+
+int scsipi_xs_count = 0;
+
+/*
+ * scsipi_init:
+ *
+ *     Called when a scsibus or atapibus is attached to the system
+ *     to initialize shared data structures.
+ */
+void
+scsipi_init(void)
+{
+       static int scsipi_init_done;
+
+       if (scsipi_init_done)
+               return;
+       scsipi_init_done = 1;
+
+       /* Initialize the scsipi_xfer pool. */
+       pool_init(&scsipi_xfer_pool, sizeof(struct scsipi_xfer), 0,
+           0, 0, "scxspl", NULL, IPL_BIO);
+       if (pool_prime(&scsipi_xfer_pool,
+           PAGE_SIZE / sizeof(struct scsipi_xfer)) == ENOMEM) {
+               printf("WARNING: not enough memory for scsipi_xfer_pool\n");
+       }
+
+       scsipi_ioctl_init();
+}
+
+/*
+ * scsipi_channel_init:
+ *
+ *     Initialize a scsipi_channel when it is attached.
+ */
+int
+scsipi_channel_init(struct scsipi_channel *chan)
+{
+       struct scsipi_adapter *adapt = chan->chan_adapter;
+       int i;
+
+       /* Initialize shared data. */
+       scsipi_init();
+
+       /* Initialize the queues. */
+       TAILQ_INIT(&chan->chan_queue);
+       TAILQ_INIT(&chan->chan_complete);
+
+       for (i = 0; i < SCSIPI_CHAN_PERIPH_BUCKETS; i++)
+               LIST_INIT(&chan->chan_periphtab[i]);
+
+       /*
+        * Create the asynchronous completion thread.
+        */
+       if (kthread_create(PRI_NONE, 0, NULL, scsipi_completion_thread, chan,
+           &chan->chan_thread, "%s", chan->chan_name)) {
+               aprint_error_dev(adapt->adapt_dev, "unable to create completion thread for "
+                   "channel %d\n", chan->chan_channel);
+               panic("scsipi_channel_init");
+       }
+
+       return 0;
+}
+
+/*
+ * scsipi_channel_shutdown:
+ *
+ *     Shutdown a scsipi_channel.
+ */
+void
+scsipi_channel_shutdown(struct scsipi_channel *chan)
+{
+
+       mutex_enter(chan_mtx(chan));
+       /*
+        * Shut down the completion thread.
+        */
+       chan->chan_tflags |= SCSIPI_CHANT_SHUTDOWN;
+       cv_broadcast(chan_cv_complete(chan));
+
+       /*
+        * Now wait for the thread to exit.
+        */
+       while (chan->chan_thread != NULL)
+               cv_wait(chan_cv_thread(chan), chan_mtx(chan));
+       mutex_exit(chan_mtx(chan));
+}
+
+static uint32_t
+scsipi_chan_periph_hash(uint64_t t, uint64_t l)
+{
+       uint32_t hash;
+
+       hash = hash32_buf(&t, sizeof(t), HASH32_BUF_INIT);
+       hash = hash32_buf(&l, sizeof(l), hash);
+
+       return hash & SCSIPI_CHAN_PERIPH_HASHMASK;
+}
+
+/*
+ * scsipi_insert_periph:
+ *
+ *     Insert a periph into the channel.
+ */
+void
+scsipi_insert_periph(struct scsipi_channel *chan, struct scsipi_periph *periph)
+{
+       uint32_t hash;
+
+       hash = scsipi_chan_periph_hash(periph->periph_target,
+           periph->periph_lun);
+
+       mutex_enter(chan_mtx(chan));
+       LIST_INSERT_HEAD(&chan->chan_periphtab[hash], periph, periph_hash);
+       mutex_exit(chan_mtx(chan));
+}
+
+/*
+ * scsipi_remove_periph:
+ *
+ *     Remove a periph from the channel.
+ */
+void
+scsipi_remove_periph(struct scsipi_channel *chan,
+    struct scsipi_periph *periph)
+{
+
+       LIST_REMOVE(periph, periph_hash);
+}
+
+/*
+ * scsipi_lookup_periph:
+ *
+ *     Lookup a periph on the specified channel.
+ */
+static struct scsipi_periph *
+scsipi_lookup_periph_internal(struct scsipi_channel *chan, int target, int lun, bool lock)
+{
+       struct scsipi_periph *periph;
+       uint32_t hash;
+
+       if (target >= chan->chan_ntargets ||
+           lun >= chan->chan_nluns)
+               return NULL;
+
+       hash = scsipi_chan_periph_hash(target, lun);
+
+       if (lock)
+               mutex_enter(chan_mtx(chan));
+       LIST_FOREACH(periph, &chan->chan_periphtab[hash], periph_hash) {
+               if (periph->periph_target == target &&
+                   periph->periph_lun == lun)
+                       break;
+       }
+       if (lock)
+               mutex_exit(chan_mtx(chan));
+
+       return periph;
+}
+
+struct scsipi_periph *
+scsipi_lookup_periph_locked(struct scsipi_channel *chan, int target, int lun)
+{
+       return scsipi_lookup_periph_internal(chan, target, lun, false);
+}
+
+struct scsipi_periph *
+scsipi_lookup_periph(struct scsipi_channel *chan, int target, int lun)
+{
+       return scsipi_lookup_periph_internal(chan, target, lun, true);
+}
+
+/*
+ * scsipi_get_resource:
+ *
+ *     Allocate a single xfer `resource' from the channel.
+ *
+ *     NOTE: Must be called with channel lock held
+ */
+static int
+scsipi_get_resource(struct scsipi_channel *chan)
+{
+       struct scsipi_adapter *adapt = chan->chan_adapter;
+
+       if (chan->chan_flags & SCSIPI_CHAN_OPENINGS) {
+               if (chan->chan_openings > 0) {
+                       chan->chan_openings--;
+                       return 1;
+               }
+               return 0;
+       }
+
+       if (adapt->adapt_openings > 0) {
+               adapt->adapt_openings--;
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * scsipi_grow_resources:
+ *
+ *     Attempt to grow resources for a channel.  If this succeeds,
+ *     we allocate one for our caller.
+ *
+ *     NOTE: Must be called with channel lock held
+ */
+static inline int
+scsipi_grow_resources(struct scsipi_channel *chan)
+{



Home | Main Index | Thread Index | Old Index