brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · c612f0a Raw
191 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.5 */6 7#include "efct_driver.h"8#include "efct_hw.h"9#include "efct_io.h"10 11struct efct_io_pool {12	struct efct *efct;13	spinlock_t lock;	/* IO pool lock */14	u32 io_num_ios;		/* Total IOs allocated */15	struct efct_io *ios[EFCT_NUM_SCSI_IOS];16	struct list_head freelist;17 18};19 20struct efct_io_pool *21efct_io_pool_create(struct efct *efct, u32 num_sgl)22{23	u32 i = 0;24	struct efct_io_pool *io_pool;25	struct efct_io *io;26 27	/* Allocate the IO pool */28	io_pool = kzalloc(sizeof(*io_pool), GFP_KERNEL);29	if (!io_pool)30		return NULL;31 32	io_pool->efct = efct;33	INIT_LIST_HEAD(&io_pool->freelist);34	/* initialize IO pool lock */35	spin_lock_init(&io_pool->lock);36 37	for (i = 0; i < EFCT_NUM_SCSI_IOS; i++) {38		io = kzalloc(sizeof(*io), GFP_KERNEL);39		if (!io)40			break;41 42		io_pool->io_num_ios++;43		io_pool->ios[i] = io;44		io->tag = i;45		io->instance_index = i;46 47		/* Allocate a response buffer */48		io->rspbuf.size = SCSI_RSP_BUF_LENGTH;49		io->rspbuf.virt = dma_alloc_coherent(&efct->pci->dev,50						     io->rspbuf.size,51						     &io->rspbuf.phys, GFP_KERNEL);52		if (!io->rspbuf.virt) {53			efc_log_err(efct, "dma_alloc rspbuf failed\n");54			efct_io_pool_free(io_pool);55			return NULL;56		}57 58		/* Allocate SGL */59		io->sgl = kzalloc(sizeof(*io->sgl) * num_sgl, GFP_KERNEL);60		if (!io->sgl) {61			efct_io_pool_free(io_pool);62			return NULL;63		}64 65		io->sgl_allocated = num_sgl;66		io->sgl_count = 0;67 68		INIT_LIST_HEAD(&io->list_entry);69		list_add_tail(&io->list_entry, &io_pool->freelist);70	}71 72	return io_pool;73}74 75int76efct_io_pool_free(struct efct_io_pool *io_pool)77{78	struct efct *efct;79	u32 i;80	struct efct_io *io;81 82	if (io_pool) {83		efct = io_pool->efct;84 85		for (i = 0; i < io_pool->io_num_ios; i++) {86			io = io_pool->ios[i];87			if (!io)88				continue;89 90			kfree(io->sgl);91			dma_free_coherent(&efct->pci->dev,92					  io->rspbuf.size, io->rspbuf.virt,93					  io->rspbuf.phys);94			memset(&io->rspbuf, 0, sizeof(struct efc_dma));95		}96 97		kfree(io_pool);98		efct->xport->io_pool = NULL;99	}100 101	return 0;102}103 104struct efct_io *105efct_io_pool_io_alloc(struct efct_io_pool *io_pool)106{107	struct efct_io *io = NULL;108	struct efct *efct;109	unsigned long flags = 0;110 111	efct = io_pool->efct;112 113	spin_lock_irqsave(&io_pool->lock, flags);114 115	if (!list_empty(&io_pool->freelist)) {116		io = list_first_entry(&io_pool->freelist, struct efct_io,117				      list_entry);118		list_del_init(&io->list_entry);119	}120 121	spin_unlock_irqrestore(&io_pool->lock, flags);122 123	if (!io)124		return NULL;125 126	io->io_type = EFCT_IO_TYPE_MAX;127	io->hio_type = EFCT_HW_IO_MAX;128	io->hio = NULL;129	io->transferred = 0;130	io->efct = efct;131	io->timeout = 0;132	io->sgl_count = 0;133	io->tgt_task_tag = 0;134	io->init_task_tag = 0;135	io->hw_tag = 0;136	io->display_name = "pending";137	io->seq_init = 0;138	io->io_free = 0;139	io->release = NULL;140	atomic_add_return(1, &efct->xport->io_active_count);141	atomic_add_return(1, &efct->xport->io_total_alloc);142	return io;143}144 145/* Free an object used to track an IO */146void147efct_io_pool_io_free(struct efct_io_pool *io_pool, struct efct_io *io)148{149	struct efct *efct;150	struct efct_hw_io *hio = NULL;151	unsigned long flags = 0;152 153	efct = io_pool->efct;154 155	spin_lock_irqsave(&io_pool->lock, flags);156	hio = io->hio;157	io->hio = NULL;158	io->io_free = 1;159	INIT_LIST_HEAD(&io->list_entry);160	list_add(&io->list_entry, &io_pool->freelist);161	spin_unlock_irqrestore(&io_pool->lock, flags);162 163	if (hio)164		efct_hw_io_free(&efct->hw, hio);165 166	atomic_sub_return(1, &efct->xport->io_active_count);167	atomic_add_return(1, &efct->xport->io_total_free);168}169 170/* Find an I/O given it's node and ox_id */171struct efct_io *172efct_io_find_tgt_io(struct efct *efct, struct efct_node *node,173		    u16 ox_id, u16 rx_id)174{175	struct efct_io	*io = NULL;176	unsigned long flags = 0;177	u8 found = false;178 179	spin_lock_irqsave(&node->active_ios_lock, flags);180	list_for_each_entry(io, &node->active_ios, list_entry) {181		if ((io->cmd_tgt && io->init_task_tag == ox_id) &&182		    (rx_id == 0xffff || io->tgt_task_tag == rx_id)) {183			if (kref_get_unless_zero(&io->ref))184				found = true;185			break;186		}187	}188	spin_unlock_irqrestore(&node->active_ios_lock, flags);189	return found ? io : NULL;190}191