iser_initiator.c 19.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
/*
 * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *	- Redistributions of source code must retain the above
 *	  copyright notice, this list of conditions and the following
 *	  disclaimer.
 *
 *	- Redistributions in binary form must reproduce the above
 *	  copyright notice, this list of conditions and the following
 *	  disclaimer in the documentation and/or other materials
 *	  provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * $Id: iser_initiator.c 6964 2006-05-07 11:11:43Z ogerlitz $
 */
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/kfifo.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>

#include "iscsi_iser.h"

/* Constant PDU lengths calculations */
#define ISER_TOTAL_HEADERS_LEN  (sizeof (struct iser_hdr) + \
				 sizeof (struct iscsi_hdr))

/* iser_dto_add_regd_buff - increments the reference count for *
 * the registered buffer & adds it to the DTO object           */
static void iser_dto_add_regd_buff(struct iser_dto *dto,
				   struct iser_regd_buf *regd_buf,
				   unsigned long use_offset,
				   unsigned long use_size)
{
	int add_idx;

	atomic_inc(&regd_buf->ref_count);

	add_idx = dto->regd_vector_len;
	dto->regd[add_idx] = regd_buf;
	dto->used_sz[add_idx] = use_size;
	dto->offset[add_idx] = use_offset;

	dto->regd_vector_len++;
}

/* Register user buffer memory and initialize passive rdma
 *  dto descriptor. Total data size is stored in
69
 *  iser_task->data[ISER_DIR_IN].data_len
70
 */
71
static int iser_prepare_read_cmd(struct iscsi_task *task,
72 73 74
				 unsigned int edtl)

{
75
	struct iscsi_iser_task *iser_task = task->dd_data;
76 77
	struct iser_regd_buf *regd_buf;
	int err;
78 79
	struct iser_hdr *hdr = &iser_task->desc.iser_header;
	struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN];
80

81
	err = iser_dma_map_task_data(iser_task,
82 83 84 85 86 87
				     buf_in,
				     ISER_DIR_IN,
				     DMA_FROM_DEVICE);
	if (err)
		return err;

88
	if (edtl > iser_task->data[ISER_DIR_IN].data_len) {
89 90
		iser_err("Total data length: %ld, less than EDTL: "
			 "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
91 92
			 iser_task->data[ISER_DIR_IN].data_len, edtl,
			 task->itt, iser_task->iser_conn);
93 94 95
		return -EINVAL;
	}

96
	err = iser_reg_rdma_mem(iser_task,ISER_DIR_IN);
97 98 99 100
	if (err) {
		iser_err("Failed to set up Data-IN RDMA\n");
		return err;
	}
101
	regd_buf = &iser_task->rdma_regd[ISER_DIR_IN];
102 103 104 105 106 107

	hdr->flags    |= ISER_RSV;
	hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
	hdr->read_va   = cpu_to_be64(regd_buf->reg.va);

	iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
108
		 task->itt, regd_buf->reg.rkey,
109 110 111 112 113 114 115
		 (unsigned long long)regd_buf->reg.va);

	return 0;
}

/* Register user buffer memory and initialize passive rdma
 *  dto descriptor. Total data size is stored in
116
 *  task->data[ISER_DIR_OUT].data_len
117 118
 */
static int
119
iser_prepare_write_cmd(struct iscsi_task *task,
120 121 122 123
		       unsigned int imm_sz,
		       unsigned int unsol_sz,
		       unsigned int edtl)
{
124
	struct iscsi_iser_task *iser_task = task->dd_data;
125 126
	struct iser_regd_buf *regd_buf;
	int err;
127 128 129
	struct iser_dto *send_dto = &iser_task->desc.dto;
	struct iser_hdr *hdr = &iser_task->desc.iser_header;
	struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
130

131
	err = iser_dma_map_task_data(iser_task,
132 133 134 135 136 137
				     buf_out,
				     ISER_DIR_OUT,
				     DMA_TO_DEVICE);
	if (err)
		return err;

138
	if (edtl > iser_task->data[ISER_DIR_OUT].data_len) {
139 140
		iser_err("Total data length: %ld, less than EDTL: %d, "
			 "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
141 142
			 iser_task->data[ISER_DIR_OUT].data_len,
			 edtl, task->itt, task->conn);
143 144 145
		return -EINVAL;
	}

146
	err = iser_reg_rdma_mem(iser_task,ISER_DIR_OUT);
147 148 149 150 151
	if (err != 0) {
		iser_err("Failed to register write cmd RDMA mem\n");
		return err;
	}

152
	regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
153 154 155 156 157 158 159 160

	if (unsol_sz < edtl) {
		hdr->flags     |= ISER_WSV;
		hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey);
		hdr->write_va   = cpu_to_be64(regd_buf->reg.va + unsol_sz);

		iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
			 "VA:%#llX + unsol:%d\n",
161
			 task->itt, regd_buf->reg.rkey,
162 163 164 165 166
			 (unsigned long long)regd_buf->reg.va, unsol_sz);
	}

	if (imm_sz > 0) {
		iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
167
			 task->itt, imm_sz);
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
		iser_dto_add_regd_buff(send_dto,
				       regd_buf,
				       0,
				       imm_sz);
	}

	return 0;
}

