1ef270ab1SKenneth D. Merry /*-
2ef270ab1SKenneth D. Merry * Copyright (c) 2017 Broadcom. All rights reserved.
3ef270ab1SKenneth D. Merry * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4ef270ab1SKenneth D. Merry *
5ef270ab1SKenneth D. Merry * Redistribution and use in source and binary forms, with or without
6ef270ab1SKenneth D. Merry * modification, are permitted provided that the following conditions are met:
7ef270ab1SKenneth D. Merry *
8ef270ab1SKenneth D. Merry * 1. Redistributions of source code must retain the above copyright notice,
9ef270ab1SKenneth D. Merry * this list of conditions and the following disclaimer.
10ef270ab1SKenneth D. Merry *
11ef270ab1SKenneth D. Merry * 2. Redistributions in binary form must reproduce the above copyright notice,
12ef270ab1SKenneth D. Merry * this list of conditions and the following disclaimer in the documentation
13ef270ab1SKenneth D. Merry * and/or other materials provided with the distribution.
14ef270ab1SKenneth D. Merry *
15ef270ab1SKenneth D. Merry * 3. Neither the name of the copyright holder nor the names of its contributors
16ef270ab1SKenneth D. Merry * may be used to endorse or promote products derived from this software
17ef270ab1SKenneth D. Merry * without specific prior written permission.
18ef270ab1SKenneth D. Merry *
19ef270ab1SKenneth D. Merry * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20ef270ab1SKenneth D. Merry * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21ef270ab1SKenneth D. Merry * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22ef270ab1SKenneth D. Merry * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23ef270ab1SKenneth D. Merry * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ef270ab1SKenneth D. Merry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ef270ab1SKenneth D. Merry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ef270ab1SKenneth D. Merry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ef270ab1SKenneth D. Merry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ef270ab1SKenneth D. Merry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ef270ab1SKenneth D. Merry * POSSIBILITY OF SUCH DAMAGE.
30ef270ab1SKenneth D. Merry */
31ef270ab1SKenneth D. Merry
32ef270ab1SKenneth D. Merry /**
33ef270ab1SKenneth D. Merry * @file
34ef270ab1SKenneth D. Merry * Provide IO object allocation.
35ef270ab1SKenneth D. Merry */
36ef270ab1SKenneth D. Merry
37ef270ab1SKenneth D. Merry /*!
38ef270ab1SKenneth D. Merry * @defgroup io_alloc IO allocation
39ef270ab1SKenneth D. Merry */
40ef270ab1SKenneth D. Merry
41ef270ab1SKenneth D. Merry #include "ocs.h"
42ef270ab1SKenneth D. Merry #include "ocs_scsi.h"
43ef270ab1SKenneth D. Merry #include "ocs_els.h"
44ef270ab1SKenneth D. Merry #include "ocs_utils.h"
45ef270ab1SKenneth D. Merry
46ef270ab1SKenneth D. Merry void ocs_mgmt_io_list(ocs_textbuf_t *textbuf, void *io);
47ef270ab1SKenneth D. Merry void ocs_mgmt_io_get_all(ocs_textbuf_t *textbuf, void *io);
48ef270ab1SKenneth D. Merry int ocs_mgmt_io_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *io);
49ef270ab1SKenneth D. Merry
50ef270ab1SKenneth D. Merry static ocs_mgmt_functions_t io_mgmt_functions = {
51ef270ab1SKenneth D. Merry .get_list_handler = ocs_mgmt_io_list,
52ef270ab1SKenneth D. Merry .get_handler = ocs_mgmt_io_get,
53ef270ab1SKenneth D. Merry .get_all_handler = ocs_mgmt_io_get_all,
54ef270ab1SKenneth D. Merry };
55ef270ab1SKenneth D. Merry
56ef270ab1SKenneth D. Merry /**
57ef270ab1SKenneth D. Merry * @brief IO pool.
58ef270ab1SKenneth D. Merry *
59ef270ab1SKenneth D. Merry * Structure encapsulating a pool of IO objects.
60ef270ab1SKenneth D. Merry *
61ef270ab1SKenneth D. Merry */
62ef270ab1SKenneth D. Merry
63ef270ab1SKenneth D. Merry struct ocs_io_pool_s {
64ef270ab1SKenneth D. Merry ocs_t *ocs; /* Pointer to device object */
65ef270ab1SKenneth D. Merry ocs_lock_t lock; /* IO pool lock */
66ef270ab1SKenneth D. Merry uint32_t io_num_ios; /* Total IOs allocated */
67ef270ab1SKenneth D. Merry ocs_pool_t *pool;
68ef270ab1SKenneth D. Merry };
69ef270ab1SKenneth D. Merry
70ef270ab1SKenneth D. Merry /**
71ef270ab1SKenneth D. Merry * @brief Create a pool of IO objects.
72ef270ab1SKenneth D. Merry *
73ef270ab1SKenneth D. Merry * @par Description
74ef270ab1SKenneth D. Merry * This function allocates memory in larger chucks called
75ef270ab1SKenneth D. Merry * "slabs" which are a fixed size. It calculates the number of IO objects that
76ef270ab1SKenneth D. Merry * fit within each "slab" and determines the number of "slabs" required to
77ef270ab1SKenneth D. Merry * allocate the number of IOs requested. Each of the slabs is allocated and
78ef270ab1SKenneth D. Merry * then it grabs each IO object within the slab and adds it to the free list.
79ef270ab1SKenneth D. Merry * Individual command, response and SGL DMA buffers are allocated for each IO.
80ef270ab1SKenneth D. Merry *
81ef270ab1SKenneth D. Merry * "Slabs"
82ef270ab1SKenneth D. Merry * +----------------+
83ef270ab1SKenneth D. Merry * | |
84ef270ab1SKenneth D. Merry * +----------------+ |
85ef270ab1SKenneth D. Merry * | IO | |
86ef270ab1SKenneth D. Merry * +----------------+ |
87ef270ab1SKenneth D. Merry * | ... | |
88ef270ab1SKenneth D. Merry * +----------------+__+
89ef270ab1SKenneth D. Merry * | IO |
90ef270ab1SKenneth D. Merry * +----------------+
91ef270ab1SKenneth D. Merry *
92ef270ab1SKenneth D. Merry * @param ocs Driver instance's software context.
93ef270ab1SKenneth D. Merry * @param num_io Number of IO contexts to allocate.
94ef270ab1SKenneth D. Merry * @param num_sgl Number of SGL entries to allocate for each IO.
95ef270ab1SKenneth D. Merry *
96ef270ab1SKenneth D. Merry * @return Returns a pointer to a new ocs_io_pool_t on success,
97ef270ab1SKenneth D. Merry * or NULL on failure.
98ef270ab1SKenneth D. Merry */
99ef270ab1SKenneth D. Merry
100ef270ab1SKenneth D. Merry ocs_io_pool_t *
ocs_io_pool_create(ocs_t * ocs,uint32_t num_io,uint32_t num_sgl)101ef270ab1SKenneth D. Merry ocs_io_pool_create(ocs_t *ocs, uint32_t num_io, uint32_t num_sgl)
102ef270ab1SKenneth D. Merry {
103ef270ab1SKenneth D. Merry uint32_t i = 0;
104ef270ab1SKenneth D. Merry int32_t rc = -1;
105ef270ab1SKenneth D. Merry ocs_io_pool_t *io_pool;
106ef270ab1SKenneth D. Merry
107ef270ab1SKenneth D. Merry /* Allocate the IO pool */
108ef270ab1SKenneth D. Merry io_pool = ocs_malloc(ocs, sizeof(*io_pool), OCS_M_ZERO | OCS_M_NOWAIT);
109ef270ab1SKenneth D. Merry if (io_pool == NULL) {
110ef270ab1SKenneth D. Merry ocs_log_err(ocs, "allocate of IO pool failed\n");
111*aeb665b5SEd Maste return NULL;
112ef270ab1SKenneth D. Merry }
113ef270ab1SKenneth D. Merry
114ef270ab1SKenneth D. Merry io_pool->ocs = ocs;
115ef270ab1SKenneth D. Merry io_pool->io_num_ios = num_io;
116ef270ab1SKenneth D. Merry
117ef270ab1SKenneth D. Merry /* initialize IO pool lock */
118ef270ab1SKenneth D. Merry ocs_lock_init(ocs, &io_pool->lock, "io_pool lock[%d]", ocs->instance_index);
119ef270ab1SKenneth D. Merry
120ef270ab1SKenneth D. Merry io_pool->pool = ocs_pool_alloc(ocs, sizeof(ocs_io_t), io_pool->io_num_ios, FALSE);
121ef270ab1SKenneth D. Merry
122ef270ab1SKenneth D. Merry for (i = 0; i < io_pool->io_num_ios; i++) {
123ef270ab1SKenneth D. Merry ocs_io_t *io = ocs_pool_get_instance(io_pool->pool, i);
124ef270ab1SKenneth D. Merry
125ef270ab1SKenneth D. Merry io->tag = i;
126ef270ab1SKenneth D. Merry io->instance_index = i;
127ef270ab1SKenneth D. Merry io->ocs = ocs;
128ef270ab1SKenneth D. Merry
129ef270ab1SKenneth D. Merry /* allocate a command/response dma buffer */
130ef270ab1SKenneth D. Merry if (ocs->enable_ini) {
131ef270ab1SKenneth D. Merry rc = ocs_dma_alloc(ocs, &io->cmdbuf, SCSI_CMD_BUF_LENGTH, OCS_MIN_DMA_ALIGNMENT);
132ef270ab1SKenneth D. Merry if (rc) {
133ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_dma_alloc cmdbuf failed\n");
134ef270ab1SKenneth D. Merry ocs_io_pool_free(io_pool);
135ef270ab1SKenneth D. Merry return NULL;
136ef270ab1SKenneth D. Merry }
137ef270ab1SKenneth D. Merry }
138ef270ab1SKenneth D. Merry
139ef270ab1SKenneth D. Merry /* Allocate a response buffer */
140ef270ab1SKenneth D. Merry rc = ocs_dma_alloc(ocs, &io->rspbuf, SCSI_RSP_BUF_LENGTH, OCS_MIN_DMA_ALIGNMENT);
141ef270ab1SKenneth D. Merry if (rc) {
142ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_dma_alloc cmdbuf failed\n");
143ef270ab1SKenneth D. Merry ocs_io_pool_free(io_pool);
144ef270ab1SKenneth D. Merry return NULL;
145ef270ab1SKenneth D. Merry }
146ef270ab1SKenneth D. Merry
147ef270ab1SKenneth D. Merry /* Allocate SGL */
148ef270ab1SKenneth D. Merry io->sgl = ocs_malloc(ocs, sizeof(*io->sgl) * num_sgl, OCS_M_NOWAIT | OCS_M_ZERO);
149ef270ab1SKenneth D. Merry if (io->sgl == NULL) {
150ef270ab1SKenneth D. Merry ocs_log_err(ocs, "malloc sgl's failed\n");
151ef270ab1SKenneth D. Merry ocs_io_pool_free(io_pool);
152ef270ab1SKenneth D. Merry return NULL;
153ef270ab1SKenneth D. Merry }
154ef270ab1SKenneth D. Merry io->sgl_allocated = num_sgl;
155ef270ab1SKenneth D. Merry io->sgl_count = 0;
156ef270ab1SKenneth D. Merry
157ef270ab1SKenneth D. Merry /* Make IO backend call to initialize IO */
158ef270ab1SKenneth D. Merry ocs_scsi_tgt_io_init(io);
159ef270ab1SKenneth D. Merry ocs_scsi_ini_io_init(io);
160ef270ab1SKenneth D. Merry
161ef270ab1SKenneth D. Merry rc = ocs_dma_alloc(ocs, &io->els_req, OCS_ELS_REQ_LEN, OCS_MIN_DMA_ALIGNMENT);
162ef270ab1SKenneth D. Merry if (rc) {
163ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_dma_alloc els_req failed\n");
164ef270ab1SKenneth D. Merry ocs_io_pool_free(io_pool);
165ef270ab1SKenneth D. Merry return NULL;
166ef270ab1SKenneth D. Merry }
167ef270ab1SKenneth D. Merry
168ef270ab1SKenneth D. Merry rc = ocs_dma_alloc(ocs, &io->els_rsp, OCS_ELS_GID_PT_RSP_LEN, OCS_MIN_DMA_ALIGNMENT);
169ef270ab1SKenneth D. Merry if (rc) {
170ef270ab1SKenneth D. Merry ocs_log_err(ocs, "ocs_dma_alloc els_rsp failed\n");
171ef270ab1SKenneth D. Merry ocs_io_pool_free(io_pool);
172ef270ab1SKenneth D. Merry return NULL;
173ef270ab1SKenneth D. Merry }
174ef270ab1SKenneth D. Merry }
175ef270ab1SKenneth D. Merry
176ef270ab1SKenneth D. Merry return io_pool;
177ef270ab1SKenneth D. Merry }
178ef270ab1SKenneth D. Merry
179ef270ab1SKenneth D. Merry /**
180ef270ab1SKenneth D. Merry * @brief Free IO objects pool
181ef270ab1SKenneth D. Merry *
182ef270ab1SKenneth D. Merry * @par Description
183ef270ab1SKenneth D. Merry * The pool of IO objects are freed.
184ef270ab1SKenneth D. Merry *
185ef270ab1SKenneth D. Merry * @param io_pool Pointer to IO pool object.
186ef270ab1SKenneth D. Merry *
187ef270ab1SKenneth D. Merry * @return Returns 0 on success, or a negative error code value on failure.
188ef270ab1SKenneth D. Merry */
189ef270ab1SKenneth D. Merry int32_t
ocs_io_pool_free(ocs_io_pool_t * io_pool)190ef270ab1SKenneth D. Merry ocs_io_pool_free(ocs_io_pool_t *io_pool)
191ef270ab1SKenneth D. Merry {
192ef270ab1SKenneth D. Merry ocs_t *ocs;
193ef270ab1SKenneth D. Merry uint32_t i;
194ef270ab1SKenneth D. Merry ocs_io_t *io;
195ef270ab1SKenneth D. Merry
196ef270ab1SKenneth D. Merry if (io_pool != NULL) {
197ef270ab1SKenneth D. Merry ocs = io_pool->ocs;
198ef270ab1SKenneth D. Merry for (i = 0; i < io_pool->io_num_ios; i++) {
199ef270ab1SKenneth D. Merry io = ocs_pool_get_instance(io_pool->pool, i);
200ef270ab1SKenneth D. Merry if (!io)
201ef270ab1SKenneth D. Merry continue;
202ef270ab1SKenneth D. Merry ocs_scsi_tgt_io_exit(io);
203ef270ab1SKenneth D. Merry ocs_scsi_ini_io_exit(io);
204ef270ab1SKenneth D. Merry if (io->sgl) {
205ef270ab1SKenneth D. Merry ocs_free(ocs, io->sgl, sizeof(*io->sgl) * io->sgl_allocated);
206ef270ab1SKenneth D. Merry }
207ef270ab1SKenneth D. Merry ocs_dma_free(ocs, &io->cmdbuf);
208ef270ab1SKenneth D. Merry ocs_dma_free(ocs, &io->rspbuf);
209ef270ab1SKenneth D. Merry ocs_dma_free(ocs, &io->els_req);
210ef270ab1SKenneth D. Merry ocs_dma_free(ocs, &io->els_rsp);
211ef270ab1SKenneth D. Merry }
212ef270ab1SKenneth D. Merry
213ef270ab1SKenneth D. Merry if (io_pool->pool != NULL) {
214ef270ab1SKenneth D. Merry ocs_pool_free(io_pool->pool);
215ef270ab1SKenneth D. Merry }
216ef270ab1SKenneth D. Merry ocs_lock_free(&io_pool->lock);
217ef270ab1SKenneth D. Merry ocs_free(ocs, io_pool, sizeof(*io_pool));
218ef270ab1SKenneth D. Merry ocs->xport->io_pool = NULL;
219ef270ab1SKenneth D. Merry }
220ef270ab1SKenneth D. Merry
221ef270ab1SKenneth D. Merry return 0;
222ef270ab1SKenneth D. Merry }
223ef270ab1SKenneth D. Merry
ocs_io_pool_allocated(ocs_io_pool_t * io_pool)224ef270ab1SKenneth D. Merry uint32_t ocs_io_pool_allocated(ocs_io_pool_t *io_pool)
225ef270ab1SKenneth D. Merry {
226ef270ab1SKenneth D. Merry return io_pool->io_num_ios;
227ef270ab1SKenneth D. Merry }
228ef270ab1SKenneth D. Merry
229ef270ab1SKenneth D. Merry /**
230ef270ab1SKenneth D. Merry * @ingroup io_alloc
231ef270ab1SKenneth D. Merry * @brief Allocate an object used to track an IO.
232ef270ab1SKenneth D. Merry *
233ef270ab1SKenneth D. Merry * @param io_pool Pointer to the IO pool.
234ef270ab1SKenneth D. Merry *
235ef270ab1SKenneth D. Merry * @return Returns the pointer to a new object, or NULL if none available.
236ef270ab1SKenneth D. Merry */
237ef270ab1SKenneth D. Merry ocs_io_t *
ocs_io_pool_io_alloc(ocs_io_pool_t * io_pool)238ef270ab1SKenneth D. Merry ocs_io_pool_io_alloc(ocs_io_pool_t *io_pool)
239ef270ab1SKenneth D. Merry {
240ef270ab1SKenneth D. Merry ocs_io_t *io = NULL;
241ef270ab1SKenneth D. Merry ocs_t *ocs;
242ef270ab1SKenneth D. Merry
243ef270ab1SKenneth D. Merry ocs_assert(io_pool, NULL);
244ef270ab1SKenneth D. Merry
245ef270ab1SKenneth D. Merry ocs = io_pool->ocs;
246ef270ab1SKenneth D. Merry
247ef270ab1SKenneth D. Merry ocs_lock(&io_pool->lock);
248ef270ab1SKenneth D. Merry if ((io = ocs_pool_get(io_pool->pool)) != NULL) {
249ef270ab1SKenneth D. Merry ocs_unlock(&io_pool->lock);
250ef270ab1SKenneth D. Merry
251ef270ab1SKenneth D. Merry io->io_type = OCS_IO_TYPE_MAX;
252ef270ab1SKenneth D. Merry io->hio_type = OCS_HW_IO_MAX;
253ef270ab1SKenneth D. Merry io->hio = NULL;
254ef270ab1SKenneth D. Merry io->transferred = 0;
255ef270ab1SKenneth D. Merry io->ocs = ocs;
256ef270ab1SKenneth D. Merry io->timeout = 0;
257ef270ab1SKenneth D. Merry io->sgl_count = 0;
258ef270ab1SKenneth D. Merry io->tgt_task_tag = 0;
259ef270ab1SKenneth D. Merry io->init_task_tag = 0;
260ef270ab1SKenneth D. Merry io->hw_tag = 0;
261ef270ab1SKenneth D. Merry io->display_name = "pending";
262ef270ab1SKenneth D. Merry io->seq_init = 0;
263ef270ab1SKenneth D. Merry io->els_req_free = 0;
264ef270ab1SKenneth D. Merry io->mgmt_functions = &io_mgmt_functions;
265ef270ab1SKenneth D. Merry io->io_free = 0;
266ef270ab1SKenneth D. Merry ocs_atomic_add_return(&ocs->xport->io_active_count, 1);
267ef270ab1SKenneth D. Merry ocs_atomic_add_return(&ocs->xport->io_total_alloc, 1);
268ef270ab1SKenneth D. Merry } else {
269ef270ab1SKenneth D. Merry ocs_unlock(&io_pool->lock);
270ef270ab1SKenneth D. Merry }
271ef270ab1SKenneth D. Merry return io;
272ef270ab1SKenneth D. Merry }
273ef270ab1SKenneth D. Merry
274ef270ab1SKenneth D. Merry /**
275ef270ab1SKenneth D. Merry * @ingroup io_alloc
276ef270ab1SKenneth D. Merry * @brief Free an object used to track an IO.
277ef270ab1SKenneth D. Merry *
278ef270ab1SKenneth D. Merry * @param io_pool Pointer to IO pool object.
279ef270ab1SKenneth D. Merry * @param io Pointer to the IO object.
280ef270ab1SKenneth D. Merry */
281ef270ab1SKenneth D. Merry void
ocs_io_pool_io_free(ocs_io_pool_t * io_pool,ocs_io_t * io)282ef270ab1SKenneth D. Merry ocs_io_pool_io_free(ocs_io_pool_t *io_pool, ocs_io_t *io)
283ef270ab1SKenneth D. Merry {
284ef270ab1SKenneth D. Merry ocs_t *ocs;
285ef270ab1SKenneth D. Merry ocs_hw_io_t *hio = NULL;
286ef270ab1SKenneth D. Merry
287ef270ab1SKenneth D. Merry ocs_assert(io_pool);
288ef270ab1SKenneth D. Merry
289ef270ab1SKenneth D. Merry ocs = io_pool->ocs;
290ef270ab1SKenneth D. Merry
291ef270ab1SKenneth D. Merry ocs_lock(&io_pool->lock);
292ef270ab1SKenneth D. Merry hio = io->hio;
293ef270ab1SKenneth D. Merry io->hio = NULL;
294ef270ab1SKenneth D. Merry ocs_pool_put(io_pool->pool, io);
295ef270ab1SKenneth D. Merry ocs_unlock(&io_pool->lock);
296ef270ab1SKenneth D. Merry
297ef270ab1SKenneth D. Merry if (hio) {
298ef270ab1SKenneth D. Merry ocs_hw_io_free(&ocs->hw, hio);
299ef270ab1SKenneth D. Merry }
300ef270ab1SKenneth D. Merry io->io_free = 1;
301ef270ab1SKenneth D. Merry ocs_atomic_sub_return(&ocs->xport->io_active_count, 1);
302ef270ab1SKenneth D. Merry ocs_atomic_add_return(&ocs->xport->io_total_free, 1);
303ef270ab1SKenneth D. Merry }
304ef270ab1SKenneth D. Merry
305ef270ab1SKenneth D. Merry /**
306ef270ab1SKenneth D. Merry * @ingroup io_alloc
307ef270ab1SKenneth D. Merry * @brief Find an I/O given it's node and ox_id.
308ef270ab1SKenneth D. Merry *
309ef270ab1SKenneth D. Merry * @param ocs Driver instance's software context.
310ef270ab1SKenneth D. Merry * @param node Pointer to node.
311ef270ab1SKenneth D. Merry * @param ox_id OX_ID to find.
312ef270ab1SKenneth D. Merry * @param rx_id RX_ID to find (0xffff for unassigned).
313ef270ab1SKenneth D. Merry */
314ef270ab1SKenneth D. Merry ocs_io_t *
ocs_io_find_tgt_io(ocs_t * ocs,ocs_node_t * node,uint16_t ox_id,uint16_t rx_id)315ef270ab1SKenneth D. Merry ocs_io_find_tgt_io(ocs_t *ocs, ocs_node_t *node, uint16_t ox_id, uint16_t rx_id)
316ef270ab1SKenneth D. Merry {
317ef270ab1SKenneth D. Merry ocs_io_t *io = NULL;
318ef270ab1SKenneth D. Merry
319ef270ab1SKenneth D. Merry ocs_lock(&node->active_ios_lock);
320ef270ab1SKenneth D. Merry ocs_list_foreach(&node->active_ios, io)
321ef270ab1SKenneth D. Merry if ((io->cmd_tgt && (io->init_task_tag == ox_id)) &&
322ef270ab1SKenneth D. Merry ((rx_id == 0xffff) || (io->tgt_task_tag == rx_id))) {
323ef270ab1SKenneth D. Merry break;
324ef270ab1SKenneth D. Merry }
325ef270ab1SKenneth D. Merry ocs_unlock(&node->active_ios_lock);
326ef270ab1SKenneth D. Merry return io;
327ef270ab1SKenneth D. Merry }
328ef270ab1SKenneth D. Merry
329ef270ab1SKenneth D. Merry /**
330ef270ab1SKenneth D. Merry * @ingroup io_alloc
331ef270ab1SKenneth D. Merry * @brief Return IO context given the instance index.
332ef270ab1SKenneth D. Merry *
333ef270ab1SKenneth D. Merry * @par Description
334ef270ab1SKenneth D. Merry * Returns a pointer to the IO context given by the instance index.
335ef270ab1SKenneth D. Merry *
336ef270ab1SKenneth D. Merry * @param ocs Pointer to driver structure.
337ef270ab1SKenneth D. Merry * @param index IO instance index to return.
338ef270ab1SKenneth D. Merry *
339ef270ab1SKenneth D. Merry * @return Returns a pointer to the IO context, or NULL if not found.
340ef270ab1SKenneth D. Merry */
341ef270ab1SKenneth D. Merry ocs_io_t *
ocs_io_get_instance(ocs_t * ocs,uint32_t index)342ef270ab1SKenneth D. Merry ocs_io_get_instance(ocs_t *ocs, uint32_t index)
343ef270ab1SKenneth D. Merry {
344ef270ab1SKenneth D. Merry ocs_xport_t *xport = ocs->xport;
345ef270ab1SKenneth D. Merry ocs_io_pool_t *io_pool = xport->io_pool;
346ef270ab1SKenneth D. Merry return ocs_pool_get_instance(io_pool->pool, index);
347ef270ab1SKenneth D. Merry }
348ef270ab1SKenneth D. Merry
349ef270ab1SKenneth D. Merry /**
350ef270ab1SKenneth D. Merry * @brief Generate IO context ddump data.
351ef270ab1SKenneth D. Merry *
352ef270ab1SKenneth D. Merry * The ddump data for an IO context is generated.
353ef270ab1SKenneth D. Merry *
354ef270ab1SKenneth D. Merry * @param textbuf Pointer to text buffer.
355ef270ab1SKenneth D. Merry * @param io Pointer to IO context.
356ef270ab1SKenneth D. Merry *
357ef270ab1SKenneth D. Merry * @return None.
358ef270ab1SKenneth D. Merry */
359ef270ab1SKenneth D. Merry
360ef270ab1SKenneth D. Merry void
ocs_ddump_io(ocs_textbuf_t * textbuf,ocs_io_t * io)361ef270ab1SKenneth D. Merry ocs_ddump_io(ocs_textbuf_t *textbuf, ocs_io_t *io)
362ef270ab1SKenneth D. Merry {
363ef270ab1SKenneth D. Merry ocs_ddump_section(textbuf, "io", io->instance_index);
364ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "display_name", "%s", io->display_name);
365ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "node_name", "%s", io->node->display_name);
366ef270ab1SKenneth D. Merry
367ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "ref_count", "%d", ocs_ref_read_count(&io->ref));
368ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "io_type", "%d", io->io_type);
369ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hio_type", "%d", io->hio_type);
370ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "cmd_tgt", "%d", io->cmd_tgt);
371ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "cmd_ini", "%d", io->cmd_ini);
372ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "send_abts", "%d", io->send_abts);
373ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "init_task_tag", "0x%x", io->init_task_tag);
374ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "tgt_task_tag", "0x%x", io->tgt_task_tag);
375ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_tag", "0x%x", io->hw_tag);
376ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "tag", "0x%x", io->tag);
377ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "timeout", "%d", io->timeout);
378ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "tmf_cmd", "%d", io->tmf_cmd);
379ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "abort_rx_id", "0x%x", io->abort_rx_id);
380ef270ab1SKenneth D. Merry
381ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "busy", "%d", ocs_io_busy(io));
382ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "transferred", "%zu", io->transferred);
383ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "auto_resp", "%d", io->auto_resp);
384ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "exp_xfer_len", "%d", io->exp_xfer_len);
385ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "xfer_req", "%d", io->xfer_req);
386ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "seq_init", "%d", io->seq_init);
387ef270ab1SKenneth D. Merry
388ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "alloc_link", "%d", ocs_list_on_list(&io->io_alloc_link));
389ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "pending_link", "%d", ocs_list_on_list(&io->io_pending_link));
390ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "backend_link", "%d", ocs_list_on_list(&io->link));
391ef270ab1SKenneth D. Merry
392ef270ab1SKenneth D. Merry if (io->hio) {
393ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_tag", "%#x", io->hio->reqtag);
394ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_xri", "%#x", io->hio->indicator);
395ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_type", "%#x", io->hio->type);
396ef270ab1SKenneth D. Merry } else {
397ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_tag", "%s", "pending");
398ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_xri", "%s", "pending");
399ef270ab1SKenneth D. Merry ocs_ddump_value(textbuf, "hw_type", "%s", "pending");
400ef270ab1SKenneth D. Merry }
401ef270ab1SKenneth D. Merry
402ef270ab1SKenneth D. Merry ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_IO, io);
403ef270ab1SKenneth D. Merry ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_IO, io);
404ef270ab1SKenneth D. Merry
405ef270ab1SKenneth D. Merry ocs_ddump_endsection(textbuf, "io", io->instance_index);
406ef270ab1SKenneth D. Merry }
407ef270ab1SKenneth D. Merry
408ef270ab1SKenneth D. Merry void
ocs_mgmt_io_list(ocs_textbuf_t * textbuf,void * object)409ef270ab1SKenneth D. Merry ocs_mgmt_io_list(ocs_textbuf_t *textbuf, void *object)
410ef270ab1SKenneth D. Merry {
411ef270ab1SKenneth D. Merry
412ef270ab1SKenneth D. Merry /* Readonly values */
413ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "display_name");
414ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "init_task_tag");
415ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "tag");
416ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "transferred");
417ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "auto_resp");
418ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "exp_xfer_len");
419ef270ab1SKenneth D. Merry ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "xfer_req");
420ef270ab1SKenneth D. Merry }
421ef270ab1SKenneth D. Merry
422ef270ab1SKenneth D. Merry int
ocs_mgmt_io_get(ocs_textbuf_t * textbuf,char * parent,char * name,void * object)423ef270ab1SKenneth D. Merry ocs_mgmt_io_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
424ef270ab1SKenneth D. Merry {
425ef270ab1SKenneth D. Merry char qualifier[80];
426ef270ab1SKenneth D. Merry int retval = -1;
427ef270ab1SKenneth D. Merry ocs_io_t *io = (ocs_io_t *) object;
428ef270ab1SKenneth D. Merry
429ef270ab1SKenneth D. Merry snprintf(qualifier, sizeof(qualifier), "%s/io[%d]", parent, io->instance_index);
430ef270ab1SKenneth D. Merry
431ef270ab1SKenneth D. Merry /* If it doesn't start with my qualifier I don't know what to do with it */
432ef270ab1SKenneth D. Merry if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
433ef270ab1SKenneth D. Merry char *unqualified_name = name + strlen(qualifier) +1;
434ef270ab1SKenneth D. Merry
435ef270ab1SKenneth D. Merry /* See if it's a value I can supply */
436ef270ab1SKenneth D. Merry if (ocs_strcmp(unqualified_name, "display_name") == 0) {
437ef270ab1SKenneth D. Merry ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", io->display_name);
438ef270ab1SKenneth D. Merry retval = 0;
439ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "init_task_tag") == 0) {
440ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "init_task_tag", "0x%x", io->init_task_tag);
441ef270ab1SKenneth D. Merry retval = 0;
442ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "tgt_task_tag") == 0) {
443ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tgt_task_tag", "0x%x", io->tgt_task_tag);
444ef270ab1SKenneth D. Merry retval = 0;
445ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "hw_tag") == 0) {
446ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_tag", "0x%x", io->hw_tag);
447ef270ab1SKenneth D. Merry retval = 0;
448ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "tag") == 0) {
449ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tag", "0x%x", io->tag);
450ef270ab1SKenneth D. Merry retval = 0;
451ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "transferred") == 0) {
452ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "transferred", "%zu", io->transferred);
453ef270ab1SKenneth D. Merry retval = 0;
454ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "auto_resp") == 0) {
455ef270ab1SKenneth D. Merry ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "auto_resp", io->auto_resp);
456ef270ab1SKenneth D. Merry retval = 0;
457ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "exp_xfer_len") == 0) {
458ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "exp_xfer_len", "%d", io->exp_xfer_len);
459ef270ab1SKenneth D. Merry retval = 0;
460ef270ab1SKenneth D. Merry } else if (ocs_strcmp(unqualified_name, "xfer_req") == 0) {
461ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "xfer_req", "%d", io->xfer_req);
462ef270ab1SKenneth D. Merry retval = 0;
463ef270ab1SKenneth D. Merry }
464ef270ab1SKenneth D. Merry }
465ef270ab1SKenneth D. Merry
466ef270ab1SKenneth D. Merry return retval;
467ef270ab1SKenneth D. Merry }
468ef270ab1SKenneth D. Merry
469ef270ab1SKenneth D. Merry void
ocs_mgmt_io_get_all(ocs_textbuf_t * textbuf,void * object)470ef270ab1SKenneth D. Merry ocs_mgmt_io_get_all(ocs_textbuf_t *textbuf, void *object)
471ef270ab1SKenneth D. Merry {
472ef270ab1SKenneth D. Merry ocs_io_t *io = (ocs_io_t *) object;
473ef270ab1SKenneth D. Merry
474ef270ab1SKenneth D. Merry ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", io->display_name);
475ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "init_task_tag", "0x%x", io->init_task_tag);
476ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tgt_task_tag", "0x%x", io->tgt_task_tag);
477ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_tag", "0x%x", io->hw_tag);
478ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tag", "0x%x", io->tag);
479ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "transferred", "%zu", io->transferred);
480ef270ab1SKenneth D. Merry ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "auto_resp", io->auto_resp);
481ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "exp_xfer_len", "%d", io->exp_xfer_len);
482ef270ab1SKenneth D. Merry ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "xfer_req", "%d", io->xfer_req);
483ef270ab1SKenneth D. Merry
484ef270ab1SKenneth D. Merry }
485