Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 385ad87d authored by Sagi Grimberg's avatar Sagi Grimberg Committed by Doug Ledford
Browse files

IB/iser: Introduce iser registration pool struct



Instead of having it a part of the connection structure,
have it be under a dedicated (embedded) structure in the
connection. A logical separation of the registration pool
and the connection structure.

Signed-off-by: default avatarSagi Grimberg <sagig@mellanox.com>
Signed-off-by: default avatarAdir Lev <adirl@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent eb6ea8c3
Loading
Loading
Loading
Loading
+29 −20
Original line number Diff line number Diff line
@@ -417,6 +417,33 @@ struct iser_fr_desc {
	struct iser_pi_context		 *pi_ctx;
};

/**
 * struct iser_fr_pool: connection fast registration pool
 *
 * @lock:                protects fmr/fastreg pool
 * @union.fmr:
 *     @pool:            FMR pool for fast registrations
 *     @page_vec:        fast reg page list to hold mapped commands pages
 *                       used for registration
 * @union.fastreg:
 *     @pool:            Fast registration descriptors pool for fast
 *                       registrations
 *     @pool_size:       Size of pool
 */
struct iser_fr_pool {
	spinlock_t		     lock;
	union {
		struct {
			struct ib_fmr_pool              *pool;
			struct iser_page_vec            *page_vec;
		} fmr;
		struct {
			struct list_head	 pool;
			int			 pool_size;
		} fastreg;
	};
};

/**
 * struct ib_conn - Infiniband related objects
 *
@@ -430,15 +457,7 @@ struct iser_fr_desc {
 * @pi_support:          Indicate device T10-PI support
 * @beacon:              beacon send wr to signal all flush errors were drained
 * @flush_comp:          completes when all connection completions consumed
 * @lock:                protects fmr/fastreg pool
 * @union.fmr:
 *     @pool:            FMR pool for fast registrations
 *     @page_vec:        page vector to hold mapped commands pages
 *                       used for registration
 * @union.fastreg:
 *     @pool:            Fast registration descriptors pool for fast
 *                       registrations
 *     @pool_size:       Size of pool
 * @fr_pool:             connection fast registration poool
 */