/**
 * iser_post_receive_control - allocates, initializes and posts receive DTO.
 */
static int iser_post_receive_control(struct iscsi_conn *conn)
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;
	struct iser_desc     *rx_desc;
	struct iser_regd_buf *regd_hdr;
	struct iser_regd_buf *regd_data;
	struct iser_dto      *recv_dto = NULL;
	struct iser_device  *device = iser_conn->ib_conn->device;
	int rx_data_size, err = 0;

	rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
	if (rx_desc == NULL) {
		iser_err("Failed to alloc desc for post recv\n");
		return -ENOMEM;
	}
	rx_desc->type = ISCSI_RX;

	/* for the login sequence we must support rx of upto 8K; login is done
	 * after conn create/bind (connect) and conn stop/bind (reconnect),
	 * what's common for both schemes is that the connection is not started
	 */
	if (conn->c_stage != ISCSI_CONN_STARTED)
202
		rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
203 204 205 206 207 208 209 210 211 212 213
	else /* FIXME till user space sets conn->max_recv_dlength correctly */
		rx_data_size = 128;

	rx_desc->data = kmalloc(rx_data_size, GFP_NOIO);
	if (rx_desc->data == NULL) {
		iser_err("Failed to alloc data buf for post recv\n");
		err = -ENOMEM;
		goto post_rx_kmalloc_failure;
	}

	recv_dto = &rx_desc->dto;
214
	recv_dto->ib_conn = iser_conn->ib_conn;
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	recv_dto->regd_vector_len = 0;

	regd_hdr = &rx_desc->hdr_regd_buf;
	memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
	regd_hdr->device  = device;
	regd_hdr->virt_addr  = rx_desc; /* == &rx_desc->iser_header */
	regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;

	iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE);

	iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0);

	regd_data = &rx_desc->data_regd_buf;
	memset(regd_data, 0, sizeof(struct iser_regd_buf));
	regd_data->device  = device;
	regd_data->virt_addr  = rx_desc->data;
	regd_data->data_size  = rx_data_size;

	iser_reg_single(device, regd_data, DMA_FROM_DEVICE);

	iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0);

	err = iser_post_recv(rx_desc);
	if (!err)
		return 0;

	/* iser_post_recv failed */
	iser_dto_buffs_release(recv_dto);
	kfree(rx_desc->data);
post_rx_kmalloc_failure:
	kmem_cache_free(ig.desc_cache, rx_desc);
	return err;
}

/* creates a new tx descriptor and adds header regd buffer */
static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
				  struct iser_desc       *tx_desc)
{
	struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf;
	struct iser_dto      *send_dto = &tx_desc->dto;

	memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
	regd_hdr->device  = iser_conn->ib_conn->device;
	regd_hdr->virt_addr  = tx_desc; /* == &tx_desc->iser_header */
	regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;

261
	send_dto->ib_conn         = iser_conn->ib_conn;
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
	send_dto->notify_enable   = 1;
	send_dto->regd_vector_len = 0;

	memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
	tx_desc->iser_header.flags = ISER_VER;

	iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0);
}

/**
 *  iser_conn_set_full_featured_mode - (iSER API)
 */
int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;

	int i;
	/* no need to keep it in a var, we are after login so if this should
	 * be negotiated, by now the result should be available here */
	int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS;

	iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num);

	/* Check that there is no posted recv or send buffers left - */
	/* they must be consumed during the login phase */
	BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0);
	BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);

	/* Initial post receive buffers */
	for (i = 0; i < initial_post_recv_bufs_num; i++) {
		if (iser_post_receive_control(conn) != 0) {
			iser_err("Failed to post recv bufs at:%d conn:0x%p\n",
				 i, conn);
			return -ENOMEM;
		}
	}
	iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn);
	return 0;
}

