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