struct ib_conn {
	struct rdma_cm_id           *cma_id;
@@ -451,17 +470,7 @@ struct ib_conn {
	bool			     pi_support;
	struct ib_send_wr	     beacon;
	struct completion	     flush_comp;
	spinlock_t		     lock;
	union {
		struct {
			struct ib_fmr_pool      *pool;
			struct iser_page_vec	*page_vec;
		} fmr;
		struct {
			struct list_head	 pool;
			int			 pool_size;
		} fastreg;
	};
	struct iser_fr_pool          fr_pool;
};

/**
+18 −14
Original line number Diff line number Diff line
@@ -184,14 +184,15 @@ iser_copy_to_bounce(struct iser_data_buf *data)
struct iser_fr_desc *
iser_reg_desc_get(struct ib_conn *ib_conn)
{
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_fr_desc *desc;
	unsigned long flags;

	spin_lock_irqsave(&ib_conn->lock, flags);
	desc = list_first_entry(&ib_conn->fastreg.pool,
	spin_lock_irqsave(&fr_pool->lock, flags);
	desc = list_first_entry(&fr_pool->fastreg.pool,
				struct iser_fr_desc, list);
	list_del(&desc->list);
	spin_unlock_irqrestore(&ib_conn->lock, flags);
	spin_unlock_irqrestore(&fr_pool->lock, flags);

	return desc;
}
@@ -200,11 +201,12 @@ void
iser_reg_desc_put(struct ib_conn *ib_conn,
		  struct iser_fr_desc *desc)
{
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	unsigned long flags;

	spin_lock_irqsave(&ib_conn->lock, flags);
	list_add(&desc->list, &ib_conn->fastreg.pool);
	spin_unlock_irqrestore(&ib_conn->lock, flags);
	spin_lock_irqsave(&fr_pool->lock, flags);
	list_add(&desc->list, &fr_pool->fastreg.pool);
	spin_unlock_irqrestore(&fr_pool->lock, flags);
}

/**
@@ -480,6 +482,7 @@ int iser_reg_page_vec(struct iscsi_iser_task *iser_task,
		      struct iser_mem_reg *mem_reg)
{
	struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_device *device = ib_conn->device;
	struct ib_pool_fmr *fmr;
	int ret, plen;
@@ -496,7 +499,7 @@ int iser_reg_page_vec(struct iscsi_iser_task *iser_task,
		return -EINVAL;
	}

	fmr  = ib_fmr_pool_map_phys(ib_conn->fmr.pool,
	fmr  = ib_fmr_pool_map_phys(fr_pool->fmr.pool,
				    page_vec->pages,
				    page_vec->length,
				    page_vec->pages[0]);
@@ -560,6 +563,7 @@ int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *iser_task,
			  enum iser_data_dir cmd_dir)
{
	struct ib_conn *ib_conn = &iser_task->iser_conn->ib_conn;
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_device   *device = ib_conn->device;
	struct ib_device     *ibdev = device->ib_device;
	struct iser_data_buf *mem = &iser_task->data[cmd_dir];
@@ -583,20 +587,20 @@ int iser_reg_rdma_mem_fmr(struct iscsi_iser_task *iser_task,
	if (mem->dma_nents == 1) {
		return iser_reg_dma(device, mem, mem_reg);
	} else { /* use FMR for multiple dma entries */
		err = iser_reg_page_vec(iser_task, mem, ib_conn->fmr.page_vec,
					mem_reg);
		err = iser_reg_page_vec(iser_task, mem,
					fr_pool->fmr.page_vec, mem_reg);
		if (err && err != -EAGAIN) {
			iser_data_buf_dump(mem, ibdev);
			iser_err("mem->dma_nents = %d (dlength = 0x%x)\n",
				 mem->dma_nents,
				 ntoh24(iser_task->desc.iscsi_header.dlength));
			iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n",
				 ib_conn->fmr.page_vec->data_size,
				 ib_conn->fmr.page_vec->length,
				 ib_conn->fmr.page_vec->offset);
			for (i = 0; i < ib_conn->fmr.page_vec->length; i++)
				 fr_pool->fmr.page_vec->data_size,
				 fr_pool->fmr.page_vec->length,
				 fr_pool->fmr.page_vec->offset);
			for (i = 0; i < fr_pool->fmr.page_vec->length; i++)
				iser_err("page_vec[%d] = 0x%llx\n", i,
					 (unsigned long long)ib_conn->fmr.page_vec->pages[i]);
					 (unsigned long long)fr_pool->fmr.page_vec->pages[i]);
		}
		if (err)
			return err;
