1331766Sken/*-
2331766Sken * Copyright (c) 2017 Broadcom. All rights reserved.
3331766Sken * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4331766Sken *
5331766Sken * Redistribution and use in source and binary forms, with or without
6331766Sken * modification, are permitted provided that the following conditions are met:
7331766Sken *
8331766Sken * 1. Redistributions of source code must retain the above copyright notice,
9331766Sken *    this list of conditions and the following disclaimer.
10331766Sken *
11331766Sken * 2. Redistributions in binary form must reproduce the above copyright notice,
12331766Sken *    this list of conditions and the following disclaimer in the documentation
13331766Sken *    and/or other materials provided with the distribution.
14331766Sken *
15331766Sken * 3. Neither the name of the copyright holder nor the names of its contributors
16331766Sken *    may be used to endorse or promote products derived from this software
17331766Sken *    without specific prior written permission.
18331766Sken *
19331766Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20331766Sken * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21331766Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22331766Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23331766Sken * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24331766Sken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25331766Sken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26331766Sken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27331766Sken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28331766Sken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29331766Sken * POSSIBILITY OF SUCH DAMAGE.
30331766Sken *
31331766Sken * $FreeBSD: stable/11/sys/dev/ocs_fc/ocs_io.c 331766 2018-03-30 15:28:25Z ken $
32331766Sken */
33331766Sken
34331766Sken/**
35331766Sken * @file
36331766Sken * Provide IO object allocation.
37331766Sken */
38331766Sken
39331766Sken/*!
40331766Sken * @defgroup io_alloc IO allocation
41331766Sken */
42331766Sken
43331766Sken#include "ocs.h"
44331766Sken#include "ocs_scsi.h"
45331766Sken#include "ocs_els.h"
46331766Sken#include "ocs_utils.h"
47331766Sken
48331766Skenvoid ocs_mgmt_io_list(ocs_textbuf_t *textbuf, void *io);
49331766Skenvoid ocs_mgmt_io_get_all(ocs_textbuf_t *textbuf, void *io);
50331766Skenint ocs_mgmt_io_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *io);
51331766Sken
52331766Skenstatic ocs_mgmt_functions_t io_mgmt_functions = {
53331766Sken	.get_list_handler	=	ocs_mgmt_io_list,
54331766Sken	.get_handler		=	ocs_mgmt_io_get,
55331766Sken	.get_all_handler	=	ocs_mgmt_io_get_all,
56331766Sken};
57331766Sken
58331766Sken/**
59331766Sken * @brief IO pool.
60331766Sken *
61331766Sken * Structure encapsulating a pool of IO objects.
62331766Sken *
63331766Sken */
64331766Sken
65331766Skenstruct ocs_io_pool_s {
66331766Sken	ocs_t *ocs;			/* Pointer to device object */
67331766Sken	ocs_lock_t lock;		/* IO pool lock */
68331766Sken	uint32_t io_num_ios;		/* Total IOs allocated */
69331766Sken	ocs_pool_t *pool;
70331766Sken};
71331766Sken
72331766Sken/**
73331766Sken * @brief Create a pool of IO objects.
74331766Sken *
75331766Sken * @par Description
76331766Sken * This function allocates memory in larger chucks called
77331766Sken * "slabs" which are a fixed size. It calculates the number of IO objects that
78331766Sken * fit within each "slab" and determines the number of "slabs" required to
79331766Sken * allocate the number of IOs requested. Each of the slabs is allocated and
80331766Sken * then it grabs each IO object within the slab and adds it to the free list.
81331766Sken * Individual command, response and SGL DMA buffers are allocated for each IO.
82331766Sken *
83331766Sken *           "Slabs"
84331766Sken *      +----------------+
85331766Sken *      |                |
86331766Sken *   +----------------+  |
87331766Sken *   |    IO          |  |
88331766Sken *   +----------------+  |
89331766Sken *   |    ...         |  |
90331766Sken *   +----------------+__+
91331766Sken *   |    IO          |
92331766Sken *   +----------------+
93331766Sken *
94331766Sken * @param ocs Driver instance's software context.
95331766Sken * @param num_io Number of IO contexts to allocate.
96331766Sken * @param num_sgl Number of SGL entries to allocate for each IO.
97331766Sken *
98331766Sken * @return Returns a pointer to a new ocs_io_pool_t on success,
99331766Sken *         or NULL on failure.
100331766Sken */
101331766Sken
102331766Skenocs_io_pool_t *
103331766Skenocs_io_pool_create(ocs_t *ocs, uint32_t num_io, uint32_t num_sgl)
104331766Sken{
105331766Sken	uint32_t i = 0;
106331766Sken	int32_t	rc = -1;
107331766Sken	ocs_io_pool_t *io_pool;
108331766Sken
109331766Sken	/* Allocate the IO pool */
110331766Sken	io_pool = ocs_malloc(ocs, sizeof(*io_pool), OCS_M_ZERO | OCS_M_NOWAIT);
111331766Sken	if (io_pool == NULL) {
112331766Sken		ocs_log_err(ocs, "allocate of IO pool failed\n");
113331766Sken		return NULL;;
114331766Sken	}
115331766Sken
116331766Sken	io_pool->ocs = ocs;
117331766Sken	io_pool->io_num_ios = num_io;
118331766Sken
119331766Sken	/* initialize IO pool lock */
120331766Sken	ocs_lock_init(ocs, &io_pool->lock, "io_pool lock[%d]", ocs->instance_index);
121331766Sken
122331766Sken	io_pool->pool = ocs_pool_alloc(ocs, sizeof(ocs_io_t), io_pool->io_num_ios, FALSE);
123331766Sken
124331766Sken	for (i = 0; i < io_pool->io_num_ios; i++) {
125331766Sken		ocs_io_t *io = ocs_pool_get_instance(io_pool->pool, i);
126331766Sken
127331766Sken		io->tag = i;
128331766Sken		io->instance_index = i;
129331766Sken		io->ocs = ocs;
130331766Sken
131331766Sken		/* allocate a command/response dma buffer */
132331766Sken		if (ocs->enable_ini) {
133331766Sken			rc = ocs_dma_alloc(ocs, &io->cmdbuf, SCSI_CMD_BUF_LENGTH, OCS_MIN_DMA_ALIGNMENT);
134331766Sken			if (rc) {
135331766Sken				ocs_log_err(ocs, "ocs_dma_alloc cmdbuf failed\n");
136331766Sken				ocs_io_pool_free(io_pool);
137331766Sken				return NULL;
138331766Sken			}
139331766Sken		}
140331766Sken
141331766Sken		/* Allocate a response buffer */
142331766Sken		rc = ocs_dma_alloc(ocs, &io->rspbuf, SCSI_RSP_BUF_LENGTH, OCS_MIN_DMA_ALIGNMENT);
143331766Sken		if (rc) {
144331766Sken			ocs_log_err(ocs, "ocs_dma_alloc cmdbuf failed\n");
145331766Sken			ocs_io_pool_free(io_pool);
146331766Sken			return NULL;
147331766Sken		}
148331766Sken
149331766Sken		/* Allocate SGL */
150331766Sken		io->sgl = ocs_malloc(ocs, sizeof(*io->sgl) * num_sgl, OCS_M_NOWAIT | OCS_M_ZERO);
151331766Sken		if (io->sgl == NULL) {
152331766Sken			ocs_log_err(ocs, "malloc sgl's failed\n");
153331766Sken			ocs_io_pool_free(io_pool);
154331766Sken			return NULL;
155331766Sken		}
156331766Sken		io->sgl_allocated = num_sgl;
157331766Sken		io->sgl_count = 0;
158331766Sken
159331766Sken		/* Make IO backend call to initialize IO */
160331766Sken		ocs_scsi_tgt_io_init(io);
161331766Sken		ocs_scsi_ini_io_init(io);
162331766Sken
163331766Sken		rc = ocs_dma_alloc(ocs, &io->els_req, OCS_ELS_REQ_LEN, OCS_MIN_DMA_ALIGNMENT);
164331766Sken		if (rc) {
165331766Sken			ocs_log_err(ocs, "ocs_dma_alloc els_req failed\n");
166331766Sken			ocs_io_pool_free(io_pool);
167331766Sken			return NULL;
168331766Sken 		}
169331766Sken
170331766Sken		rc = ocs_dma_alloc(ocs, &io->els_rsp, OCS_ELS_GID_PT_RSP_LEN, OCS_MIN_DMA_ALIGNMENT);
171331766Sken		if (rc) {
172331766Sken			ocs_log_err(ocs, "ocs_dma_alloc els_rsp failed\n");
173331766Sken			ocs_io_pool_free(io_pool);
174331766Sken			return NULL;
175331766Sken 		}
176331766Sken	}
177331766Sken
178331766Sken	return io_pool;
179331766Sken}
180331766Sken
181331766Sken/**
182331766Sken * @brief Free IO objects pool
183331766Sken *
184331766Sken * @par Description
185331766Sken * The pool of IO objects are freed.
186331766Sken *
187331766Sken * @param io_pool Pointer to IO pool object.
188331766Sken *
189331766Sken * @return Returns 0 on success, or a negative error code value on failure.
190331766Sken */
191331766Skenint32_t
192331766Skenocs_io_pool_free(ocs_io_pool_t *io_pool)
193331766Sken{
194331766Sken	ocs_t *ocs;
195331766Sken	uint32_t i;
196331766Sken	ocs_io_t *io;
197331766Sken
198331766Sken	if (io_pool != NULL) {
199331766Sken		ocs = io_pool->ocs;
200331766Sken		for (i = 0; i < io_pool->io_num_ios; i++) {
201331766Sken			io = ocs_pool_get_instance(io_pool->pool, i);
202331766Sken			if (!io)
203331766Sken				continue;
204331766Sken			ocs_scsi_tgt_io_exit(io);
205331766Sken			ocs_scsi_ini_io_exit(io);
206331766Sken			if (io->sgl) {
207331766Sken				ocs_free(ocs, io->sgl, sizeof(*io->sgl) * io->sgl_allocated);
208331766Sken			}
209331766Sken			ocs_dma_free(ocs, &io->cmdbuf);
210331766Sken			ocs_dma_free(ocs, &io->rspbuf);
211331766Sken			ocs_dma_free(ocs, &io->els_req);
212331766Sken			ocs_dma_free(ocs, &io->els_rsp);
213331766Sken		}
214331766Sken
215331766Sken		if (io_pool->pool != NULL) {
216331766Sken			ocs_pool_free(io_pool->pool);
217331766Sken		}
218331766Sken		ocs_lock_free(&io_pool->lock);
219331766Sken		ocs_free(ocs, io_pool, sizeof(*io_pool));
220331766Sken		ocs->xport->io_pool = NULL;
221331766Sken	}
222331766Sken
223331766Sken	return 0;
224331766Sken}
225331766Sken
226331766Skenuint32_t ocs_io_pool_allocated(ocs_io_pool_t *io_pool)
227331766Sken{
228331766Sken	return io_pool->io_num_ios;
229331766Sken}
230331766Sken
231331766Sken/**
232331766Sken * @ingroup io_alloc
233331766Sken * @brief Allocate an object used to track an IO.
234331766Sken *
235331766Sken * @param io_pool Pointer to the IO pool.
236331766Sken *
237331766Sken * @return Returns the pointer to a new object, or NULL if none available.
238331766Sken */
239331766Skenocs_io_t *
240331766Skenocs_io_pool_io_alloc(ocs_io_pool_t *io_pool)
241331766Sken{
242331766Sken	ocs_io_t *io = NULL;
243331766Sken	ocs_t *ocs;
244331766Sken
245331766Sken	ocs_assert(io_pool, NULL);
246331766Sken
247331766Sken	ocs = io_pool->ocs;
248331766Sken
249331766Sken	ocs_lock(&io_pool->lock);
250331766Sken	if ((io = ocs_pool_get(io_pool->pool)) != NULL) {
251331766Sken		ocs_unlock(&io_pool->lock);
252331766Sken
253331766Sken		io->io_type = OCS_IO_TYPE_MAX;
254331766Sken		io->hio_type = OCS_HW_IO_MAX;
255331766Sken		io->hio = NULL;
256331766Sken		io->transferred = 0;
257331766Sken		io->ocs = ocs;
258331766Sken		io->timeout = 0;
259331766Sken		io->sgl_count = 0;
260331766Sken		io->tgt_task_tag = 0;
261331766Sken		io->init_task_tag = 0;
262331766Sken		io->hw_tag = 0;
263331766Sken		io->display_name = "pending";
264331766Sken		io->seq_init = 0;
265331766Sken		io->els_req_free = 0;
266331766Sken		io->mgmt_functions = &io_mgmt_functions;
267331766Sken		io->io_free = 0;
268331766Sken		ocs_atomic_add_return(&ocs->xport->io_active_count, 1);
269331766Sken		ocs_atomic_add_return(&ocs->xport->io_total_alloc, 1);
270331766Sken	} else {
271331766Sken		ocs_unlock(&io_pool->lock);
272331766Sken	}
273331766Sken	return io;
274331766Sken}
275331766Sken
276331766Sken/**
277331766Sken * @ingroup io_alloc
278331766Sken * @brief Free an object used to track an IO.
279331766Sken *
280331766Sken * @param io_pool Pointer to IO pool object.
281331766Sken * @param io Pointer to the IO object.
282331766Sken */
283331766Skenvoid
284331766Skenocs_io_pool_io_free(ocs_io_pool_t *io_pool, ocs_io_t *io)
285331766Sken{
286331766Sken	ocs_t *ocs;
287331766Sken	ocs_hw_io_t *hio = NULL;
288331766Sken
289331766Sken	ocs_assert(io_pool);
290331766Sken
291331766Sken	ocs = io_pool->ocs;
292331766Sken
293331766Sken	ocs_lock(&io_pool->lock);
294331766Sken		hio = io->hio;
295331766Sken		io->hio = NULL;
296331766Sken		ocs_pool_put(io_pool->pool, io);
297331766Sken	ocs_unlock(&io_pool->lock);
298331766Sken
299331766Sken	if (hio) {
300331766Sken		ocs_hw_io_free(&ocs->hw, hio);
301331766Sken	}
302331766Sken	io->io_free = 1;
303331766Sken	ocs_atomic_sub_return(&ocs->xport->io_active_count, 1);
304331766Sken	ocs_atomic_add_return(&ocs->xport->io_total_free, 1);
305331766Sken}
306331766Sken
307331766Sken/**
308331766Sken * @ingroup io_alloc
309331766Sken * @brief Find an I/O given it's node and ox_id.
310331766Sken *
311331766Sken * @param ocs Driver instance's software context.
312331766Sken * @param node Pointer to node.
313331766Sken * @param ox_id OX_ID to find.
314331766Sken * @param rx_id RX_ID to find (0xffff for unassigned).
315331766Sken */
316331766Skenocs_io_t *
317331766Skenocs_io_find_tgt_io(ocs_t *ocs, ocs_node_t *node, uint16_t ox_id, uint16_t rx_id)
318331766Sken{
319331766Sken	ocs_io_t	*io = NULL;
320331766Sken
321331766Sken	ocs_lock(&node->active_ios_lock);
322331766Sken		ocs_list_foreach(&node->active_ios, io)
323331766Sken			if ((io->cmd_tgt && (io->init_task_tag == ox_id)) &&
324331766Sken			    ((rx_id == 0xffff) || (io->tgt_task_tag == rx_id))) {
325331766Sken				break;
326331766Sken			}
327331766Sken	ocs_unlock(&node->active_ios_lock);
328331766Sken	return io;
329331766Sken}
330331766Sken
331331766Sken/**
332331766Sken * @ingroup io_alloc
333331766Sken * @brief Return IO context given the instance index.
334331766Sken *
335331766Sken * @par Description
336331766Sken * Returns a pointer to the IO context given by the instance index.
337331766Sken *
338331766Sken * @param ocs Pointer to driver structure.
339331766Sken * @param index IO instance index to return.
340331766Sken *
341331766Sken * @return Returns a pointer to the IO context, or NULL if not found.
342331766Sken */
343331766Skenocs_io_t *
344331766Skenocs_io_get_instance(ocs_t *ocs, uint32_t index)
345331766Sken{
346331766Sken	ocs_xport_t *xport = ocs->xport;
347331766Sken	ocs_io_pool_t *io_pool = xport->io_pool;
348331766Sken	return ocs_pool_get_instance(io_pool->pool, index);
349331766Sken}
350331766Sken
351331766Sken/**
352331766Sken * @brief Generate IO context ddump data.
353331766Sken *
354331766Sken * The ddump data for an IO context is generated.
355331766Sken *
356331766Sken * @param textbuf Pointer to text buffer.
357331766Sken * @param io Pointer to IO context.
358331766Sken *
359331766Sken * @return None.
360331766Sken */
361331766Sken
362331766Skenvoid
363331766Skenocs_ddump_io(ocs_textbuf_t *textbuf, ocs_io_t *io)
364331766Sken{
365331766Sken	ocs_ddump_section(textbuf, "io", io->instance_index);
366331766Sken	ocs_ddump_value(textbuf, "display_name", "%s", io->display_name);
367331766Sken	ocs_ddump_value(textbuf, "node_name", "%s", io->node->display_name);
368331766Sken
369331766Sken	ocs_ddump_value(textbuf, "ref_count", "%d", ocs_ref_read_count(&io->ref));
370331766Sken	ocs_ddump_value(textbuf, "io_type", "%d", io->io_type);
371331766Sken	ocs_ddump_value(textbuf, "hio_type", "%d", io->hio_type);
372331766Sken	ocs_ddump_value(textbuf, "cmd_tgt", "%d", io->cmd_tgt);
373331766Sken	ocs_ddump_value(textbuf, "cmd_ini", "%d", io->cmd_ini);
374331766Sken	ocs_ddump_value(textbuf, "send_abts", "%d", io->send_abts);
375331766Sken	ocs_ddump_value(textbuf, "init_task_tag", "0x%x", io->init_task_tag);
376331766Sken	ocs_ddump_value(textbuf, "tgt_task_tag", "0x%x", io->tgt_task_tag);
377331766Sken	ocs_ddump_value(textbuf, "hw_tag", "0x%x", io->hw_tag);
378331766Sken	ocs_ddump_value(textbuf, "tag", "0x%x", io->tag);
379331766Sken	ocs_ddump_value(textbuf, "timeout", "%d", io->timeout);
380331766Sken	ocs_ddump_value(textbuf, "tmf_cmd", "%d", io->tmf_cmd);
381331766Sken	ocs_ddump_value(textbuf, "abort_rx_id", "0x%x", io->abort_rx_id);
382331766Sken
383331766Sken	ocs_ddump_value(textbuf, "busy", "%d", ocs_io_busy(io));
384331766Sken	ocs_ddump_value(textbuf, "transferred", "%zu", io->transferred);
385331766Sken	ocs_ddump_value(textbuf, "auto_resp", "%d", io->auto_resp);
386331766Sken	ocs_ddump_value(textbuf, "exp_xfer_len", "%d", io->exp_xfer_len);
387331766Sken	ocs_ddump_value(textbuf, "xfer_req", "%d", io->xfer_req);
388331766Sken	ocs_ddump_value(textbuf, "seq_init", "%d", io->seq_init);
389331766Sken
390331766Sken	ocs_ddump_value(textbuf, "alloc_link", "%d", ocs_list_on_list(&io->io_alloc_link));
391331766Sken	ocs_ddump_value(textbuf, "pending_link", "%d", ocs_list_on_list(&io->io_pending_link));
392331766Sken	ocs_ddump_value(textbuf, "backend_link", "%d", ocs_list_on_list(&io->link));
393331766Sken
394331766Sken	if (io->hio) {
395331766Sken		ocs_ddump_value(textbuf, "hw_tag", "%#x", io->hio->reqtag);
396331766Sken		ocs_ddump_value(textbuf, "hw_xri", "%#x", io->hio->indicator);
397331766Sken		ocs_ddump_value(textbuf, "hw_type", "%#x", io->hio->type);
398331766Sken	} else {
399331766Sken		ocs_ddump_value(textbuf, "hw_tag", "%s", "pending");
400331766Sken		ocs_ddump_value(textbuf, "hw_xri", "%s", "pending");
401331766Sken		ocs_ddump_value(textbuf, "hw_type", "%s", "pending");
402331766Sken	}
403331766Sken
404331766Sken	ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_IO, io);
405331766Sken	ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_IO, io);
406331766Sken
407331766Sken	ocs_ddump_endsection(textbuf, "io", io->instance_index);
408331766Sken}
409331766Sken
410331766Sken
411331766Skenvoid
412331766Skenocs_mgmt_io_list(ocs_textbuf_t *textbuf, void *object)
413331766Sken{
414331766Sken
415331766Sken	/* Readonly values */
416331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "display_name");
417331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "init_task_tag");
418331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "tag");
419331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "transferred");
420331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "auto_resp");
421331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "exp_xfer_len");
422331766Sken	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "xfer_req");
423331766Sken}
424331766Sken
425331766Skenint
426331766Skenocs_mgmt_io_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
427331766Sken{
428331766Sken	char qualifier[80];
429331766Sken	int retval = -1;
430331766Sken	ocs_io_t *io = (ocs_io_t *) object;
431331766Sken
432331766Sken	snprintf(qualifier, sizeof(qualifier), "%s/io[%d]", parent, io->instance_index);
433331766Sken
434331766Sken	/* If it doesn't start with my qualifier I don't know what to do with it */
435331766Sken	if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
436331766Sken		char *unqualified_name = name + strlen(qualifier) +1;
437331766Sken
438331766Sken		/* See if it's a value I can supply */
439331766Sken		if (ocs_strcmp(unqualified_name, "display_name") == 0) {
440331766Sken			ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", io->display_name);
441331766Sken			retval = 0;
442331766Sken		} else if (ocs_strcmp(unqualified_name, "init_task_tag") == 0) {
443331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "init_task_tag", "0x%x", io->init_task_tag);
444331766Sken			retval = 0;
445331766Sken		} else if (ocs_strcmp(unqualified_name, "tgt_task_tag") == 0) {
446331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tgt_task_tag", "0x%x", io->tgt_task_tag);
447331766Sken			retval = 0;
448331766Sken		} else if (ocs_strcmp(unqualified_name, "hw_tag") == 0) {
449331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_tag", "0x%x", io->hw_tag);
450331766Sken			retval = 0;
451331766Sken		} else if (ocs_strcmp(unqualified_name, "tag") == 0) {
452331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tag", "0x%x", io->tag);
453331766Sken			retval = 0;
454331766Sken		} else if (ocs_strcmp(unqualified_name, "transferred") == 0) {
455331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "transferred", "%zu", io->transferred);
456331766Sken			retval = 0;
457331766Sken		} else if (ocs_strcmp(unqualified_name, "auto_resp") == 0) {
458331766Sken			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "auto_resp", io->auto_resp);
459331766Sken			retval = 0;
460331766Sken		} else if (ocs_strcmp(unqualified_name, "exp_xfer_len") == 0) {
461331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "exp_xfer_len", "%d", io->exp_xfer_len);
462331766Sken			retval = 0;
463331766Sken		} else if (ocs_strcmp(unqualified_name, "xfer_req") == 0) {
464331766Sken			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "xfer_req", "%d", io->xfer_req);
465331766Sken			retval = 0;
466331766Sken		}
467331766Sken	}
468331766Sken
469331766Sken	return retval;
470331766Sken}
471331766Sken
472331766Skenvoid
473331766Skenocs_mgmt_io_get_all(ocs_textbuf_t *textbuf, void *object)
474331766Sken{
475331766Sken	ocs_io_t *io = (ocs_io_t *) object;
476331766Sken
477331766Sken	ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", io->display_name);
478331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "init_task_tag", "0x%x", io->init_task_tag);
479331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tgt_task_tag", "0x%x", io->tgt_task_tag);
480331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_tag", "0x%x", io->hw_tag);
481331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tag", "0x%x", io->tag);
482331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "transferred", "%zu", io->transferred);
483331766Sken	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "auto_resp", io->auto_resp);
484331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "exp_xfer_len", "%d", io->exp_xfer_len);
485331766Sken	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "xfer_req", "%d", io->xfer_req);
486331766Sken
487331766Sken}
488331766Sken
489331766Sken
490331766Sken
491331766Sken
492