static int
303
iser_check_xmit(struct iscsi_conn *conn, void *task)
304 305 306 307 308
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;

	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
	    ISER_QP_MAX_REQ_DTOS) {
309
		iser_dbg("%ld can't xmit task %p\n",jiffies,task);
310
		return -ENOBUFS;
311
	}
312
	return 0;
313 314 315 316 317 318
}


/**
 * iser_send_command - send command PDU
 */
319
int iser_send_command(struct iscsi_conn *conn,
320
		      struct iscsi_task *task)
321 322
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;
323
	struct iscsi_iser_task *iser_task = task->dd_data;
324 325 326 327 328
	struct iser_dto *send_dto = NULL;
	unsigned long edtl;
	int err = 0;
	struct iser_data_buf *data_buf;

329 330
	struct iscsi_cmd *hdr =  task->hdr;
	struct scsi_cmnd *sc  =  task->sc;
331 332 333 334 335

	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
		return -EPERM;
	}
336
	if (iser_check_xmit(conn, task))
337
		return -ENOBUFS;
338 339 340 341

	edtl = ntohl(hdr->data_length);

	/* build the tx desc regd header and add it to the tx desc dto */
342 343 344 345
	iser_task->desc.type = ISCSI_TX_SCSI_COMMAND;
	send_dto = &iser_task->desc.dto;
	send_dto->task = iser_task;
	iser_create_send_desc(iser_conn, &iser_task->desc);
346 347

	if (hdr->flags & ISCSI_FLAG_CMD_READ)
348
		data_buf = &iser_task->data[ISER_DIR_IN];
349
	else
350
		data_buf = &iser_task->data[ISER_DIR_OUT];
351

352 353 354
	if (scsi_sg_count(sc)) { /* using a scatter list */
		data_buf->buf  = scsi_sglist(sc);
		data_buf->size = scsi_sg_count(sc);
355 356
	}

357
	data_buf->data_len = scsi_bufflen(sc);
358 359

	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
360
		err = iser_prepare_read_cmd(task, edtl);
361 362 363 364
		if (err)
			goto send_command_error;
	}
	if (hdr->flags & ISCSI_FLAG_CMD_WRITE) {
365 366 367 368
		err = iser_prepare_write_cmd(task,
					     task->imm_count,
				             task->imm_count +
					     task->unsol_count,
369 370 371 372 373 374 375 376 377 378 379 380 381 382
					     edtl);
		if (err)
			goto send_command_error;
	}

	iser_reg_single(iser_conn->ib_conn->device,
			send_dto->regd[0], DMA_TO_DEVICE);

	if (iser_post_receive_control(conn) != 0) {
		iser_err("post_recv failed!\n");
		err = -ENOMEM;
		goto send_command_error;
	}

383
	iser_task->status = ISER_TASK_STATUS_STARTED;
384

385
	err = iser_post_send(&iser_task->desc);
386 387 388 389 390
	if (!err)
		return 0;

send_command_error:
	iser_dto_buffs_release(send_dto);
391
	iser_err("conn %p failed task->itt %d err %d\n",conn, task->itt, err);
392 393 394 395 396 397
	return err;
}

/**
 * iser_send_data_out - send data out PDU
 */
398
int iser_send_data_out(struct iscsi_conn *conn,
399
		       struct iscsi_task *task,
400 401 402
		       struct iscsi_data *hdr)
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;
403
	struct iscsi_iser_task *iser_task = task->dd_data;
404 405 406 407
	struct iser_desc *tx_desc = NULL;
	struct iser_dto *send_dto = NULL;
	unsigned long buf_offset;
	unsigned long data_seg_len;
408
	uint32_t itt;
409 410 411 412 413 414 415
	int err = 0;

	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
		return -EPERM;
	}

416
	if (iser_check_xmit(conn, task))
417
		return -ENOBUFS;
418

419
	itt = (__force uint32_t)hdr->itt;
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	data_seg_len = ntoh24(hdr->dlength);
	buf_offset   = ntohl(hdr->offset);

	iser_dbg("%s itt %d dseg_len %d offset %d\n",
		 __func__,(int)itt,(int)data_seg_len,(int)buf_offset);

	tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
	if (tx_desc == NULL) {
		iser_err("Failed to alloc desc for post dataout\n");
		return -ENOMEM;
	}

	tx_desc->type = ISCSI_TX_DATAOUT;
	memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));

	/* build the tx desc regd header and add it to the tx desc dto */
	send_dto = &tx_desc->dto;
437
	send_dto->task = iser_task;
