| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: scsipi_base.c,v 1.170 2016/12/16 15:00:52 mlelstv Exp $ */ | | 1 | /* $NetBSD: scsipi_base.c,v 1.171 2016/12/18 13:59:14 mlelstv Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace | | 8 | * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace |
9 | * Simulation Facility, NASA Ames Research Center. | | 9 | * Simulation Facility, NASA Ames Research Center. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -21,27 +21,27 @@ | | | @@ -21,27 +21,27 @@ |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | #include <sys/cdefs.h> | | 33 | #include <sys/cdefs.h> |
34 | __KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.170 2016/12/16 15:00:52 mlelstv Exp $"); | | 34 | __KERNEL_RCSID(0, "$NetBSD: scsipi_base.c,v 1.171 2016/12/18 13:59:14 mlelstv Exp $"); |
35 | | | 35 | |
36 | #ifdef _KERNEL_OPT | | 36 | #ifdef _KERNEL_OPT |
37 | #include "opt_scsi.h" | | 37 | #include "opt_scsi.h" |
38 | #endif | | 38 | #endif |
39 | | | 39 | |
40 | #include <sys/param.h> | | 40 | #include <sys/param.h> |
41 | #include <sys/systm.h> | | 41 | #include <sys/systm.h> |
42 | #include <sys/kernel.h> | | 42 | #include <sys/kernel.h> |
43 | #include <sys/buf.h> | | 43 | #include <sys/buf.h> |
44 | #include <sys/uio.h> | | 44 | #include <sys/uio.h> |
45 | #include <sys/malloc.h> | | 45 | #include <sys/malloc.h> |
46 | #include <sys/pool.h> | | 46 | #include <sys/pool.h> |
47 | #include <sys/errno.h> | | 47 | #include <sys/errno.h> |
| @@ -1452,28 +1452,28 @@ scsipi_done(struct scsipi_xfer *xs) | | | @@ -1452,28 +1452,28 @@ scsipi_done(struct scsipi_xfer *xs) |
1452 | * if we can handle it in interrupt context. | | 1452 | * if we can handle it in interrupt context. |
1453 | */ | | 1453 | */ |
1454 | if (xs->error == XS_NOERROR) { | | 1454 | if (xs->error == XS_NOERROR) { |
1455 | mutex_exit(chan_mtx(chan)); | | 1455 | mutex_exit(chan_mtx(chan)); |
1456 | (void) scsipi_complete(xs); | | 1456 | (void) scsipi_complete(xs); |
1457 | goto out; | | 1457 | goto out; |
1458 | } | | 1458 | } |
1459 | | | 1459 | |
1460 | /* | | 1460 | /* |
1461 | * There is an error on this xfer. Put it on the channel's | | 1461 | * There is an error on this xfer. Put it on the channel's |
1462 | * completion queue, and wake up the completion thread. | | 1462 | * completion queue, and wake up the completion thread. |
1463 | */ | | 1463 | */ |
1464 | TAILQ_INSERT_TAIL(&chan->chan_complete, xs, channel_q); | | 1464 | TAILQ_INSERT_TAIL(&chan->chan_complete, xs, channel_q); |
1465 | mutex_exit(chan_mtx(chan)); | | | |
1466 | cv_broadcast(chan_cv_complete(chan)); | | 1465 | cv_broadcast(chan_cv_complete(chan)); |
| | | 1466 | mutex_exit(chan_mtx(chan)); |
1467 | | | 1467 | |
1468 | out: | | 1468 | out: |
1469 | /* | | 1469 | /* |
1470 | * If there are more xfers on the channel's queue, attempt to | | 1470 | * If there are more xfers on the channel's queue, attempt to |
1471 | * run them. | | 1471 | * run them. |
1472 | */ | | 1472 | */ |
1473 | scsipi_run_queue(chan); | | 1473 | scsipi_run_queue(chan); |
1474 | } | | 1474 | } |
1475 | | | 1475 | |
1476 | /* | | 1476 | /* |
1477 | * scsipi_complete: | | 1477 | * scsipi_complete: |
1478 | * | | 1478 | * |
1479 | * Completion of a scsipi_xfer. This is the guts of scsipi_done(). | | 1479 | * Completion of a scsipi_xfer. This is the guts of scsipi_done(). |
| @@ -2128,88 +2128,84 @@ scsipi_execute_xs(struct scsipi_xfer *xs | | | @@ -2128,88 +2128,84 @@ scsipi_execute_xs(struct scsipi_xfer *xs |
2128 | * function, restarting the command, if necessary. | | 2128 | * function, restarting the command, if necessary. |
2129 | */ | | 2129 | */ |
2130 | static void | | 2130 | static void |
2131 | scsipi_completion_thread(void *arg) | | 2131 | scsipi_completion_thread(void *arg) |
2132 | { | | 2132 | { |
2133 | struct scsipi_channel *chan = arg; | | 2133 | struct scsipi_channel *chan = arg; |
2134 | struct scsipi_xfer *xs; | | 2134 | struct scsipi_xfer *xs; |
2135 | | | 2135 | |
2136 | if (chan->chan_init_cb) | | 2136 | if (chan->chan_init_cb) |
2137 | (*chan->chan_init_cb)(chan, chan->chan_init_cb_arg); | | 2137 | (*chan->chan_init_cb)(chan, chan->chan_init_cb_arg); |
2138 | | | 2138 | |
2139 | mutex_enter(chan_mtx(chan)); | | 2139 | mutex_enter(chan_mtx(chan)); |
2140 | chan->chan_flags |= SCSIPI_CHAN_TACTIVE; | | 2140 | chan->chan_flags |= SCSIPI_CHAN_TACTIVE; |
2141 | mutex_exit(chan_mtx(chan)); | | | |
2142 | for (;;) { | | 2141 | for (;;) { |
2143 | mutex_enter(chan_mtx(chan)); | | | |
2144 | xs = TAILQ_FIRST(&chan->chan_complete); | | 2142 | xs = TAILQ_FIRST(&chan->chan_complete); |
2145 | if (xs == NULL && chan->chan_tflags == 0) { | | 2143 | if (xs == NULL && chan->chan_tflags == 0) { |
2146 | /* nothing to do; wait */ | | 2144 | /* nothing to do; wait */ |
2147 | cv_wait(chan_cv_complete(chan), chan_mtx(chan)); | | 2145 | cv_wait(chan_cv_complete(chan), chan_mtx(chan)); |
2148 | mutex_exit(chan_mtx(chan)); | | | |
2149 | continue; | | 2146 | continue; |
2150 | } | | 2147 | } |
2151 | if (chan->chan_tflags & SCSIPI_CHANT_CALLBACK) { | | 2148 | if (chan->chan_tflags & SCSIPI_CHANT_CALLBACK) { |
2152 | /* call chan_callback from thread context */ | | 2149 | /* call chan_callback from thread context */ |
2153 | chan->chan_tflags &= ~SCSIPI_CHANT_CALLBACK; | | 2150 | chan->chan_tflags &= ~SCSIPI_CHANT_CALLBACK; |
2154 | chan->chan_callback(chan, chan->chan_callback_arg); | | 2151 | chan->chan_callback(chan, chan->chan_callback_arg); |
2155 | mutex_exit(chan_mtx(chan)); | | | |
2156 | continue; | | 2152 | continue; |
2157 | } | | 2153 | } |
2158 | if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) { | | 2154 | if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) { |
2159 | /* attempt to get more openings for this channel */ | | 2155 | /* attempt to get more openings for this channel */ |
2160 | chan->chan_tflags &= ~SCSIPI_CHANT_GROWRES; | | 2156 | chan->chan_tflags &= ~SCSIPI_CHANT_GROWRES; |
2161 | mutex_exit(chan_mtx(chan)); | | 2157 | mutex_exit(chan_mtx(chan)); |
2162 | scsipi_adapter_request(chan, | | 2158 | scsipi_adapter_request(chan, |
2163 | ADAPTER_REQ_GROW_RESOURCES, NULL); | | 2159 | ADAPTER_REQ_GROW_RESOURCES, NULL); |
2164 | scsipi_channel_thaw(chan, 1); | | 2160 | scsipi_channel_thaw(chan, 1); |
2165 | if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) | | 2161 | if (chan->chan_tflags & SCSIPI_CHANT_GROWRES) |
2166 | kpause("scsizzz", FALSE, hz/10, NULL); | | 2162 | kpause("scsizzz", FALSE, hz/10, NULL); |
| | | 2163 | mutex_enter(chan_mtx(chan)); |
2167 | continue; | | 2164 | continue; |
2168 | } | | 2165 | } |
2169 | if (chan->chan_tflags & SCSIPI_CHANT_KICK) { | | 2166 | if (chan->chan_tflags & SCSIPI_CHANT_KICK) { |
2170 | /* explicitly run the queues for this channel */ | | 2167 | /* explicitly run the queues for this channel */ |
2171 | chan->chan_tflags &= ~SCSIPI_CHANT_KICK; | | 2168 | chan->chan_tflags &= ~SCSIPI_CHANT_KICK; |
2172 | mutex_exit(chan_mtx(chan)); | | 2169 | mutex_exit(chan_mtx(chan)); |
2173 | scsipi_run_queue(chan); | | 2170 | scsipi_run_queue(chan); |
| | | 2171 | mutex_enter(chan_mtx(chan)); |
2174 | continue; | | 2172 | continue; |
2175 | } | | 2173 | } |
2176 | if (chan->chan_tflags & SCSIPI_CHANT_SHUTDOWN) { | | 2174 | if (chan->chan_tflags & SCSIPI_CHANT_SHUTDOWN) { |
2177 | mutex_exit(chan_mtx(chan)); | | | |
2178 | break; | | 2175 | break; |
2179 | } | | 2176 | } |
2180 | if (xs) { | | 2177 | if (xs) { |
2181 | TAILQ_REMOVE(&chan->chan_complete, xs, channel_q); | | 2178 | TAILQ_REMOVE(&chan->chan_complete, xs, channel_q); |
2182 | mutex_exit(chan_mtx(chan)); | | 2179 | mutex_exit(chan_mtx(chan)); |
2183 | | | 2180 | |
2184 | /* | | 2181 | /* |
2185 | * Have an xfer with an error; process it. | | 2182 | * Have an xfer with an error; process it. |
2186 | */ | | 2183 | */ |
2187 | (void) scsipi_complete(xs); | | 2184 | (void) scsipi_complete(xs); |
2188 | | | 2185 | |
2189 | /* | | 2186 | /* |
2190 | * Kick the queue; keep it running if it was stopped | | 2187 | * Kick the queue; keep it running if it was stopped |
2191 | * for some reason. | | 2188 | * for some reason. |
2192 | */ | | 2189 | */ |
2193 | scsipi_run_queue(chan); | | 2190 | scsipi_run_queue(chan); |
2194 | } else { | | | |
2195 | mutex_exit(chan_mtx(chan)); | | | |
2196 | } | | 2191 | } |
2197 | } | | 2192 | } |
2198 | | | 2193 | |
2199 | chan->chan_thread = NULL; | | 2194 | chan->chan_thread = NULL; |
2200 | | | 2195 | |
2201 | /* In case parent is waiting for us to exit. */ | | 2196 | /* In case parent is waiting for us to exit. */ |
2202 | cv_broadcast(chan_cv_thread(chan)); | | 2197 | cv_broadcast(chan_cv_thread(chan)); |
| | | 2198 | mutex_exit(chan_mtx(chan)); |
2203 | | | 2199 | |
2204 | kthread_exit(0); | | 2200 | kthread_exit(0); |
2205 | } | | 2201 | } |
2206 | /* | | 2202 | /* |
2207 | * scsipi_thread_call_callback: | | 2203 | * scsipi_thread_call_callback: |
2208 | * | | 2204 | * |
2209 | * request to call a callback from the completion thread | | 2205 | * request to call a callback from the completion thread |
2210 | */ | | 2206 | */ |
2211 | int | | 2207 | int |
2212 | scsipi_thread_call_callback(struct scsipi_channel *chan, | | 2208 | scsipi_thread_call_callback(struct scsipi_channel *chan, |
2213 | void (*callback)(struct scsipi_channel *, void *), void *arg) | | 2209 | void (*callback)(struct scsipi_channel *, void *), void *arg) |
2214 | { | | 2210 | { |
2215 | | | 2211 | |