blob: 3e65a43d215416152042f8b1964d0079b66d7822 [file] [log] [blame]
Or Gerlitze85b24b2006-05-11 10:02:19 +03001/*
2 * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
Or Gerlitze85b24b2006-05-11 10:02:19 +030031 */
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/mm.h>
Or Gerlitze85b24b2006-05-11 10:02:19 +030035#include <linux/scatterlist.h>
36#include <linux/kfifo.h>
37#include <scsi/scsi_cmnd.h>
38#include <scsi/scsi_host.h>
39
40#include "iscsi_iser.h"
41
Or Gerlitze85b24b2006-05-11 10:02:19 +030042
43/* iser_dto_add_regd_buff - increments the reference count for *
44 * the registered buffer & adds it to the DTO object */
45static void iser_dto_add_regd_buff(struct iser_dto *dto,
46 struct iser_regd_buf *regd_buf,
47 unsigned long use_offset,
48 unsigned long use_size)
49{
50 int add_idx;
51
52 atomic_inc(&regd_buf->ref_count);
53
54 add_idx = dto->regd_vector_len;
55 dto->regd[add_idx] = regd_buf;
56 dto->used_sz[add_idx] = use_size;
57 dto->offset[add_idx] = use_offset;
58
59 dto->regd_vector_len++;
60}
61
Or Gerlitze85b24b2006-05-11 10:02:19 +030062/* Register user buffer memory and initialize passive rdma
63 * dto descriptor. Total data size is stored in
Mike Christie2261ec32008-05-21 15:54:11 -050064 * iser_task->data[ISER_DIR_IN].data_len
Or Gerlitze85b24b2006-05-11 10:02:19 +030065 */
Mike Christie2261ec32008-05-21 15:54:11 -050066static int iser_prepare_read_cmd(struct iscsi_task *task,
Or Gerlitze85b24b2006-05-11 10:02:19 +030067 unsigned int edtl)
68
69{
Mike Christie2261ec32008-05-21 15:54:11 -050070 struct iscsi_iser_task *iser_task = task->dd_data;
Or Gerlitze85b24b2006-05-11 10:02:19 +030071 struct iser_regd_buf *regd_buf;
72 int err;
Mike Christie2261ec32008-05-21 15:54:11 -050073 struct iser_hdr *hdr = &iser_task->desc.iser_header;
74 struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN];
Or Gerlitze85b24b2006-05-11 10:02:19 +030075
Mike Christie2261ec32008-05-21 15:54:11 -050076 err = iser_dma_map_task_data(iser_task,
Or Gerlitze85b24b2006-05-11 10:02:19 +030077 buf_in,
78 ISER_DIR_IN,
79 DMA_FROM_DEVICE);
80 if (err)
81 return err;
82
Mike Christie2261ec32008-05-21 15:54:11 -050083 if (edtl > iser_task->data[ISER_DIR_IN].data_len) {
Or Gerlitze85b24b2006-05-11 10:02:19 +030084 iser_err("Total data length: %ld, less than EDTL: "
85 "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
Mike Christie2261ec32008-05-21 15:54:11 -050086 iser_task->data[ISER_DIR_IN].data_len, edtl,
87 task->itt, iser_task->iser_conn);
Or Gerlitze85b24b2006-05-11 10:02:19 +030088 return -EINVAL;
89 }
90
Mike Christie2261ec32008-05-21 15:54:11 -050091 err = iser_reg_rdma_mem(iser_task,ISER_DIR_IN);
Or Gerlitze85b24b2006-05-11 10:02:19 +030092 if (err) {
93 iser_err("Failed to set up Data-IN RDMA\n");
94 return err;
95 }
Mike Christie2261ec32008-05-21 15:54:11 -050096 regd_buf = &iser_task->rdma_regd[ISER_DIR_IN];
Or Gerlitze85b24b2006-05-11 10:02:19 +030097
98 hdr->flags |= ISER_RSV;
99 hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
100 hdr->read_va = cpu_to_be64(regd_buf->reg.va);
101
102 iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
Mike Christie2261ec32008-05-21 15:54:11 -0500103 task->itt, regd_buf->reg.rkey,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300104 (unsigned long long)regd_buf->reg.va);
105
106 return 0;
107}
108
109/* Register user buffer memory and initialize passive rdma
110 * dto descriptor. Total data size is stored in
Mike Christie2261ec32008-05-21 15:54:11 -0500111 * task->data[ISER_DIR_OUT].data_len
Or Gerlitze85b24b2006-05-11 10:02:19 +0300112 */
113static int
Mike Christie2261ec32008-05-21 15:54:11 -0500114iser_prepare_write_cmd(struct iscsi_task *task,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300115 unsigned int imm_sz,
116 unsigned int unsol_sz,
117 unsigned int edtl)
118{
Mike Christie2261ec32008-05-21 15:54:11 -0500119 struct iscsi_iser_task *iser_task = task->dd_data;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300120 struct iser_regd_buf *regd_buf;
121 int err;
Mike Christie2261ec32008-05-21 15:54:11 -0500122 struct iser_dto *send_dto = &iser_task->desc.dto;
123 struct iser_hdr *hdr = &iser_task->desc.iser_header;
124 struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
Or Gerlitze85b24b2006-05-11 10:02:19 +0300125
Mike Christie2261ec32008-05-21 15:54:11 -0500126 err = iser_dma_map_task_data(iser_task,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300127 buf_out,
128 ISER_DIR_OUT,
129 DMA_TO_DEVICE);
130 if (err)
131 return err;
132
Mike Christie2261ec32008-05-21 15:54:11 -0500133 if (edtl > iser_task->data[ISER_DIR_OUT].data_len) {
Or Gerlitze85b24b2006-05-11 10:02:19 +0300134 iser_err("Total data length: %ld, less than EDTL: %d, "
135 "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
Mike Christie2261ec32008-05-21 15:54:11 -0500136 iser_task->data[ISER_DIR_OUT].data_len,
137 edtl, task->itt, task->conn);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300138 return -EINVAL;
139 }
140
Mike Christie2261ec32008-05-21 15:54:11 -0500141 err = iser_reg_rdma_mem(iser_task,ISER_DIR_OUT);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300142 if (err != 0) {
143 iser_err("Failed to register write cmd RDMA mem\n");
144 return err;
145 }
146
Mike Christie2261ec32008-05-21 15:54:11 -0500147 regd_buf = &iser_task->rdma_regd[ISER_DIR_OUT];
Or Gerlitze85b24b2006-05-11 10:02:19 +0300148
149 if (unsol_sz < edtl) {
150 hdr->flags |= ISER_WSV;
151 hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey);
152 hdr->write_va = cpu_to_be64(regd_buf->reg.va + unsol_sz);
153
154 iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
155 "VA:%#llX + unsol:%d\n",
Mike Christie2261ec32008-05-21 15:54:11 -0500156 task->itt, regd_buf->reg.rkey,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300157 (unsigned long long)regd_buf->reg.va, unsol_sz);
158 }
159
160 if (imm_sz > 0) {
161 iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
Mike Christie2261ec32008-05-21 15:54:11 -0500162 task->itt, imm_sz);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300163 iser_dto_add_regd_buff(send_dto,
164 regd_buf,
165 0,
166 imm_sz);
167 }
168
169 return 0;
170}
171
Or Gerlitze85b24b2006-05-11 10:02:19 +0300172/* creates a new tx descriptor and adds header regd buffer */
173static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
174 struct iser_desc *tx_desc)
175{
176 struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf;
177 struct iser_dto *send_dto = &tx_desc->dto;
178
179 memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
180 regd_hdr->device = iser_conn->ib_conn->device;
181 regd_hdr->virt_addr = tx_desc; /* == &tx_desc->iser_header */
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000182 regd_hdr->data_size = ISER_HEADERS_LEN;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300183
Erez Zilber87e8df72006-09-27 15:27:10 +0300184 send_dto->ib_conn = iser_conn->ib_conn;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300185 send_dto->notify_enable = 1;
186 send_dto->regd_vector_len = 0;
187
188 memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
189 tx_desc->iser_header.flags = ISER_VER;
190
191 iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0);
192}
193
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000194int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
195{
196 int i, j;
197 u64 dma_addr;
198 struct iser_rx_desc *rx_desc;
199 struct ib_sge *rx_sg;
200 struct iser_device *device = ib_conn->device;
201
202 ib_conn->rx_descs = kmalloc(ISER_QP_MAX_RECV_DTOS *
203 sizeof(struct iser_rx_desc), GFP_KERNEL);
204 if (!ib_conn->rx_descs)
205 goto rx_desc_alloc_fail;
206
207 rx_desc = ib_conn->rx_descs;
208
209 for (i = 0; i < ISER_QP_MAX_RECV_DTOS; i++, rx_desc++) {
210 dma_addr = ib_dma_map_single(device->ib_device, (void *)rx_desc,
211 ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
212 if (ib_dma_mapping_error(device->ib_device, dma_addr))
213 goto rx_desc_dma_map_failed;
214
215 rx_desc->dma_addr = dma_addr;
216
217 rx_sg = &rx_desc->rx_sg;
218 rx_sg->addr = rx_desc->dma_addr;
219 rx_sg->length = ISER_RX_PAYLOAD_SIZE;
220 rx_sg->lkey = device->mr->lkey;
221 }
222
223 ib_conn->rx_desc_head = 0;
224 return 0;
225
226rx_desc_dma_map_failed:
227 rx_desc = ib_conn->rx_descs;
228 for (j = 0; j < i; j++, rx_desc++)
229 ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
230 ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
231 kfree(ib_conn->rx_descs);
232 ib_conn->rx_descs = NULL;
233rx_desc_alloc_fail:
234 iser_err("failed allocating rx descriptors / data buffers\n");
235 return -ENOMEM;
236}
237
238void iser_free_rx_descriptors(struct iser_conn *ib_conn)
239{
240 int i;
241 struct iser_rx_desc *rx_desc;
242 struct iser_device *device = ib_conn->device;
243
244 if (ib_conn->login_buf) {
245 ib_dma_unmap_single(device->ib_device, ib_conn->login_dma,
246 ISER_RX_LOGIN_SIZE, DMA_FROM_DEVICE);
247 kfree(ib_conn->login_buf);
248 }
249
250 if (!ib_conn->rx_descs)
251 return;
252
253 rx_desc = ib_conn->rx_descs;
254 for (i = 0; i < ISER_QP_MAX_RECV_DTOS; i++, rx_desc++)
255 ib_dma_unmap_single(device->ib_device, rx_desc->dma_addr,
256 ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
257 kfree(ib_conn->rx_descs);
258}
259
Or Gerlitze85b24b2006-05-11 10:02:19 +0300260/**
261 * iser_conn_set_full_featured_mode - (iSER API)
262 */
263int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
264{
265 struct iscsi_iser_conn *iser_conn = conn->dd_data;
266
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000267 iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300268
269 /* Check that there is no posted recv or send buffers left - */
270 /* they must be consumed during the login phase */
Or Gerlitz704315f2010-02-08 13:18:39 +0000271 BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300272 BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
273
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000274 if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
275 return -ENOMEM;
276
Or Gerlitze85b24b2006-05-11 10:02:19 +0300277 /* Initial post receive buffers */
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000278 if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
279 return -ENOMEM;
280
Or Gerlitze85b24b2006-05-11 10:02:19 +0300281 return 0;
282}
283
284static int
285iser_check_xmit(struct iscsi_conn *conn, void *task)
286{
Or Gerlitze85b24b2006-05-11 10:02:19 +0300287 struct iscsi_iser_conn *iser_conn = conn->dd_data;
288
Or Gerlitze85b24b2006-05-11 10:02:19 +0300289 if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
290 ISER_QP_MAX_REQ_DTOS) {
Erez Zilberf0938402007-01-07 12:28:02 +0200291 iser_dbg("%ld can't xmit task %p\n",jiffies,task);
292 return -ENOBUFS;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300293 }
Erez Zilberf0938402007-01-07 12:28:02 +0200294 return 0;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300295}
296
297
298/**
299 * iser_send_command - send command PDU
300 */
Mike Christie2747fdb2008-05-21 15:54:08 -0500301int iser_send_command(struct iscsi_conn *conn,
Mike Christie2261ec32008-05-21 15:54:11 -0500302 struct iscsi_task *task)
Or Gerlitze85b24b2006-05-11 10:02:19 +0300303{
304 struct iscsi_iser_conn *iser_conn = conn->dd_data;
Mike Christie2261ec32008-05-21 15:54:11 -0500305 struct iscsi_iser_task *iser_task = task->dd_data;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300306 struct iser_dto *send_dto = NULL;
307 unsigned long edtl;
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000308 int err;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300309 struct iser_data_buf *data_buf;
Mike Christie0f9c7442008-12-02 00:32:06 -0600310 struct iscsi_cmd *hdr = (struct iscsi_cmd *)task->hdr;
Mike Christie2261ec32008-05-21 15:54:11 -0500311 struct scsi_cmnd *sc = task->sc;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300312
313 if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
314 iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
315 return -EPERM;
316 }
Mike Christie2261ec32008-05-21 15:54:11 -0500317 if (iser_check_xmit(conn, task))
Erez Zilberf0938402007-01-07 12:28:02 +0200318 return -ENOBUFS;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300319
320 edtl = ntohl(hdr->data_length);
321
322 /* build the tx desc regd header and add it to the tx desc dto */
Mike Christie2261ec32008-05-21 15:54:11 -0500323 iser_task->desc.type = ISCSI_TX_SCSI_COMMAND;
324 send_dto = &iser_task->desc.dto;
325 send_dto->task = iser_task;
326 iser_create_send_desc(iser_conn, &iser_task->desc);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300327
328 if (hdr->flags & ISCSI_FLAG_CMD_READ)
Mike Christie2261ec32008-05-21 15:54:11 -0500329 data_buf = &iser_task->data[ISER_DIR_IN];
Or Gerlitze85b24b2006-05-11 10:02:19 +0300330 else
Mike Christie2261ec32008-05-21 15:54:11 -0500331 data_buf = &iser_task->data[ISER_DIR_OUT];
Or Gerlitze85b24b2006-05-11 10:02:19 +0300332
FUJITA Tomonorida9c0c72007-06-01 18:56:21 +0900333 if (scsi_sg_count(sc)) { /* using a scatter list */
334 data_buf->buf = scsi_sglist(sc);
335 data_buf->size = scsi_sg_count(sc);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300336 }
337
FUJITA Tomonorida9c0c72007-06-01 18:56:21 +0900338 data_buf->data_len = scsi_bufflen(sc);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300339
340 if (hdr->flags & ISCSI_FLAG_CMD_READ) {
Mike Christie2261ec32008-05-21 15:54:11 -0500341 err = iser_prepare_read_cmd(task, edtl);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300342 if (err)
343 goto send_command_error;
344 }
345 if (hdr->flags & ISCSI_FLAG_CMD_WRITE) {
Mike Christie2261ec32008-05-21 15:54:11 -0500346 err = iser_prepare_write_cmd(task,
347 task->imm_count,
348 task->imm_count +
Mike Christie0f9c7442008-12-02 00:32:06 -0600349 task->unsol_r2t.data_length,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300350 edtl);
351 if (err)
352 goto send_command_error;
353 }
354
355 iser_reg_single(iser_conn->ib_conn->device,
356 send_dto->regd[0], DMA_TO_DEVICE);
357
Mike Christie2261ec32008-05-21 15:54:11 -0500358 iser_task->status = ISER_TASK_STATUS_STARTED;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300359
Mike Christie2261ec32008-05-21 15:54:11 -0500360 err = iser_post_send(&iser_task->desc);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300361 if (!err)
362 return 0;
363
364send_command_error:
365 iser_dto_buffs_release(send_dto);
Mike Christie2261ec32008-05-21 15:54:11 -0500366 iser_err("conn %p failed task->itt %d err %d\n",conn, task->itt, err);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300367 return err;
368}
369
370/**
371 * iser_send_data_out - send data out PDU
372 */
Mike Christie2747fdb2008-05-21 15:54:08 -0500373int iser_send_data_out(struct iscsi_conn *conn,
Mike Christie2261ec32008-05-21 15:54:11 -0500374 struct iscsi_task *task,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300375 struct iscsi_data *hdr)
376{
377 struct iscsi_iser_conn *iser_conn = conn->dd_data;
Mike Christie2261ec32008-05-21 15:54:11 -0500378 struct iscsi_iser_task *iser_task = task->dd_data;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300379 struct iser_desc *tx_desc = NULL;
380 struct iser_dto *send_dto = NULL;
381 unsigned long buf_offset;
382 unsigned long data_seg_len;
Erez Zilber0a22ab92008-04-16 21:09:35 -0700383 uint32_t itt;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300384 int err = 0;
385
386 if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
387 iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
388 return -EPERM;
389 }
390
Mike Christie2261ec32008-05-21 15:54:11 -0500391 if (iser_check_xmit(conn, task))
Erez Zilberf0938402007-01-07 12:28:02 +0200392 return -ENOBUFS;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300393
Erez Zilber0a22ab92008-04-16 21:09:35 -0700394 itt = (__force uint32_t)hdr->itt;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300395 data_seg_len = ntoh24(hdr->dlength);
396 buf_offset = ntohl(hdr->offset);
397
398 iser_dbg("%s itt %d dseg_len %d offset %d\n",
399 __func__,(int)itt,(int)data_seg_len,(int)buf_offset);
400
401 tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
402 if (tx_desc == NULL) {
403 iser_err("Failed to alloc desc for post dataout\n");
404 return -ENOMEM;
405 }
406
407 tx_desc->type = ISCSI_TX_DATAOUT;
408 memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));
409
410 /* build the tx desc regd header and add it to the tx desc dto */
411 send_dto = &tx_desc->dto;
Mike Christie2261ec32008-05-21 15:54:11 -0500412 send_dto->task = iser_task;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300413 iser_create_send_desc(iser_conn, tx_desc);
414
415 iser_reg_single(iser_conn->ib_conn->device,
416 send_dto->regd[0], DMA_TO_DEVICE);
417
418 /* all data was registered for RDMA, we can use the lkey */
419 iser_dto_add_regd_buff(send_dto,
Mike Christie2261ec32008-05-21 15:54:11 -0500420 &iser_task->rdma_regd[ISER_DIR_OUT],
Or Gerlitze85b24b2006-05-11 10:02:19 +0300421 buf_offset,
422 data_seg_len);
423
Mike Christie2261ec32008-05-21 15:54:11 -0500424 if (buf_offset + data_seg_len > iser_task->data[ISER_DIR_OUT].data_len) {
Or Gerlitze85b24b2006-05-11 10:02:19 +0300425 iser_err("Offset:%ld & DSL:%ld in Data-Out "
426 "inconsistent with total len:%ld, itt:%d\n",
427 buf_offset, data_seg_len,
Mike Christie2261ec32008-05-21 15:54:11 -0500428 iser_task->data[ISER_DIR_OUT].data_len, itt);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300429 err = -EINVAL;
430 goto send_data_out_error;
431 }
432 iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n",
433 itt, buf_offset, data_seg_len);
434
435
436 err = iser_post_send(tx_desc);
437 if (!err)
438 return 0;
439
440send_data_out_error:
441 iser_dto_buffs_release(send_dto);
442 kmem_cache_free(ig.desc_cache, tx_desc);
443 iser_err("conn %p failed err %d\n",conn, err);
444 return err;
445}
446
447int iser_send_control(struct iscsi_conn *conn,
Mike Christie2261ec32008-05-21 15:54:11 -0500448 struct iscsi_task *task)
Or Gerlitze85b24b2006-05-11 10:02:19 +0300449{
450 struct iscsi_iser_conn *iser_conn = conn->dd_data;
Mike Christie2261ec32008-05-21 15:54:11 -0500451 struct iscsi_iser_task *iser_task = task->dd_data;
452 struct iser_desc *mdesc = &iser_task->desc;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300453 struct iser_dto *send_dto = NULL;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300454 unsigned long data_seg_len;
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000455 int err;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300456 struct iser_regd_buf *regd_buf;
457 struct iser_device *device;
458
459 if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
460 iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
461 return -EPERM;
462 }
463
Mike Christie2261ec32008-05-21 15:54:11 -0500464 if (iser_check_xmit(conn, task))
Erez Zilberf0938402007-01-07 12:28:02 +0200465 return -ENOBUFS;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300466
467 /* build the tx desc regd header and add it to the tx desc dto */
468 mdesc->type = ISCSI_TX_CONTROL;
469 send_dto = &mdesc->dto;
Mike Christie2261ec32008-05-21 15:54:11 -0500470 send_dto->task = NULL;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300471 iser_create_send_desc(iser_conn, mdesc);
472
473 device = iser_conn->ib_conn->device;
474
475 iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
476
Mike Christie2261ec32008-05-21 15:54:11 -0500477 data_seg_len = ntoh24(task->hdr->dlength);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300478
479 if (data_seg_len > 0) {
480 regd_buf = &mdesc->data_regd_buf;
481 memset(regd_buf, 0, sizeof(struct iser_regd_buf));
482 regd_buf->device = device;
Mike Christie2261ec32008-05-21 15:54:11 -0500483 regd_buf->virt_addr = task->data;
484 regd_buf->data_size = task->data_count;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300485 iser_reg_single(device, regd_buf,
486 DMA_TO_DEVICE);
487 iser_dto_add_regd_buff(send_dto, regd_buf,
488 0,
489 data_seg_len);
490 }
491
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000492 if (task == conn->login_task) {
493 err = iser_post_recvl(iser_conn->ib_conn);
494 if (err)
495 goto send_control_error;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300496 }
497
498 err = iser_post_send(mdesc);
499 if (!err)
500 return 0;
501
502send_control_error:
503 iser_dto_buffs_release(send_dto);
504 iser_err("conn %p failed err %d\n",conn, err);
505 return err;
506}
507
508/**
509 * iser_rcv_dto_completion - recv DTO completion
510 */
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000511void iser_rcv_completion(struct iser_rx_desc *rx_desc,
512 unsigned long rx_xfer_len,
513 struct iser_conn *ib_conn)
Or Gerlitze85b24b2006-05-11 10:02:19 +0300514{
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000515 struct iscsi_iser_conn *conn = ib_conn->iser_conn;
Mike Christie2261ec32008-05-21 15:54:11 -0500516 struct iscsi_task *task;
517 struct iscsi_iser_task *iser_task;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300518 struct iscsi_hdr *hdr;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300519 unsigned char opcode;
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000520 u64 rx_dma;
521 int rx_buflen, outstanding, count, err;
522
523 /* differentiate between login to all other PDUs */
524 if ((char *)rx_desc == ib_conn->login_buf) {
525 rx_dma = ib_conn->login_dma;
526 rx_buflen = ISER_RX_LOGIN_SIZE;
527 } else {
528 rx_dma = rx_desc->dma_addr;
529 rx_buflen = ISER_RX_PAYLOAD_SIZE;
530 }
531
532 ib_dma_sync_single_for_cpu(ib_conn->device->ib_device, rx_dma,
533 rx_buflen, DMA_FROM_DEVICE);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300534
535 hdr = &rx_desc->iscsi_header;
536
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000537 iser_dbg("op 0x%x itt 0x%x dlen %d\n", hdr->opcode,
538 hdr->itt, (int)(rx_xfer_len - ISER_HEADERS_LEN));
Or Gerlitze85b24b2006-05-11 10:02:19 +0300539
540 opcode = hdr->opcode & ISCSI_OPCODE_MASK;
541
542 if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
Mike Christie913e5bf2008-05-21 15:54:18 -0500543 spin_lock(&conn->iscsi_conn->session->lock);
Mike Christie2261ec32008-05-21 15:54:11 -0500544 task = iscsi_itt_to_ctask(conn->iscsi_conn, hdr->itt);
Mike Christie913e5bf2008-05-21 15:54:18 -0500545 if (task)
546 __iscsi_get_task(task);
547 spin_unlock(&conn->iscsi_conn->session->lock);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300548
Mike Christie2261ec32008-05-21 15:54:11 -0500549 if (!task)
550 iser_err("itt can't be matched to task!!! "
Mike Christie0af967f2008-05-21 15:54:04 -0500551 "conn %p opcode %d itt %d\n",
552 conn->iscsi_conn, opcode, hdr->itt);
553 else {
Mike Christie2261ec32008-05-21 15:54:11 -0500554 iser_task = task->dd_data;
555 iser_dbg("itt %d task %p\n",hdr->itt, task);
556 iser_task->status = ISER_TASK_STATUS_COMPLETED;
557 iser_task_rdma_finalize(iser_task);
Mike Christie913e5bf2008-05-21 15:54:18 -0500558 iscsi_put_task(task);
Mike Christie0af967f2008-05-21 15:54:04 -0500559 }
Or Gerlitze85b24b2006-05-11 10:02:19 +0300560 }
Or Gerlitze85b24b2006-05-11 10:02:19 +0300561
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000562 iscsi_iser_recv(conn->iscsi_conn, hdr,
563 rx_desc->data, rx_xfer_len - ISER_HEADERS_LEN);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300564
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000565 ib_dma_sync_single_for_device(ib_conn->device->ib_device, rx_dma,
566 rx_buflen, DMA_FROM_DEVICE);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300567
568 /* decrementing conn->post_recv_buf_count only --after-- freeing the *
569 * task eliminates the need to worry on tasks which are completed in *
570 * parallel to the execution of iser_conn_term. So the code that waits *
571 * for the posted rx bufs refcount to become zero handles everything */
Or Gerlitz704315f2010-02-08 13:18:39 +0000572 conn->ib_conn->post_recv_buf_count--;
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000573
574 if (rx_dma == ib_conn->login_dma)
575 return;
576
Or Gerlitz704315f2010-02-08 13:18:39 +0000577 outstanding = ib_conn->post_recv_buf_count;
Or Gerlitzbcc60c32010-02-08 13:17:42 +0000578 if (outstanding + ISER_MIN_POSTED_RX <= ISER_QP_MAX_RECV_DTOS) {
579 count = min(ISER_QP_MAX_RECV_DTOS - outstanding,
580 ISER_MIN_POSTED_RX);
581 err = iser_post_recvm(ib_conn, count);
582 if (err)
583 iser_err("posting %d rx bufs err %d\n", count, err);
584 }
Or Gerlitze85b24b2006-05-11 10:02:19 +0300585}
586
587void iser_snd_completion(struct iser_desc *tx_desc)
588{
589 struct iser_dto *dto = &tx_desc->dto;
Erez Zilber87e8df72006-09-27 15:27:10 +0300590 struct iser_conn *ib_conn = dto->ib_conn;
591 struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300592 struct iscsi_conn *conn = iser_conn->iscsi_conn;
Mike Christie2261ec32008-05-21 15:54:11 -0500593 struct iscsi_task *task;
Erez Zilberf0938402007-01-07 12:28:02 +0200594 int resume_tx = 0;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300595
596 iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
597
598 iser_dto_buffs_release(dto);
599
600 if (tx_desc->type == ISCSI_TX_DATAOUT)
601 kmem_cache_free(ig.desc_cache, tx_desc);
602
Erez Zilberf0938402007-01-07 12:28:02 +0200603 if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
604 ISER_QP_MAX_REQ_DTOS)
605 resume_tx = 1;
606
Erez Zilber87e8df72006-09-27 15:27:10 +0300607 atomic_dec(&ib_conn->post_send_buf_count);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300608
Erez Zilberf0938402007-01-07 12:28:02 +0200609 if (resume_tx) {
Or Gerlitze85b24b2006-05-11 10:02:19 +0300610 iser_dbg("%ld resuming tx\n",jiffies);
Mike Christie32ae7632009-03-05 14:46:03 -0600611 iscsi_conn_queue_work(conn);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300612 }
Or Gerlitze85b24b2006-05-11 10:02:19 +0300613
614 if (tx_desc->type == ISCSI_TX_CONTROL) {
615 /* this arithmetic is legal by libiscsi dd_data allocation */
Mike Christie2261ec32008-05-21 15:54:11 -0500616 task = (void *) ((long)(void *)tx_desc -
617 sizeof(struct iscsi_task));
618 if (task->hdr->itt == RESERVED_ITT)
619 iscsi_put_task(task);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300620 }
621}
622
Mike Christie2261ec32008-05-21 15:54:11 -0500623void iser_task_rdma_init(struct iscsi_iser_task *iser_task)
Or Gerlitze85b24b2006-05-11 10:02:19 +0300624
625{
Mike Christie2261ec32008-05-21 15:54:11 -0500626 iser_task->status = ISER_TASK_STATUS_INIT;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300627
Mike Christie2261ec32008-05-21 15:54:11 -0500628 iser_task->dir[ISER_DIR_IN] = 0;
629 iser_task->dir[ISER_DIR_OUT] = 0;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300630
Mike Christie2261ec32008-05-21 15:54:11 -0500631 iser_task->data[ISER_DIR_IN].data_len = 0;
632 iser_task->data[ISER_DIR_OUT].data_len = 0;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300633
Mike Christie2261ec32008-05-21 15:54:11 -0500634 memset(&iser_task->rdma_regd[ISER_DIR_IN], 0,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300635 sizeof(struct iser_regd_buf));
Mike Christie2261ec32008-05-21 15:54:11 -0500636 memset(&iser_task->rdma_regd[ISER_DIR_OUT], 0,
Or Gerlitze85b24b2006-05-11 10:02:19 +0300637 sizeof(struct iser_regd_buf));
638}
639
Mike Christie2261ec32008-05-21 15:54:11 -0500640void iser_task_rdma_finalize(struct iscsi_iser_task *iser_task)
Or Gerlitze85b24b2006-05-11 10:02:19 +0300641{
642 int deferred;
Erez Zilber74a20782006-09-27 16:43:06 +0300643 int is_rdma_aligned = 1;
Erez Zilber3104a212007-03-25 12:07:10 +0200644 struct iser_regd_buf *regd;
Or Gerlitze85b24b2006-05-11 10:02:19 +0300645
646 /* if we were reading, copy back to unaligned sglist,
647 * anyway dma_unmap and free the copy
648 */
Mike Christie2261ec32008-05-21 15:54:11 -0500649 if (iser_task->data_copy[ISER_DIR_IN].copy_buf != NULL) {
Erez Zilber74a20782006-09-27 16:43:06 +0300650 is_rdma_aligned = 0;
Mike Christie2261ec32008-05-21 15:54:11 -0500651 iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_IN);
Erez Zilber74a20782006-09-27 16:43:06 +0300652 }
Mike Christie2261ec32008-05-21 15:54:11 -0500653 if (iser_task->data_copy[ISER_DIR_OUT].copy_buf != NULL) {
Erez Zilber74a20782006-09-27 16:43:06 +0300654 is_rdma_aligned = 0;
Mike Christie2261ec32008-05-21 15:54:11 -0500655 iser_finalize_rdma_unaligned_sg(iser_task, ISER_DIR_OUT);
Erez Zilber74a20782006-09-27 16:43:06 +0300656 }
Or Gerlitze85b24b2006-05-11 10:02:19 +0300657
Mike Christie2261ec32008-05-21 15:54:11 -0500658 if (iser_task->dir[ISER_DIR_IN]) {
659 regd = &iser_task->rdma_regd[ISER_DIR_IN];
Erez Zilber3104a212007-03-25 12:07:10 +0200660 deferred = iser_regd_buff_release(regd);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300661 if (deferred) {
Erez Zilber3104a212007-03-25 12:07:10 +0200662 iser_err("%d references remain for BUF-IN rdma reg\n",
663 atomic_read(&regd->ref_count));
Or Gerlitze85b24b2006-05-11 10:02:19 +0300664 }
665 }
666
Mike Christie2261ec32008-05-21 15:54:11 -0500667 if (iser_task->dir[ISER_DIR_OUT]) {
668 regd = &iser_task->rdma_regd[ISER_DIR_OUT];
Erez Zilber3104a212007-03-25 12:07:10 +0200669 deferred = iser_regd_buff_release(regd);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300670 if (deferred) {
Erez Zilber3104a212007-03-25 12:07:10 +0200671 iser_err("%d references remain for BUF-OUT rdma reg\n",
672 atomic_read(&regd->ref_count));
Or Gerlitze85b24b2006-05-11 10:02:19 +0300673 }
674 }
675
Erez Zilber74a20782006-09-27 16:43:06 +0300676 /* if the data was unaligned, it was already unmapped and then copied */
677 if (is_rdma_aligned)
Mike Christie2261ec32008-05-21 15:54:11 -0500678 iser_dma_unmap_task_data(iser_task);
Or Gerlitze85b24b2006-05-11 10:02:19 +0300679}
680
681void iser_dto_buffs_release(struct iser_dto *dto)
682{
683 int i;
684
685 for (i = 0; i < dto->regd_vector_len; i++)
686 iser_regd_buff_release(dto->regd[i]);
687}
688