438 439 440 441 442 443 444
	iser_create_send_desc(iser_conn, tx_desc);

	iser_reg_single(iser_conn->ib_conn->device,
			send_dto->regd[0], DMA_TO_DEVICE);

	/* all data was registered for RDMA, we can use the lkey */
	iser_dto_add_regd_buff(send_dto,
445
			       &iser_task->rdma_regd[ISER_DIR_OUT],
446 447 448
			       buf_offset,
			       data_seg_len);

449
	if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) {
450 451 452
		iser_err("Offset:%ld & DSL:%ld in Data-Out "
			 "inconsistent with total len:%ld, itt:%d\n",
			 buf_offset, data_seg_len,
453
			 iser_task->data[ISER_DIR_OUT].data_len, itt);
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
		err = -EINVAL;
		goto send_data_out_error;
	}
	iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n",
		 itt, buf_offset, data_seg_len);


	err = iser_post_send(tx_desc);
	if (!err)
		return 0;

send_data_out_error:
	iser_dto_buffs_release(send_dto);
	kmem_cache_free(ig.desc_cache, tx_desc);
	iser_err("conn %p failed err %d\n",conn, err);
	return err;
}

int iser_send_control(struct iscsi_conn *conn,
473
		      struct iscsi_task *task)
474 475
{
	struct iscsi_iser_conn *iser_conn = conn->dd_data;
476 477
	struct iscsi_iser_task *iser_task = task->dd_data;
	struct iser_desc *mdesc = &iser_task->desc;
478 479 480 481 482 483 484 485 486 487 488
	struct iser_dto *send_dto = NULL;
	unsigned long data_seg_len;
	int err = 0;
	struct iser_regd_buf *regd_buf;
	struct iser_device *device;

	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
		return -EPERM;
	}

489
	if (iser_check_xmit(conn, task))
490
		return -ENOBUFS;
491 492 493 494

	/* build the tx desc regd header and add it to the tx desc dto */
	mdesc->type = ISCSI_TX_CONTROL;
	send_dto = &mdesc->dto;
495
	send_dto->task = NULL;
496 497 498 499 500 501
	iser_create_send_desc(iser_conn, mdesc);

	device = iser_conn->ib_conn->device;

	iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);

502
	data_seg_len = ntoh24(task->hdr->dlength);
503 504 505 506 507

	if (data_seg_len > 0) {
		regd_buf = &mdesc->data_regd_buf;
		memset(regd_buf, 0, sizeof(struct iser_regd_buf));
		regd_buf->device = device;
508 509
		regd_buf->virt_addr = task->data;
		regd_buf->data_size = task->data_count;
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
		iser_reg_single(device, regd_buf,
				DMA_TO_DEVICE);
		iser_dto_add_regd_buff(send_dto, regd_buf,
				       0,
				       data_seg_len);
	}

	if (iser_post_receive_control(conn) != 0) {
		iser_err("post_rcv_buff failed!\n");
		err = -ENOMEM;
		goto send_control_error;
	}

	err = iser_post_send(mdesc);
	if (!err)
		return 0;

send_control_error:
	iser_dto_buffs_release(send_dto);
	iser_err("conn %p failed err %d\n",conn, err);
	return err;
}

/**
 * iser_rcv_dto_completion - recv DTO completion
 */
void iser_rcv_completion(struct iser_desc *rx_desc,
			 unsigned long dto_xfer_len)
{
539
	struct iser_dto *dto = &rx_desc->dto;
540
	struct iscsi_iser_conn *conn = dto->ib_conn->iser_conn;
541 542
	struct iscsi_task *task;
	struct iscsi_iser_task *iser_task;
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
	struct iscsi_hdr *hdr;
	char   *rx_data = NULL;
	int     rx_data_len = 0;
	unsigned char opcode;

	hdr = &rx_desc->iscsi_header;

	iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt);

	if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */
		rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN;
		rx_data     = dto->regd[1]->virt_addr;
		rx_data    += dto->offset[1];
	}

	opcode = hdr->opcode & ISCSI_OPCODE_MASK;

	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
561
		spin_lock(&conn->iscsi_conn->session->lock);
562
		task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
563 564 565 566
		if (task)
			__iscsi_get_task(task);
		spin_unlock(&conn->iscsi_conn->session->lock);

567 568
		if (!task)
			iser_err("itt can't be matched to task!!! "
569 570 571
				 "conn %p opcode %d itt %d\n",
				 conn->iscsi_conn, opcode, hdr->itt);
		else {
572 573 574 575
			iser_task = task->dd_data;
			iser_dbg("itt %d task %p\n",hdr->itt, task);
			iser_task->status = ISER_TASK_STATUS_COMPLETED;
			iser_task_rdma_finalize(iser_task);
576
			iscsi_put_task(task);
577
		}