+35 −25
Original line number Diff line number Diff line
@@ -202,16 +202,21 @@ static void iser_free_device_ib_res(struct iser_device *device)
int iser_alloc_fmr_pool(struct ib_conn *ib_conn, unsigned cmds_max)
{
	struct iser_device *device = ib_conn->device;
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_page_vec *page_vec;
	struct ib_fmr_pool *fmr_pool;
	struct ib_fmr_pool_param params;
	int ret = -ENOMEM;

	ib_conn->fmr.page_vec = kmalloc(sizeof(*ib_conn->fmr.page_vec) +
	spin_lock_init(&fr_pool->lock);

	page_vec = kmalloc(sizeof(*page_vec) +
			   (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE + 1)),
			   GFP_KERNEL);
	if (!ib_conn->fmr.page_vec)
	if (!page_vec)
		return ret;

	ib_conn->fmr.page_vec->pages = (u64 *)(ib_conn->fmr.page_vec + 1);
	page_vec->pages = (u64 *)(page_vec + 1);

	params.page_shift        = SHIFT_4K;
	/* when the first/last SG element are not start/end *
@@ -227,18 +232,20 @@ int iser_alloc_fmr_pool(struct ib_conn *ib_conn, unsigned cmds_max)
				    IB_ACCESS_REMOTE_WRITE |
				    IB_ACCESS_REMOTE_READ);

	ib_conn->fmr.pool = ib_create_fmr_pool(device->pd, &params);
	if (IS_ERR(ib_conn->fmr.pool)) {
		ret = PTR_ERR(ib_conn->fmr.pool);
	fmr_pool = ib_create_fmr_pool(device->pd, &params);
	if (IS_ERR(fmr_pool)) {
		ret = PTR_ERR(fmr_pool);
		iser_err("FMR allocation failed, err %d\n", ret);
		goto err;
	}

	fr_pool->fmr.page_vec = page_vec;
	fr_pool->fmr.pool = fmr_pool;

	return 0;

err:
	kfree(ib_conn->fmr.page_vec);
	ib_conn->fmr.page_vec = NULL;
	kfree(page_vec);
	return ret;
}

@@ -247,14 +254,15 @@ int iser_alloc_fmr_pool(struct ib_conn *ib_conn, unsigned cmds_max)
 */
void iser_free_fmr_pool(struct ib_conn *ib_conn)
{
	iser_info("freeing conn %p fmr pool %p\n",
		  ib_conn, ib_conn->fmr.pool);
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;

	ib_destroy_fmr_pool(ib_conn->fmr.pool);
	ib_conn->fmr.pool = NULL;
	iser_info("freeing conn %p fmr pool %p\n",
		  ib_conn, fr_pool->fmr.pool);

	kfree(ib_conn->fmr.page_vec);
	ib_conn->fmr.page_vec = NULL;
	ib_destroy_fmr_pool(fr_pool->fmr.pool);
	fr_pool->fmr.pool = NULL;
	kfree(fr_pool->fmr.page_vec);
	fr_pool->fmr.page_vec = NULL;
}

static int
@@ -380,11 +388,13 @@ iser_create_fastreg_desc(struct ib_device *ib_device, struct ib_pd *pd,
int iser_alloc_fastreg_pool(struct ib_conn *ib_conn, unsigned cmds_max)
{
	struct iser_device *device = ib_conn->device;
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_fr_desc *desc;
	int i, ret;

	INIT_LIST_HEAD(&ib_conn->fastreg.pool);
	ib_conn->fastreg.pool_size = 0;
	INIT_LIST_HEAD(&fr_pool->fastreg.pool);
	spin_lock_init(&fr_pool->lock);
	fr_pool->fastreg.pool_size = 0;
	for (i = 0; i < cmds_max; i++) {
		desc = iser_create_fastreg_desc(device->ib_device, device->pd,
						ib_conn->pi_support);
@@ -393,8 +403,8 @@ int iser_alloc_fastreg_pool(struct ib_conn *ib_conn, unsigned cmds_max)
			goto err;
		}

		list_add_tail(&desc->list, &ib_conn->fastreg.pool);
		ib_conn->fastreg.pool_size++;
		list_add_tail(&desc->list, &fr_pool->fastreg.pool);
		fr_pool->fastreg.pool_size++;
	}

	return 0;
@@ -409,15 +419,16 @@ int iser_alloc_fastreg_pool(struct ib_conn *ib_conn, unsigned cmds_max)
 */
void iser_free_fastreg_pool(struct ib_conn *ib_conn)
{
	struct iser_fr_pool *fr_pool = &ib_conn->fr_pool;
	struct iser_fr_desc *desc, *tmp;
	int i = 0;

	if (list_empty(&ib_conn->fastreg.pool))
	if (list_empty(&fr_pool->fastreg.pool))
		return;

	iser_info("freeing conn %p fr pool\n", ib_conn);

	list_for_each_entry_safe(desc, tmp, &ib_conn->fastreg.pool, list) {
	list_for_each_entry_safe(desc, tmp, &fr_pool->fastreg.pool, list) {
		list_del(&desc->list);
		iser_free_reg_res(&desc->rsc);
		if (desc->pi_ctx)
@@ -426,9 +437,9 @@ void iser_free_fastreg_pool(struct ib_conn *ib_conn)
		++i;
	}

	if (i < ib_conn->fastreg.pool_size)
	if (i < fr_pool->fastreg.pool_size)
		iser_warn("pool still has %d regions registered\n",
			  ib_conn->fastreg.pool_size - i);
			  fr_pool->fastreg.pool_size - i);
}

/**
@@ -924,7 +935,6 @@ void iser_conn_init(struct iser_conn *iser_conn)
	init_completion(&iser_conn->ib_completion);
	init_completion(&iser_conn->up_completion);
	INIT_LIST_HEAD(&iser_conn->conn_list);
	spin_lock_init(&iser_conn->ib_conn.lock);
	mutex_init(&iser_conn->state_mutex);
}