578 579 580 581 582 583 584 585 586
	}
	iser_dto_buffs_release(dto);

	iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len);

	kfree(rx_desc->data);
	kmem_cache_free(ig.desc_cache, rx_desc);

	/* decrementing conn->post_recv_buf_count only --after-- freeing the   *
587
	 * task eliminates the need to worry on tasks which are completed in   *
588 589 590 591 592 593 594 595
	 * parallel to the execution of iser_conn_term. So the code that waits *
	 * for the posted rx bufs refcount to become zero handles everything   */
	atomic_dec(&conn->ib_conn->post_recv_buf_count);
}

void iser_snd_completion(struct iser_desc *tx_desc)
{
	struct iser_dto        *dto = &tx_desc->dto;
596 597
	struct iser_conn       *ib_conn = dto->ib_conn;
	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
598
	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
599
	struct iscsi_task *task;
600
	int resume_tx = 0;
601 602 603 604 605 606 607 608

	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);

	iser_dto_buffs_release(dto);

	if (tx_desc->type == ISCSI_TX_DATAOUT)
		kmem_cache_free(ig.desc_cache, tx_desc);

609 610 611 612
	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
	    ISER_QP_MAX_REQ_DTOS)
		resume_tx = 1;

613
	atomic_dec(&ib_conn->post_send_buf_count);
614

615
	if (resume_tx) {
616 617 618 619 620 621
		iser_dbg("%ld resuming tx\n",jiffies);
		scsi_queue_work(conn->session->host, &conn->xmitwork);
	}

	if (tx_desc->type == ISCSI_TX_CONTROL) {
		/* this arithmetic is legal by libiscsi dd_data allocation */
622 623 624 625
		task = (void *) ((long)(void *)tx_desc -
				  sizeof(struct iscsi_task));
		if (task->hdr->itt == RESERVED_ITT)
			iscsi_put_task(task);
626 627 628
	}
}

629
void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
630 631

{
632
	iser_task->status = ISER_TASK_STATUS_INIT;
633

634 635
	iser_task->dir[ISER_DIR_IN] = 0;
	iser_task->dir[ISER_DIR_OUT] = 0;
636

637 638
	iser_task->data[ISER_DIR_IN].data_len  = 0;
	iser_task->data[ISER_DIR_OUT].data_len = 0;
639

640
	memset(&iser_task->rdma_regd[ISER_DIR_IN], 0,
641
	       sizeof(struct iser_regd_buf));
642
	memset(&iser_task->rdma_regd[ISER_DIR_OUT], 0,
643 644 645
	       sizeof(struct iser_regd_buf));
}

646
void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
647 648
{
	int deferred;
649
	int is_rdma_aligned = 1;
650
	struct iser_regd_buf *regd;
651 652 653 654

	/* if we were reading, copy back to unaligned sglist,
	 * anyway dma_unmap and free the copy
	 */
655
	if (iser_task->data_copy[ISER_DIR_IN].copy_buf != NULL) {
656
		is_rdma_aligned = 0;
657
		iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_IN);
658
	}
659
	if (iser_task->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
660
		is_rdma_aligned = 0;
661
		iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_OUT);
662
	}
663

664 665
	if (iser_task->dir[ISER_DIR_IN]) {
		regd = &iser_task->rdma_regd[ISER_DIR_IN];
666
		deferred = iser_regd_buff_release(regd);
667
		if (deferred) {
668 669
			iser_err("%d references remain for BUF-IN rdma reg\n",
				 atomic_read(&regd->ref_count));
670 671 672
		}
	}

673 674
	if (iser_task->dir[ISER_DIR_OUT]) {
		regd = &iser_task->rdma_regd[ISER_DIR_OUT];
675
		deferred = iser_regd_buff_release(regd);
676
		if (deferred) {
677 678
			iser_err("%d references remain for BUF-OUT rdma reg\n",
				 atomic_read(&regd->ref_count));
679 680 681
		}
	}

682 683
       /* if the data was unaligned, it was already unmapped and then copied */
       if (is_rdma_aligned)
684
		iser_dma_unmap_task_data(iser_task);
685 686 687 688 689 690 691 692 693 694
}

void iser_dto_buffs_release(struct iser_dto *dto)
{
	int i;

	for (i = 0; i < dto->regd_vector_len; i++)
		iser_regd_buff_release(dto->regd[i]);
}