[openib-general] [PATCH] iSER - changes in API, socket-based connect
Alex Nezhinsky
alexn at voltaire.com
Tue Sep 13 10:01:31 PDT 2005
Hi,
Attached is a patch with changes in iSER API.
1. Got rid of iscsi entities stuff, now iser implies a single iscsi
entity.
2. Connections are established using iser sockets.
The iser module registers itself as a new socket provider.
Connections are established by creating and connecting a socket.
Then iscsi should call a new iser_conn_bind() api function.
It associates an instance of struct socket * with a pair of reciprocate
connection handles.
All further api calls identify the connection using these handles.
Finally, conn_terminate() releases the socket as part of the connection
shutdown routine.
Files added: iser_socket.c, iser_socket.h
3. Some cosmetic changes included, too.
Files deleted: iser_pdu.c, include/iser_types.h, include/iser_pdu.h
Some leftovers from the deleted files in include/*.h moved into
include/iser_api.h.
---
Changes in iSER API. Single iSCSI entity supported. Connection
establishment using
sockets, registered by iSER module. Header files cleanup.
Signed-off-by: Alexander Nezhinsky <alexn at voltaire.com>
Index: iser_memory.h
===================================================================
--- iser_memory.h (revision 3404)
+++ iser_memory.h (working copy)
@@ -66,9 +66,9 @@
iser_regd_buff_release(struct iser_regd_buf *p_regd_buf,
int *release_deferred);
-int iser_init_regd_buff_cache(struct iser_adaptor *p_iser_adaptor);
+int iser_reg_all_mem(struct iser_adaptor *p_iser_adaptor);
-int iser_release_regd_buff_cache(struct iser_adaptor *p_iser_adaptor);
+int iser_unreg_all_mem(struct iser_adaptor *p_iser_adaptor);
struct iser_regd_buf *iser_regd_buff_lookup(struct iser_adaptor
*p_iser_adaptor,
Index: iser_mod.c
===================================================================
--- iser_mod.c (revision 3404)
+++ iser_mod.c (working copy)
@@ -49,7 +49,11 @@
#include <linux/interrupt.h>
#include "iser.h"
+#include "iser_socket.h"
+#include "iser_conn.h"
+#include "iser_task.h"
#include "iser_initiator.h"
+#include "iser_utils.h"
int iser_fmr_enabled = 1;
int iser_trace_enabled = 0;
@@ -65,20 +69,184 @@
MODULE_PARM_DESC(iser_trace_enabled,
"enable/disable trace upon loading
(default:disabled)");
+struct iser_global ig;
+
/**
+ * iser_global_init - Initializes the global iSER context structure.
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_global_init(void)
+{
+ memset(&ig, 0, sizeof(struct iser_global));
+
+ /* Allocate adaptors; currently single adaptor */
+ ig.num_adaptors = 1;
+ if (iser_adaptor_init(&ig.adaptor[0], "InfiniHost0") != 0) {
+ printk(KERN_ERR PFX "initializing iser failed!\n");
+ iser_adaptor_release(&ig.adaptor[0]);
+ return -1;
+ }
+
+ /* Allocate kmem_cache for iser_task structures */
+ ig.task_mem_cache =
+ kmem_cache_create("iser_task", sizeof(struct iser_task), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ if (ig.task_mem_cache == NULL) {
+ printk(KERN_ERR PFX
+ "Failed to alloc task_mem_cache, name:
iser_task\n");
+ return -1;
+ }
+
+ /* Allocate kmem_cache for iser_dto structures, for post-recv */
+ ig.recv_dto_mem_cache =
+ kmem_cache_create("iser_recv_dto",
+ sizeof(struct iser_dto),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (ig.recv_dto_mem_cache == NULL) {
+ printk(KERN_ERR PFX
+ "Failed to alloc recv_dto_mem_cache, "
+ "name: iser_recv_dto\n");
+ return -1;
+ }
+
+ /* Allocate kmem_cache for iser_dto structures, for send */
+ ig.send_dto_mem_cache =
+ kmem_cache_create("iser_send_dto",
+ sizeof(struct iser_dto),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (ig.send_dto_mem_cache == NULL) {
+ printk(KERN_ERR PFX
+ "Failed to alloc send_dto_mem_cache,
iser_send_dto\n");
+ return -1;
+ }
+
+ /* Allocate kmem_cache for iser_regd_buf structures */
+ ig.regd_buf_mem_cache =
+ kmem_cache_create("iser_regbuf",
+ sizeof(struct iser_regd_buf),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ if (ig.regd_buf_mem_cache == NULL) {
+ printk(KERN_ERR PFX
+ "Failed to alloc regd_buf_mem_cache, "
+ "name: iser_regbuf\n");
+ return -1;
+ }
+ /* Initialize task hash table */
+ hash_init(&ig.task_hash);
+
+ return 0;
+} /* iser_global_init */
+
+/**
+ * iser_global_release - Releases all res through
+ * the global iSER context structure.
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_global_release(void)
+{
+ /* Release all adaptors */
+ iser_adaptor_release(&ig.adaptor[0]);
+ ig.num_adaptors = 0;
+
+ if (ig.task_mem_cache != NULL) {
+ kmem_cache_destroy(ig.task_mem_cache);
+ ig.task_mem_cache = NULL;
+ }
+
+ if (ig.recv_dto_mem_cache != NULL) {
+ kmem_cache_destroy(ig.recv_dto_mem_cache);
+ ig.recv_dto_mem_cache = NULL;
+ }
+
+ if (ig.send_dto_mem_cache != NULL) {
+ kmem_cache_destroy(ig.send_dto_mem_cache);
+ ig.send_dto_mem_cache = NULL;
+ }
+
+ if (ig.regd_buf_mem_cache != NULL) {
+ kmem_cache_destroy(ig.regd_buf_mem_cache);
+ ig.regd_buf_mem_cache = NULL;
+ }
+
+ return 0;
+} /* iser_global_release */
+
+/**
+ * iser_api_register - register iSER API, two-way
+ */
+int
+iser_api_register(char *provider_name,
+ struct iser_api * api,
+ struct iser_api_cb * api_cb)
+{
+ int iser_err = 0;
+
+ if (provider_name == NULL) {
+ printk(KERN_ERR PFX "NULL *provider_name\n");
+ iser_err = -EINVAL;
+ goto api_register_exit;
+ }
+ if (api == NULL) {
+ printk(KERN_ERR PFX "NULL *api structure\n");
+ iser_err = -EINVAL;
+ goto api_register_exit;
+ }
+ if (api_cb == NULL) {
+ printk(KERN_ERR PFX "NULL *api_cb structure\n");
+ iser_err = -EINVAL;
+ goto api_register_exit;
+ }
+
+ api->conn_bind = iser_conn_bind;
+ api->notice_key_values = iser_notice_key_values;
+ api->conn_enable_rdma = iser_conn_enable_rdma;
+ api->send_control = iser_send_control;
+ api->release_control = iser_release_control;
+ api->conn_terminate = iser_conn_term;
+ api->dealloc_conn_res = iser_dealloc_conn_res;
+ api->dealloc_task_res = iser_dealloc_task_res;
+
+ ig.api_cb.control_notify = api_cb->control_notify;
+ ig.api_cb.conn_term_notify = api_cb->conn_term_notify;
+
+ strncpy(ig.provider_name,provider_name,ISER_OBJECT_NAME_SIZE);
+
+ api_register_exit:
+ return iser_err;
+} /* iser_api_register */
+EXPORT_SYMBOL(iser_api_register);
+
+/**
+ * iser_api_unregister - Unregister API
+ */
+int iser_api_unregister(void)
+{
+ ig.api_cb.conn_term_notify = NULL;
+ ig.api_cb.control_notify = NULL;
+ return 0;
+} /* iser_api_unregister */
+EXPORT_SYMBOL(iser_api_unregister);
+
+/**
* init_module - module initialialization function
*/
int init_module(void)
{
ITRACE(ISER_TRACE_MODULE, "Starting iSER datamover...\n");
- /* Initialize the global iSER context */
- if (ig_init() != 0) {
+ if (iser_global_init() != 0) {
printk(KERN_ERR PFX
"initializing iser global structures failed!\n");
return -1;
}
-
+ if (iser_register_sockets() != 0) {
+ printk(KERN_ERR PFX "iser socket init failed!\n");
+ iser_global_release();
+ return -1;
+ }
return 0;
} /* init_module */
@@ -88,6 +256,6 @@
void cleanup_module(void)
{
ITRACE(ISER_TRACE_MODULE, "Removing iSER datamover...\n");
-
- ig_release();
-}
+ iser_global_release();
+ iser_unreg_sockets();
+} /* cleanup_module */
Index: include/iser_pdu.h
===================================================================
--- include/iser_pdu.h (revision 3404)
+++ include/iser_pdu.h (working copy)
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 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.
- *
- */
-
-#ifndef __ISER_PDU_H__
-#define __ISER_PDU_H__
-
-#include <linux/types.h>
-
-#include "iser_types.h"
-
-/*!
--------------------------------------------------------------------
- [iser_pdu_bhs]
-
- Description: iSCSI PDU Basic Header Segment (BHS)
-
- The purpose of defining BHS here is define the fields relevant
- to iSER operation. iSCSI layer should have its own definitions and
- may view the BHS passed to iSER just as a buffer.
- In order to avoid potential name collision, the structure has
- "iser" prefix, although strictly speaking it must be "iscsi".
- --------------------------------------------------------------------
*/
-
-#define ISER_PDU_BHS_LENGTH 48
-
-union iser_pdu_bhs {
-
- unsigned char buf[ISER_PDU_BHS_LENGTH];
-
- struct {
- uint8_t opcode; /* optional bits + opcode */
- uint8_t flags; /* opcode-specific flags */
- uint8_t rsvd[2]; /* usually reserved, used in
response */
- uint8_t ahs_length; /* AHS total length */
- uint8_t dlength[3]; /* Data segment length */
- uint8_t lun[8]; /* LUN */
- uint8_t itt[4]; /* Initiator Task Tag */
- uint8_t other[28]; /* opcode-specific */
- } byte;
-
- struct {
- uint32_t op_flg_rsvd; /* opcode, flags, reserved */
- uint32_t length; /* AHS length, Data segment
length */
- uint32_t lun[2]; /* LUN */
- uint32_t itt; /* Initiator Task Tag */
- uint32_t other[7]; /* opcode-specific */
- } dword;
-}; /* iser_pdu_bhs */
-
-/* --------------------------------------------------------
- * opcode byte
- * --------------------------------------------------------
- */
-
-/* Set when marked for immediate delivery */
-#define ISCSI_OP_IMMEDIATE 0x40
-/* Masks out the opcode itself */
-#define ISCSI_OPCODE_MASK 0x3F
-
-/* Initiator only opcode values */
-#define ISCSI_OP_NOP_OUT 0x00
-#define ISCSI_OP_SCSI_CMD 0x01
-#define ISCSI_OP_TASK_MGT_REQ 0x02
-#define ISCSI_OP_LOGIN_REQ 0x03
-#define ISCSI_OP_TEXT_REQ 0x04
-#define ISCSI_OP_DATA_OUT 0x05
-#define ISCSI_OP_LOGOUT_REQ 0x06
-#define ISCSI_OP_SNACK_REQ 0x10
-
-/* Target only opcode values */
-#define ISCSI_OP_NOP_IN 0x20
-#define ISCSI_OP_SCSI_RSP 0x21
-#define ISCSI_OP_TASK_MGT_RSP 0x22
-#define ISCSI_OP_LOGIN_RSP 0x23
-#define ISCSI_OP_TEXT_RSP 0x24
-#define ISCSI_OP_DATA_IN 0x25
-#define ISCSI_OP_LOGOUT_RSP 0x26
-#define ISCSI_OP_R2T 0x31
-#define ISCSI_OP_ASYNC 0x32
-#define ISCSI_OP_REJECT 0x3f
-
-/* --------------------------------------------------------
- * flags byte
- * --------------------------------------------------------
- */
-
-/* When set indicates the final (or only) PDU of a sequence */
-#define ISCSI_FLAG_FINAL 0x80
-/* When set indicates that data is to be read */
-#define ISCSI_FLAG_READ_CMD 0x40
-/* When set indicates that data is to be written */
-#define ISCSI_FLAG_WRITE_CMD 0x20
-
-#define IS_SET_ISCSI_FLAG_FINAL(x) \
- (ISCSI_FLAG_FINAL & x)
-
-#define IS_SET_ISCSI_FLAG_READ_CMD(x) \
- (ISCSI_FLAG_READ_CMD & x)
-
-#define IS_SET_ISCSI_FLAG_WRITE_CMD(x) \
- (ISCSI_FLAG_WRITE_CMD & x)
-
-/* Login specific */
-#define ISCSI_FLAG_LOGIN_TRANSIT 0x80
-#define ISCSI_FLAG_LOGIN_CONTINUE 0x40
-
-#define IS_SET_ISCSI_FLAG_LOGIN_TRANSIT(x) \
- (ISCSI_FLAG_LOGIN_TRANSIT & x)
-
-#define IS_SET_ISCSI_FLAG_LOGIN_CONTINUE(x) \
- (ISCSI_FLAG_LOGIN_CONTINUE & x)
-
-#define ISCSI_FLAG_LOGIN_CSG_MASK 0x0C
-#define ISCSI_FLAG_LOGIN_NSG_MASK 0x03
-
-#define GET_ISCSI_FLAG_LOGIN_CSG(x) \
- (ISCSI_FLAG_LOGIN_CSG_MASK & x)
-
-#define GET_ISCSI_FLAG_LOGIN_NSG(x) \
- (ISCSI_FLAG_LOGIN_NSG_MASK & x)
-
-#define ISCSI_LOGIN_STAGE_SECURITY 0x00
-#define ISCSI_LOGIN_STAGE_OPERATIONAL 0x01
-#define ISCSI_LOGIN_STAGE_FULL_FEATURE 0x03
-
-#define IS_ISCSI_LOGIN_NSG_OPERATIONAL(x) \
- (GET_ISCSI_FLAG_LOGIN_NSG(x) ==
ISCSI_LOGIN_STAGE_OPERATIONAL)
-
-#define IS_ISCSI_LOGIN_NSG_FULL_FEATURE(x) \
- (GET_ISCSI_FLAG_LOGIN_NSG(x) ==
ISCSI_LOGIN_STAGE_FULL_FEATURE)
-
-#define ISCSI_AHSL_MASK 0xFF000000
-#define ISCSI_DSL_MASK 0x00FFFFFF
-
-#define ISCSI_INVALID_ITT 0xFFFFFFFF
-
-/* --------------------------------------------------------
- * opcode-specific dword fields,
- * offsets are indices of: iser_pdu_bhs.dword.other[7]
- * --------------------------------------------------------
- */
-
-/* SCSI Command */
-#define ISCSI_CMD_FIELD_EDTL 0
-#define ISCSI_CMD_FIELD_CMD_SN 1
-#define ISCSI_CMD_FIELD_EXP_STAT_SN 2
-
-/* Data-OUT */
-#define ISCSI_DATA_OUT_FIELD_TTT 0
-#define ISCSI_DATA_OUT_FIELD_EXP_STAT_SN 2
-#define ISCSI_DATA_OUT_FIELD_DATA_SN 4
-#define ISCSI_DATA_OUT_FIELD_OFFSET 5
-
-/* Data-IN */
-#define ISCSI_DATA_IN_FIELD_TTT 0
-#define ISCSI_DATA_IN_FIELD_STAT_SN 1
-#define ISCSI_DATA_IN_FIELD_EXP_CMD_SN 2
-#define ISCSI_DATA_IN_FIELD_MAX_CMD_SN 3
-#define ISCSI_DATA_IN_FIELD_DATA_SN 4
-#define ISCSI_DATA_IN_FIELD_OFFSET 5
-#define ISCSI_DATA_IN_FIELD_RESID_CNT 6
-
-/* R2T */
-#define ISCSI_R2T_FIELD_TTT 0
-#define ISCSI_R2T_FIELD_STAT_SN 1
-#define ISCSI_R2T_FIELD_EXP_CMD_SN 2
-#define ISCSI_R2T_FIELD_MAX_CMD_SN 3
-#define ISCSI_R2T_FIELD_R2T_SN 4
-#define ISCSI_R2T_FIELD_OFFSET 5
-#define ISCSI_R2T_FIELD_DESIRED_CNT 6
-
-/*!
--------------------------------------------------------------------
- [iser_send_pdu]
-
- Description: descriptor of a control PDU to be sent by Send_Control
- --------------------------------------------------------------------
*/
-struct iser_send_pdu {
- union iser_pdu_bhs *p_bhs; /* BHS */
- union {
- /* Command */
- struct {
- /* data-out buffer meant for the entire
- write/bidir command */
- struct iser_data_buf buf_out;
- /* data-in buffer meant for the
- entire read/bidir command */
- struct iser_data_buf buf_in;
- /* although not data segment, ahs defined here
*/
- struct iser_data_buf ahs;
- /* size of immediate unsolicited data for
- write/bidir command, will be sent as
- the data segment of the command PDU */
- unsigned int immediate_sz;
- /* entire unsolicited data for write/bidir
command,
- will be sent in data segments of command
- and data-out PDUs */
- unsigned int unsolicited_sz;
- } command;
- /* Response */
- struct {
- /* the sense and response information for the
command */
- struct iser_data_buf buf_status;
-
- } response;
- /* Task Mgt Request */
- struct {
- /* data-out for the entire write/bidir command,
- valid only if Function=TASK REASSIGN */
- struct iser_data_buf buf_in;
- /* data-out for the entire read/bidir command,
- valid only if Function=TASK REASSIGN */
- struct iser_data_buf buf_out;
- } task_mgt_req;
- /* Data-In - not sent */
- struct {
- /* buffer from which the data-in is to be sent
*/
- struct iser_data_buf src_buf;
- } data_in;
- /* R2T - not sent */
- struct {
- /* buffer to which the data-out is to be
received */
- struct iser_data_buf dst_buf;
- } r2t;
-
- /* Other Transmitted
PDUs
- *
------------------------------------------------------------
- * Data-Out - disregarded, offset & DSL fields of BHS
are used
- * Asynchronous message - sense and iSCSI Event
information
- * Text Request - iSCSI Text Request
- * Text Response - iSCSI Text Response
- * Login Request - iSCSI Login Request
- * Login Response - iSCSI Login Response
- * Reject - reject desriptor
- * Nop-Out - data accompanying Nop-Out PDU (iSCSI ping)
- * Nop-In - data accompanying Nop-In PDU (iSCSI return
ping)
- *
------------------------------------------------------------
- */
- struct {
- /* data segment of a generic tx PDU */
- struct iser_data_buf buf;
- } tx;
- /* Any Received PDU */
- } data; /* PDU data segment descriptor */
-
-}; /* iser_send_pdu */
-
-/*!
--------------------------------------------------------------------
- [iser_recv_pdu]
-
- Description: received control PDU descriptor; passed to
Control_Notify
- --------------------------------------------------------------------
*/
-struct iser_recv_pdu {
-
- union iser_pdu_bhs *p_bhs; /* BHS */
-
- struct iser_data_buf rx_data; /* data segment */
-}; /* iser_recv_pdu */
-
-#endif /* __ISER_PDU_H__ */
Index: include/iser_api.h
===================================================================
--- include/iser_api.h (revision 3404)
+++ include/iser_api.h (working copy)
@@ -34,98 +34,294 @@
#ifndef __ISER_API_H__
#define __ISER_API_H__
-#include <linux/socket.h>
-#include <linux/in.h>
+#include <linux/types.h>
+#include <linux/net.h>
-#include "iser_types.h"
-#include "iser_pdu.h"
+/**
+ * iser_data_buf - generic iSER buffer descriptor
+ */
-/* Functions exported by iSER datamover layer for iSCSI layer */
+enum iser_buf_type {
+ ISER_BUF_TYPE_SINGLE = 0, /* single contiguous buffer */
+ ISER_BUF_TYPE_SCATTERLIST, /* struct scatterlist array */
+ ISER_BUF_TYPES_NUM
+};
-typedef iser_status
- (*iser_conn_establish_func) (void *api_h,
- void *iscsi_conn_h,
- struct sockaddr_in * dst_addr,
- struct sockaddr_in * src_addr);
-typedef iser_status
- (*iser_enable_datamover_func) (void *conn_h, void *tport_conn);
+struct iser_data_buf {
+ void *p_buf;
+ unsigned int size;
+ enum iser_buf_type type;
+};
-typedef iser_status(*iser_dealloc_conn_res_func) (void *conn_h);
+#define AF_ISER 28 /* to be defined properly */
-typedef iser_status
- (*iser_send_control_func) (void *conn_h,
- struct iser_send_pdu * p_ctrl_pdu);
+/**
+ * iser_pdu_bhs - iSCSI PDU Basic Header Segment (BHS)
+ *
+ * The purpose of defining BHS here is define the fields relevant
+ * to iSER operation. iSCSI layer should have its own definitions and
+ * may view the BHS passed to iSER just as a buffer.
+ * In order to avoid potential name collision, the structure has
+ * "iser" prefix, although strictly speaking it must be "iscsi".
+ */
+#define ISER_PDU_BHS_LENGTH 48
+union iser_pdu_bhs {
-/* extention API function, iSCSI layer notifies iSER datamover layer
- that an iSCSI control-type PDU previously passed through the
Control_Notify
- primitive is no longer in use and its memory may be released.
-*/
-typedef iser_status
- (*iser_release_control_func) (void *conn_h,
- struct iser_recv_pdu * p_ctrl_pdu);
+ unsigned char buf[ISER_PDU_BHS_LENGTH];
-typedef iser_status(*iser_connectionerminate_func) (void *conn_h);
+ struct {
+ uint8_t opcode; /* optional bits + opcode */
+ uint8_t flags; /* opcode-specific flags */
+ uint8_t rsvd[2]; /* usually reserved, used in
response */
+ uint8_t ahs_length; /* AHS total length */
+ uint8_t dlength[3]; /* Data segment length */
+ uint8_t lun[8]; /* LUN */
+ uint8_t itt[4]; /* Initiator Task Tag */
+ uint8_t other[28]; /* opcode-specific */
+ } byte;
-typedef iser_status
- (*iser_dealloc_task_res_func) (void *conn_h, unsigned int itt);
+ struct {
+ uint32_t op_flg_rsvd; /* opcode, flags, reserved */
+ uint32_t length; /* AHS length, Data segment
length */
+ uint32_t lun[2]; /* LUN */
+ uint32_t itt; /* Initiator Task Tag */
+ uint32_t other[7]; /* opcode-specific */
+ } dword;
+}; /* iser_pdu_bhs */
-typedef iser_status
- (*iser_notice_key_values_func) (void *conn_h, char *key, char
*value);
+/**
+ * opcode byte
+ */
-struct iser_conn_res {
- void *api_h; /* IN */
- struct sockaddr_in *dst_addr; /* IN */
- struct sockaddr_in *src_addr; /* IN */
- unsigned int max_recv_pdu_sz; /* to be deleted!!! */
- /* Maximal PDU size, receiving of which should be anticipated */
- unsigned int first_burst_length; /* IN */
- unsigned int max_recv_dsl; /* IN */
- unsigned int max_outstand_cmds; /* IN */
+/* Set when marked for immediate delivery */
+#define ISCSI_OP_IMMEDIATE 0x40
+/* Masks out the opcode itself */
+#define ISCSI_OPCODE_MASK 0x3F
- unsigned int num_reg_buf; /* IN */
-}; /* iser_conn_res */
+/* Initiator only opcode values */
+#define ISCSI_OP_NOP_OUT 0x00
+#define ISCSI_OP_SCSI_CMD 0x01
+#define ISCSI_OP_TASK_MGT_REQ 0x02
+#define ISCSI_OP_LOGIN_REQ 0x03
+#define ISCSI_OP_TEXT_REQ 0x04
+#define ISCSI_OP_DATA_OUT 0x05
+#define ISCSI_OP_LOGOUT_REQ 0x06
+#define ISCSI_OP_SNACK_REQ 0x10
-typedef iser_status(*iser_alloc_conn_res_func)
- (void *conn_h, struct iser_conn_res * conn_res);
+/* Target only opcode values */
+#define ISCSI_OP_NOP_IN 0x20
+#define ISCSI_OP_SCSI_RSP 0x21
+#define ISCSI_OP_TASK_MGT_RSP 0x22
+#define ISCSI_OP_LOGIN_RSP 0x23
+#define ISCSI_OP_TEXT_RSP 0x24
+#define ISCSI_OP_DATA_IN 0x25
+#define ISCSI_OP_LOGOUT_RSP 0x26
+#define ISCSI_OP_R2T 0x31
+#define ISCSI_OP_ASYNC 0x32
+#define ISCSI_OP_REJECT 0x3f
-struct iser_api {
- iser_conn_establish_func conn_establish;
- iser_send_control_func send_control;
- iser_release_control_func release_control;
- iser_alloc_conn_res_func alloc_conn_res;
- iser_notice_key_values_func notice_key_values;
- iser_enable_datamover_func enable_datamover;
- iser_connectionerminate_func conn_terminate;
- iser_dealloc_conn_res_func dealloc_conn_res;
- iser_dealloc_task_res_func dealloc_task_res;
+/**
+ * flags byte
+ */
+
+/* When set indicates the final (or only) PDU of a sequence */
+#define ISCSI_FLAG_FINAL 0x80
+/* When set indicates that data is to be read */
+#define ISCSI_FLAG_READ_CMD 0x40
+/* When set indicates that data is to be written */
+#define ISCSI_FLAG_WRITE_CMD 0x20
+
+#define IS_SET_ISCSI_FLAG_FINAL(x) \
+ (ISCSI_FLAG_FINAL & x)
+
+#define IS_SET_ISCSI_FLAG_READ_CMD(x) \
+ (ISCSI_FLAG_READ_CMD & x)
+
+#define IS_SET_ISCSI_FLAG_WRITE_CMD(x) \
+ (ISCSI_FLAG_WRITE_CMD & x)
+
+/* Login specific */
+#define ISCSI_FLAG_LOGIN_TRANSIT 0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE 0x40
+
+#define IS_SET_ISCSI_FLAG_LOGIN_TRANSIT(x) \
+ (ISCSI_FLAG_LOGIN_TRANSIT & x)
+
+#define IS_SET_ISCSI_FLAG_LOGIN_CONTINUE(x) \
+ (ISCSI_FLAG_LOGIN_CONTINUE & x)
+
+#define ISCSI_FLAG_LOGIN_CSG_MASK 0x0C
+#define ISCSI_FLAG_LOGIN_NSG_MASK 0x03
+
+#define GET_ISCSI_FLAG_LOGIN_CSG(x) \
+ (ISCSI_FLAG_LOGIN_CSG_MASK & x)
+
+#define GET_ISCSI_FLAG_LOGIN_NSG(x) \
+ (ISCSI_FLAG_LOGIN_NSG_MASK & x)
+
+#define ISCSI_LOGIN_STAGE_SECURITY 0x00
+#define ISCSI_LOGIN_STAGE_OPERATIONAL 0x01
+#define ISCSI_LOGIN_STAGE_FULL_FEATURE 0x03
+
+#define IS_ISCSI_LOGIN_NSG_OPERATIONAL(x) \
+ (GET_ISCSI_FLAG_LOGIN_NSG(x) ==
ISCSI_LOGIN_STAGE_OPERATIONAL)
+
+#define IS_ISCSI_LOGIN_NSG_FULL_FEATURE(x) \
+ (GET_ISCSI_FLAG_LOGIN_NSG(x) ==
ISCSI_LOGIN_STAGE_FULL_FEATURE)
+
+#define ISCSI_AHSL_MASK 0xFF000000
+#define ISCSI_DSL_MASK 0x00FFFFFF
+
+#define ISCSI_INVALID_ITT 0xFFFFFFFF
+
+/**
+ * opcode-specific dword fields,
+ * offsets are indices of: iser_pdu_bhs.dword.other
+ */
+
+/* SCSI Command */
+#define ISCSI_CMD_F_EDTL 0
+#define ISCSI_CMD_F_CMDSN 1
+#define ISCSI_CMD_F_EXP_STATSN 2
+
+/* Data-OUT */
+#define ISCSI_DOUT_F_TTT 0
+#define ISCSI_DOUT_F_EXP_STATSN 2
+#define ISCSI_DOUT_F_DATASN 4
+#define ISCSI_DOUT_F_OFFSET 5
+
+/**
+ * iser_send_pdu - descriptor of a control PDU to be sent by
send_control
+ */
+struct iser_send_pdu {
+ union iser_pdu_bhs *p_bhs; /* BHS */
+ union {
+ /* Command */
+ struct {
+ struct iser_data_buf buf_out;
+ struct iser_data_buf buf_in;
+ struct iser_data_buf ahs;
+ /* size of immediate unsolicited data for
+ write/bidir command, will be sent as
+ the data segment of the command PDU */
+ unsigned int immediate_sz;
+ /* entire unsolicited data for write/bidir
command,
+ will be sent in data segments of command
+ and data-out PDUs */
+ unsigned int unsolicited_sz;
+ } command;
+ /* Task Mgt Request */
+ struct {
+ /* data-out for the entire write/bidir command,
+ valid only if Function=TASK REASSIGN */
+ struct iser_data_buf buf_in;
+ /* data-out for the entire read/bidir command,
+ valid only if Function=TASK REASSIGN */
+ struct iser_data_buf buf_out;
+ } task_mgt_req;
+ /* Other Transmitted PDUs:
+ * Data-Out - disregarded, offset & DSL fields of BHS
are used
+ * Text Request - iSCSI Text Request
+ * Login Request - iSCSI Login Request
+ * Nop-Out - data accompanying Nop-Out PDU (iSCSI ping)
+ */
+ struct {
+ struct iser_data_buf buf;
+ } tx;
+ } data;
+}; /* iser_send_pdu */
+
+/**
+ * iser_recv_pdu - received control PDU descriptor; passed to
control_notify
+ */
+struct iser_recv_pdu {
+ union iser_pdu_bhs *p_bhs; /* BHS */
+ struct iser_data_buf rx_data; /* data segment */
+}; /* iser_recv_pdu */
+
+/**
+ * Functions exported by iSER layer for iSCSI layer
+ */
+
+struct iser_conn_res {
+ unsigned int first_burst_length;
+ unsigned int max_recv_dsl;
+ unsigned int max_outstand_cmds;
};
-/* Functions exported by iSCSI layer for iSER datamover layer */
+/* bind connection previosuly established thru a socket */
+typedef int
+(*iser_conn_bind_func) (void *iscsi_conn_h, /* IN */
+ struct socket *sock, /* IN */
+ void **iser_conn_h); /* OUT */
-typedef iser_status(*iser_conn_establish_notify_func) (void
*iscsi_conn_h,
- int established);
+/* pass a finalized key-value pair */
+typedef int
+(*iser_notice_key_values_func) (void *iser_conn_h,
+ char *key, char *value);
-typedef void (*iser_control_notify_func) (void *conn_h,
- struct iser_recv_pdu *
p_ctrl_pdu);
+/* allocate connection resources and enable datamover rdma
functionality */
+typedef int
+(*iser_conn_enable_rdma_func) (void *iser_conn_h,
+ struct iser_conn_res *conn_res);
-typedef void (*iser_connectionerm_notify_func) (void *conn_h);
+/* send iSCSI control-type PDU, also appropriate for Login phase */
+typedef int
+(*iser_send_control_func) (void *iser_conn_h,
+ struct iser_send_pdu *p_ctrl_pdu);
-/* Callbacks registration */
+/* deallocate connection resources */
+typedef int
+(*iser_dealloc_conn_res_func) (void *iser_conn_h);
+/* signal that iSCSI control-type PDU previously passed through
+ control_notify() is no longer in use, its resources may be released
*/
+typedef int
+(*iser_release_control_func) (void *iser_conn_h,
+ struct iser_recv_pdu *p_ctrl_pdu);
+
+/* terminate a connection */
+typedef int
+(*iser_conn_terminate_func) (void *iser_conn_h);
+
+/* release all iSER task resources */
+typedef int
+(*iser_dealloc_task_res_func) (void *iser_conn_h, unsigned int itt);
+
+struct iser_api {
+ iser_conn_bind_func conn_bind;
+ iser_notice_key_values_func notice_key_values;
+ iser_conn_enable_rdma_func conn_enable_rdma;
+ iser_send_control_func send_control;
+ iser_release_control_func release_control;
+ iser_conn_terminate_func conn_terminate;
+ iser_dealloc_conn_res_func dealloc_conn_res;
+ iser_dealloc_task_res_func dealloc_task_res;
+};
+
+/**
+ * Functions exported by iSCSI layer for iSER layer
+ */
+
+typedef void
+(*iser_control_notify_func) (void *iscsi_conn_h,
+ struct iser_recv_pdu *p_ctrl_pdu);
+typedef void
+(*iser_conn_term_notify_func) (void *iscsi_conn_h);
+
struct iser_api_cb {
- iser_conn_establish_notify_func conn_establish_notify;
- iser_connectionerm_notify_func conn_terminate_notify;
iser_control_notify_func control_notify;
+ iser_conn_term_notify_func conn_term_notify;
};
-#define ISER_INVALID_API_H ((void *)~0x0)
+/**
+ * iSER API registration
+ */
-iser_status
-iser_api_register(char *provider_name,
- struct iser_api *api,
- struct iser_api_cb *api_cb, void **p_api_h);
+int iser_api_register(char *provider_name,
+ struct iser_api *api, /* OUT */
+ struct iser_api_cb *api_cb); /* IN */
-/* Unregister API previously registered for this entity */
-iser_status iser_api_unregister(void *api_h); /* IN */
+int iser_api_unregister(void);
-#endif /* __ISER_API_H__ */
+#endif /* __ISER_API_H__ */
Index: include/iser_types.h
===================================================================
--- include/iser_types.h (revision 3404)
+++ include/iser_types.h (working copy)
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 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.
- *
- */
-
-#ifndef __ISER_TYPES_H__
-#define __ISER_TYPES_H__
-
-typedef enum {
- ISER_SUCCESS = 0, /* operation successful */
- ISER_FAILURE, /* operation failed */
- ISER_INVALID_CONN, /* invalid conn handle supplied */
- ISER_INVALID_ITT, /* invalid Initiator Task Tag supplied
*/
- ISER_ILLEGAL_PARAM, /* illegal value of a parameter,
- e.g. NULL pointer */
- ISER_UNREGISTERED, /* this function has not been registered
*/
- ISER_INVALID_KEY, /* Unsupported or invalid key passed to
- Notice_Key_Value */
- ISER_INVALID_VALUE, /* Unsupported or invalid value passed
to
- Notice_Key_Value */
-} iser_status;
-
-enum iser_buf_type {
- ISER_BUF_TYPE_SINGLE = 0, /* single contiguous buffer */
- ISER_BUF_TYPE_SCATTERLIST, /* struct scatterlist array */
- ISER_BUF_TYPES_NUM
-};
-
-struct iser_data_buf {
- void *p_buf;
- unsigned int size;
- enum iser_buf_type type;
-};
-
-#endif /* __ISER_TYPES_H__ */
Index: iser.h
===================================================================
--- iser.h (revision 3404)
+++ iser.h (working copy)
@@ -65,7 +65,6 @@
/* Various size limits */
#define ISER_LOGIN_PHASE_PDU_DATA_LEN (8*1024) /* 8K */
#define ISER_MIN_RECV_DSL (8*1024) /* 8K */
-#define ISER_MAX_CMD_SIZE (2*1024*1024) /* 2M */
#define ISER_MAX_FIRST_BURST (128*1024) /* 128K */
#define ISER_MAX_CTRLS_PER_CMD(first_burst,recv_dsl,imm) \
@@ -226,7 +225,6 @@
struct iser_connection {
void *iscsi_conn_h; /* iSCSI-supplied handle */
struct iser_adaptor *p_adaptor; /* IA context */
- struct iser_entity *p_entity; /* iSCSI entity */
atomic_t state; /* Connection state */
spinlock_t conn_lock; /* Guards the conn and
related structures */
@@ -239,37 +237,21 @@
hash buckets */
struct list_head adaptor_list; /* Entry in the adaptor's
list of conns */
- struct list_head entity_list; /* Entry in the entity
- list of conns */
- struct dat_ep *ep_handle; /* End-Point of the conn */
- struct iser_buf_pool *post_recv_pool; /* Pool of post_recv
- buffers */
- struct iser_buf_pool *send_data_pool; /* Pool of send data
- buffers */
- atomic_t post_recv_buf_count; /* Counter of posted
- recv buffers */
- atomic_t post_send_buf_count; /* Counter of posted
- send buffers */
- struct list_head ctrl_notify_dto_list; /* controls passed
- to ctrl_notify() */
- struct iser_op_params param; /* Session operational
parameters */
- unsigned int max_outstand_cmds; /* current max allowed
- commands */
- unsigned int initial_post_recv_bufs_num; /* posted at
- the beginning
*/
- /* allocd through a buffer pool */
+ struct dat_ep *ep_handle;
+ struct iser_buf_pool *post_recv_pool;
+ struct iser_buf_pool *send_data_pool;
+ atomic_t post_recv_buf_count;
+ atomic_t post_send_buf_count;
+ struct list_head ctrl_notify_dto_list; /* controls pushed to
issci */
+ struct iser_op_params param; /* operational parameters */
+ unsigned int max_outstand_cmds;
+ unsigned int initial_post_recv_bufs_num;
unsigned int alloc_post_recv_bufs_num;
- int disc_evt_flag; /* Set if EVENT_DISCONNECTED
- is received from DAPL */
- wait_queue_head_t disconnect_wait_q; /* for waiting for a
- disconn completion */
- struct iser_buf_pool *spare_post_recv_pool; /* Pool of
post_recv
- buffers */
- struct iser_buf_pool *spare_send_data_pool; /* Pool of
send_data
- buffers */
- char name[ISER_OBJECT_NAME_SIZE]; /* Conn. name -
- e.g. ip addr */
-
+ int disc_evt_flag; /* Set if disconnect event recvd */
+ wait_queue_head_t disconnect_wait_q;
+ struct iser_buf_pool *spare_post_recv_pool;
+ struct iser_buf_pool *spare_send_data_pool;
+ char name[ISER_OBJECT_NAME_SIZE];
};
struct iser_regd_buf {
@@ -388,19 +370,8 @@
};
#define ISER_MAX_ADAPTORS 1
-#define ISER_MAX_ENTITIES 1
#define ISER_MAX_CONN 4
-struct iser_entity {
- int registered;
- struct iser_api_cb api_cb;
- /* List of all iSER conns on this adaptor */
- spinlock_t conn_lock;
- struct list_head conn_list;
- /* name of the iSCSI layer entity provider */
- char provider_name[ISER_OBJECT_NAME_SIZE];
-};
-
struct iser_adaptor {
struct dat_ia *ia_handle; /* Interface Adaptor */
struct dat_pz *pz_handle; /* Protection Zone */
@@ -445,23 +416,17 @@
* providers use this iSER datamover.
*/
struct iser_global {
- /* IA context, Future: array of adaptors, by name */
unsigned int num_adaptors;
struct iser_adaptor adaptor[ISER_MAX_ADAPTORS];
- /* Ext API callbacks registration */
- unsigned int num_entities;
- struct iser_entity entity[ISER_MAX_ENTITIES];
- /* Memory pools */
- kmem_cache_t *conn_mem_cache; /* slab for iser_connection */
+
kmem_cache_t *task_mem_cache; /* slab for iser_task */
kmem_cache_t *recv_dto_mem_cache; /* slab for iser_dto */
kmem_cache_t *send_dto_mem_cache; /* slab for iser_dto */
kmem_cache_t *regd_buf_mem_cache; /* for iser_regd_buf */
- /* Hash tables */
struct hash_table task_hash; /* hash table for tasks */
- struct hash_table conn_hash; /* conns */
-
+ struct iser_api_cb api_cb;
+ char provider_name[ISER_OBJECT_NAME_SIZE];
}; /* iser_global */
extern struct iser_global ig;
Index: iser_dto.c
===================================================================
--- iser_dto.c (revision 3404)
+++ iser_dto.c (working copy)
@@ -144,7 +144,7 @@
cur_buf = 0;
do {
- contig = iser_iovec_contig_length(p_mem, cur_buf,
+ contig = iser_data_contig_length(p_mem, cur_buf,
&contig_start_addr,
&contig_size);
/* Try to find the buffer in the pre-registered cache */
@@ -163,16 +163,16 @@
/* If got here using a pre-registered buffer is not an
option,
register memory */
/* Determine an aligned stretch */
- aligned_len = iser_iovec_aligned_length(p_mem, cur_buf);
+ aligned_len = iser_data_aligned_length(p_mem, cur_buf);
if (p_mem->type != ISER_BUF_TYPE_SINGLE) {
- p_phys_vec = iser_alloc_phys_mem(p_mem, cur_buf,
+ p_phys_vec = iser_alloc_phys_desc(p_mem,
cur_buf,
aligned_len);
- iser_convert_mem_to_phys(p_mem, p_phys_vec,
cur_buf,
+ iser_data_convert_to_phys(p_mem, p_phys_vec,
cur_buf,
aligned_len);
} else {
p_phys_vec =
- iser_alloc_phys_mem(p_mem, 0, p_mem->size);
- iser_convert_mem_to_phys(p_mem, p_phys_vec, 0,
0);
+ iser_alloc_phys_desc(p_mem, 0, p_mem->size);
+ iser_data_convert_to_phys(p_mem, p_phys_vec, 0,
0);
}
p_regd_buf = (struct iser_regd_buf *)
@@ -182,7 +182,7 @@
printk(KERN_ERR PFX
"Failed to alloc registered buffer\n");
ret_val = -1;
- iser_free_phys_mem(p_phys_vec);
+ iser_free_phys_desc(p_phys_vec);
goto dto_add_local_memory_exit;
}
memset(p_regd_buf, 0, sizeof(struct iser_regd_buf));
@@ -198,7 +198,7 @@
"Failed to register %d phys entries "
"starting from %d\n", aligned_len,
cur_buf);
/* ToDo: deregister all previously allocd memory
*/
- iser_free_phys_mem(p_phys_vec);
+ iser_free_phys_desc(p_phys_vec);
goto dto_add_local_memory_exit;
}
@@ -218,11 +218,10 @@
"to add %d phys.entries\n",
p_regd_buf, p_dto, p_dto->regd_vector_len,
p_mem->size);
- iser_free_phys_mem(p_phys_vec);
+ iser_free_phys_desc(p_phys_vec);
} while (cur_buf < p_mem->size);
- dto_add_local_memory_exit:
-
+ dto_add_local_memory_exit:
return ret_val;
} /* iser_dto_add_local_memory */
Index: iser_pdu.c
===================================================================
--- iser_pdu.c (revision 3404)
+++ iser_pdu.c (working copy)
@@ -1,1274 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 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.
- *
- */
-
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <scsi/scsi.h>
-
-#include "iser.h"
-#include "iser_bhs.h"
-#include "iser_global.h"
-#include "iser_utils.h"
-#include "iser_trace.h"
-
-/* size of the buffer for trace string accumulation */
-#define PRINT_BUF_LEN 1024
-/* max size of data printed in a single block */
-#define ISER_PDU_PRINT_MAX_DATA_BLOCK_LEN 256
-
-/* current position witin the print buffer */
-static int print_buf_pos = 0;
-/* set if the buffer was truncated to avoid overflow */
-static int print_buf_trunc = 0;
-/* print buffer */
-static char print_buf[PRINT_BUF_LEN];
-
-#define PRINT_BUFF_CAT( fmt , args... ) \
- do { \
- if( !print_buf_trunc && print_buf_pos + 32 < PRINT_BUF_LEN ) \
- print_buf_pos += sprintf(print_buf+print_buf_pos, fmt , ##
args); \
- else if( !print_buf_trunc ) { \
- print_buf_pos += \
- sprintf(print_buf+print_buf_pos, " ... (deleted)\n");
\
- print_buf_trunc = 1; \
- } \
- } while(0)
-
-#define PRINT_BUFF_OUT() \
- do { \
- sprintf(print_buf+print_buf_pos, "\n"); \
- print_buf_pos = 0; print_buf_trunc = 0; \
- ISER_DEBUG_LOG(print_buf); \
- } while(0)
-
-union u64_view {
- __u64 x;
- __u8 c[8];
-};
-
-static char *
-string_llx( __u64 x )
-{
- int i;
- static char str[20];
- static char convert[] = "0123456789abcdef";
- char *ptr;
- __u32 c;
- union u64_view tmp;
-
- tmp.x = x;
- ptr = str;
- *ptr++ = '0';
- *ptr++ = 'x';
- for( i = 7; i >= 0; i-- )
- {
- c = tmp.c[i];
- *ptr++ = convert[c>>4];
- *ptr++ = convert[c&0xf];
- }
- *ptr = '\0';
- return str;
-}
-
-
-static void
-print_rsvd_u8( int n, __u8 rsvd )
-{
- if( rsvd != 0 )
- PRINT_BUFF_CAT("rsvd%d: 0x%.2x ", n, rsvd);
-}
-
-
-static void
-print_rsvd_u16( int n, __u16 rsvd )
-{
- if( rsvd != 0 )
- PRINT_BUFF_CAT("rsvd%d: 0x%.4x ", n, rsvd);
-}
-
-
-static void
-print_rsvd_u32( int n, __u32 rsvd )
-{
- if( rsvd != 0 )
- PRINT_BUFF_CAT("rsvd%d: 0x%.8x ", n, rsvd);
-}
-
-
-static void
-print_rsvd_u64( int n, __u64 rsvd )
-{
- if( rsvd != 0ll )
- PRINT_BUFF_CAT("rsvd%d: %s ", n, string_llx(rsvd));
-}
-
-
-static void
-print_opcode( __u8 opcode )
-{
- PRINT_BUFF_CAT("(0x%.2X%s) ",
- opcode&0x3f, ((opcode&0x40)!=0 ? "-Imm" : "") );
-}
-
-
-static void
-print_flags( __u8 flags )
-{
- PRINT_BUFF_CAT("flags: 0x%.2x ", flags);
-}
-
-
-static void
-print_version( char *which, __u8 version )
-{
- PRINT_BUFF_CAT("Version%s: 0x%.2x ", which, version);
-}
-
-
-static void
-print_response( __u8 response )
-{
- if ( response == 0x00 ) {
- PRINT_BUFF_CAT("Resp: Completed(0) ");
- }
- else if ( response == 0x01 ) {
- PRINT_BUFF_CAT("Resp: Failure(1) ");
- }
- else {
- PRINT_BUFF_CAT("Resp: Vendor(%d) ", response);
- }
-}
-
-
-static void
-print_status( __u8 status )
-{
- if ( status == 0x00 ) {
- PRINT_BUFF_CAT("Status: GOOD(0) ");
- }
- else if ( status == 0x02 ) {
- PRINT_BUFF_CAT("Status: CHCK(2) ");
- }
- else if ( status == 0x08 ) {
- PRINT_BUFF_CAT("Status: BUSY(2) ");
- }
- else {
- PRINT_BUFF_CAT("Status: 0x%.2x ", status);
- }
-}
-
-
-static void
-print_lun( __u64 lun )
-{
- PRINT_BUFF_CAT("LUN: %s ", string_llx(lun));
-}
-
-
-static void
-print_isid_tsih( __u8 isid[6], __u16 tsih )
-{
- PRINT_BUFF_CAT("ISID: 0x%.2x %.2x %.2x %.2x %.2x %.2x ",
- isid[0], isid[1], isid[2], isid[3], isid[4],
isid[5]);
- PRINT_BUFF_CAT("TSIH: %u ", be16_to_cpu(tsih));
-}
-
-
-static void
-print_dsl( __u32 length )
-{
- __u32 be32_length = be32_to_cpu(length);
-
- PRINT_BUFF_CAT("DSL: 0x%X(%u) ", be32_length, be32_length);
-}
-
-static void
-print_itt( __u32 init_task_tag )
-{
- if( init_task_tag == 0xffffffff )
- PRINT_BUFF_CAT("ITT: 0x%08X ", init_task_tag);
- else {
- __u32 be32_init_task_tag = be32_to_cpu(init_task_tag);
- PRINT_BUFF_CAT("ITT: 0x%X(%u) ",
- be32_init_task_tag, be32_init_task_tag);
- }
-}
-
-
-static void
-print_ttt( __u32 target_xfer_tag )
-{
- if( target_xfer_tag == 0xffffffff )
- PRINT_BUFF_CAT("TTT: 0x%08x ", target_xfer_tag);
- else
- PRINT_BUFF_CAT("TTT: %u ", be32_to_cpu(target_xfer_tag));
-}
-
-
-static void
-print_cid( __u16 cid )
-{
- PRINT_BUFF_CAT("CID: %u ", be16_to_cpu(cid));
-}
-
-
-static void
-print_expstatsn( __u32 exp_stat_sn )
-{
- if( exp_stat_sn != 0 )
- PRINT_BUFF_CAT("ExpStatSN: %u ", be32_to_cpu(exp_stat_sn));
-}
-
-
-static void
-print_cmdsn_expstatsn( __u32 cmd_sn, __u32 exp_stat_sn )
-{
- PRINT_BUFF_CAT("CmdSN: %u ", be32_to_cpu(cmd_sn));
- print_expstatsn(exp_stat_sn);
-}
-
-
-static void
-print_statsn_exp_max( __u32 stat_sn, __u32 exp_cmd_sn, __u32 max_cmd_sn
)
-{
- if( stat_sn != 0 )
- PRINT_BUFF_CAT("StatSN: %u ", be32_to_cpu(stat_sn));
- PRINT_BUFF_CAT("ExpCmdSN: %u ", be32_to_cpu(exp_cmd_sn));
- PRINT_BUFF_CAT("MaxCmdSN: %u ", be32_to_cpu(max_cmd_sn));
-}
-
-
-static void
-print_residual( __u32 resid )
-{
- if( resid != 0 )
- PRINT_BUFF_CAT("ResidualCount: %u ", be32_to_cpu(resid));
-}
-
-
-static void
-print_datasn( __u32 data_sn )
-{
- PRINT_BUFF_CAT("DataSN: %u ", be32_to_cpu(data_sn));
-}
-
-static void
-print_offset( __u32 offset, __u32 length )
-{
- __u32 be32_offset = be32_to_cpu(offset);
- __u32 be32_length = be32_to_cpu(length);
-
- PRINT_BUFF_CAT("Buf: %u-%u ",
- be32_offset, be32_offset+be32_length);
-}
-
-
-static void
-print_rtt( __u32 ref_task_tag )
-{
- if( ref_task_tag != 0 )
- PRINT_BUFF_CAT("RTT: 0x%.8x ", be32_to_cpu(ref_task_tag));
-}
-
-
-static void
-print_exp_data_sn( __u32 exp_data_sn )
-{
- if( exp_data_sn != 0 )
- PRINT_BUFF_CAT("ExpDataSN: %u ", be32_to_cpu(exp_data_sn));
-}
-
-
-static void
-print_begrun( __u32 begrun )
-{
- PRINT_BUFF_CAT("BegRun: %u ", be32_to_cpu(begrun));
-}
-
-
-static void
-print_runlen( __u32 runlen )
-{
- PRINT_BUFF_CAT("RunLength: %u ", be32_to_cpu(runlen));
-}
-
-/* command opcodes which don't appear in <scsi/scsi.h> */
-#define EXTENDED_COPY 0x83
-#define MOVE_MEDIUM_ATTACHED 0xa7
-#define READ_ELEMENT_STATUS_ATTACHED 0xb4
-#define RECEIVE_COPY_RESULTS 0x84
-#define REPORT_DEVICE_ID 0xa3
-#define REPORT_LUNS 0xa0
-#define SET_DEVICE_ID 0xa4
-
-static void
-print_scsi_cdb_op( __u8 opcode )
-{
- char *result = "UNKNOWN";
-
- /* opcode symbols defined in <scsi/scsi.h> */
- /* this table includes only those symbols we have actually seen
- being sent to/from a vendor */
- switch( opcode )
- {
- case TEST_UNIT_READY: /* 0x00 */
- result = "TEST_UNIT_READY";
- break;
- case REZERO_UNIT: /* 0x01 */
- result = "REWIND";
- break;
- case REQUEST_SENSE: /* 0x03 */
- result = "REQUEST_SENSE";
- break;
- case READ_BLOCK_LIMITS: /* 0x05 */
- result = "READ_BLOCK_LIMITS";
- break;
- case READ_6: /* 0x08 */
- result = "READ_6";
- break;
- case WRITE_6: /* 0x0a */
- result = "WRITE_6";
- break;
- case WRITE_FILEMARKS: /* 0x10 */
- result = "WRITE_FILEMARKS";
- break;
- case INQUIRY: /* 0x12 */
- result = "INQUIRY";
- break;
- case MODE_SENSE: /* 0x1a */
- result = "MODE_SENSE";
- break;
- case READ_CAPACITY: /* 0x25 */
- result = "READ_CAPACITY";
- break;
- case READ_10: /* 0x28 */
- result = "READ_10";
- break;
- case WRITE_10: /* 0x2a */
- result = "WRITE_10";
- break;
- case READ_12: /* 0xa8 */
- result = "READ_12";
- break;
- case WRITE_12: /* 0xaa */
- result = "WRITE_12";
- break;
- case FORMAT_UNIT: /* 0x04 */
- result = "FORMAT_UNIT";
- break;
- case REASSIGN_BLOCKS: /* 0x07 */
- result = "REASSIGN_BLOCKS";
- break;
- case SEEK_6: /* 0x0b */
- result = "SEEK_6";
- break;
- case READ_REVERSE: /* 0x0f */
- result = "READ_REVERSE";
- break;
- case SPACE: /* 0x11 */
- result = "SPACE";
- break;
- case RECOVER_BUFFERED_DATA: /* 0x14 */
- result = "RECOVER_BUFFERED_DATA";
- break;
- case MODE_SELECT: /* 0x15 */
- result = "MODE_SELECT";
- break;
- case RESERVE: /* 0x16 */
- result = "RESERVE";
- break;
- case RELEASE: /* 0x17 */
- result = "RELEASE";
- break;
- case COPY: /* 0x18 */
- result = "COPY";
- break;
- case ERASE: /* 0x19 */
- result = "ERASE";
- break;
- case START_STOP: /* 0x1b */
- result = "START_STOP";
- break;
- case RECEIVE_DIAGNOSTIC: /* 0x1c */
- result = "RECEIVE_DIAGNOSTIC";
- break;
- case SEND_DIAGNOSTIC: /* 0x1d */
- result = "SEND_DIAGNOSTIC";
- break;
- case ALLOW_MEDIUM_REMOVAL: /* 0x1e */
- result = "ALLOW_MEDIUM_REMOVAL";
- break;
- case SET_WINDOW: /* 0x24 */
- result = "SET_WINDOW";
- break;
- case SEEK_10: /* 0x2b */
- result = "SEEK_10";
- break;
- case WRITE_VERIFY: /* 0x2e */
- result = "WRITE_VERIFY";
- break;
- case VERIFY: /* 0x2f */
- result = "VERIFY";
- break;
- case SEARCH_HIGH: /* 0x30 */
- result = "SEARCH_HIGH";
- break;
- case SEARCH_EQUAL: /* 0x31 */
- result = "SEARCH_EQUAL";
- break;
- case SEARCH_LOW: /* 0x32 */
- result = "SEARCH_LOW";
- break;
- case SET_LIMITS: /* 0x33 */
- result = "SET_LIMITS";
- break;
- case PRE_FETCH: /* 0x34 */
- result = "PRE_FETCH";
- break;
- case SYNCHRONIZE_CACHE: /* 0x35 */
- result = "SYNCHRONIZE_CACHE";
- break;
- case LOCK_UNLOCK_CACHE: /* 0x36 */
- result = "LOCK_UNLOCK_CACHE";
- break;
- case READ_DEFECT_DATA: /* 0x37 */
- result = "READ_DEFECT_DATA";
- break;
- case MEDIUM_SCAN: /* 0x38 */
- result = "MEDIUM_SCAN";
- break;
- case COMPARE: /* 0x39 */
- result = "COMPARE";
- break;
- case COPY_VERIFY: /* 0x3a */
- result = "COPY_VERIFY";
- break;
- case WRITE_BUFFER: /* 0x3b */
- result = "WRITE_BUFFER";
- break;
- case READ_BUFFER: /* 0x3c */
- result = "READ_BUFFER";
- break;
- case UPDATE_BLOCK: /* 0x3d */
- result = "UPDATE_BLOCK";
- break;
- case READ_LONG: /* 0x3e */
- result = "READ_LONG";
- break;
- case WRITE_LONG: /* 0x3f */
- result = "WRITE_LONG";
- break;
- case CHANGE_DEFINITION: /* 0x40 */
- result = "CHANGE_DEFINITION";
- break;
- case WRITE_SAME: /* 0x41 */
- result = "WRITE_SAME";
- break;
- case READ_TOC: /* 0x43 */
- result = "READ_TOC";
- break;
- case LOG_SELECT: /* 0x4c */
- result = "LOG_SELECT";
- break;
- case LOG_SENSE: /* 0x4d */
- result = "LOG_SENSE";
- break;
- case MODE_SELECT_10: /* 0x55 */
- result = "MODE_SELECT_10";
- break;
- case RESERVE_10: /* 0x56 */
- result = "RESERVE_10";
- break;
- case RELEASE_10: /* 0x57 */
- result = "RELEASE_10";
- break;
- case MODE_SENSE_10: /* 0x5a */
- result = "MODE_SENSE_10";
- break;
- case PERSISTENT_RESERVE_IN: /* 0x5e */
- result = "PERSISTENT_RESERVE_IN";
- break;
- case PERSISTENT_RESERVE_OUT: /* 0x5f */
- result = "PERSISTENT_RESERVE_OUT";
- break;
- case EXTENDED_COPY: /* 0x83 */
- result = "EXTENDED_COPY";
- break;
- case RECEIVE_COPY_RESULTS: /* 0x84 */
- result = "RECEIVE_COPY_RESULTS";
- break;
- case REPORT_DEVICE_ID: /* 0xa3 */
- result = "REPORT_DEVICE_ID";
- break;
- case REPORT_LUNS: /* 0xa0 */
- result = "REPORT_LUNS";
- break;
- case SET_DEVICE_ID: /* 0xa4 */
- result = "SET_DEVICE_ID";
- break;
- case MOVE_MEDIUM: /* 0xa5 */
- result = "MOVE_MEDIUM";
- break;
- case MOVE_MEDIUM_ATTACHED: /* 0xa7 */
- result = "MOVE_MEDIUM_ATTACHED";
- break;
- case WRITE_VERIFY_12: /* 0xae */
- result = "WRITE_VERIFY_12";
- break;
- case SEARCH_HIGH_12: /* 0xb0 */
- result = "SEARCH_HIGH_12";
- break;
- case SEARCH_EQUAL_12: /* 0xb1 */
- result = "SEARCH_EQUAL_12";
- break;
- case SEARCH_LOW_12: /* 0xb2 */
- result = "SEARCH_LOW_12";
- break;
- case READ_ELEMENT_STATUS_ATTACHED: /* 0xb4 */
- result = "READ_ELEMENT_STATUS_ATTACHED";
- break;
- case READ_ELEMENT_STATUS: /* 0xb8 */
- result = "READ_ELEMENT_STATUS";
- break;
- case SEND_VOLUME_TAG: /* 0xb6 */
- result = "SEND_VOLUME_TAG";
- break;
- case WRITE_LONG_2: /* 0xea */
- result = "WRITE_LONG_2";
- break;
- } /* switch */
-
- PRINT_BUFF_CAT( "CDB-OP: %s ", result );
-}
-
-static void
-print_init_scsi_cmnd( char * buffer )
-{
- struct iscsi_init_scsi_cmnd *cmd = (struct iscsi_init_scsi_cmnd
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- PRINT_BUFF_CAT("EDTL: %u ", be32_to_cpu(cmd->xfer_len));
- print_cmdsn_expstatsn(cmd->cmd_sn ,cmd->exp_stat_sn);
- print_scsi_cdb_op(cmd->cdb[0]);
- PRINT_BUFF_CAT("CDB-DATA: 0x%.2x%.2x%.2x%.2x %.2x%.2x%.2x%.2x "
- "%.2x%.2x%.2x%.2x %.2x%.2x%.2x%.2x ",
- cmd->cdb[0], cmd->cdb[1], cmd->cdb[2], cmd->cdb[3],
- cmd->cdb[4], cmd->cdb[5], cmd->cdb[6], cmd->cdb[7],
- cmd->cdb[8], cmd->cdb[9], cmd->cdb[10], cmd->cdb[11],
- cmd->cdb[12], cmd->cdb[13], cmd->cdb[14], cmd->cdb[15]);
-}
-
-
-static void
-print_targ_scsi_rsp( char * buffer )
-{
- struct iscsi_targ_scsi_rsp *cmd = (struct iscsi_targ_scsi_rsp
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_response(cmd->response);
- print_status(cmd->status);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_exp_data_sn(cmd->exp_data_sn);
- if( cmd->bidi_resid != 0 )
- PRINT_BUFF_CAT("BidirResidualCount: %u ",
be32_to_cpu(cmd->bidi_resid));
- print_residual(cmd->resid);
-}
-
-
-static void
-print_init_text_cmnd( char * buffer )
-{
- struct iscsi_init_text_cmnd *cmd = (struct iscsi_init_text_cmnd
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_cmdsn_expstatsn(cmd->cmd_sn ,cmd->exp_stat_sn);
- print_rsvd_u64(4, cmd->rsvd4);
- print_rsvd_u64(5, cmd->rsvd5);
-}
-
-
-static void
-print_targ_text_rsp( char * buffer )
-{
- struct iscsi_targ_text_rsp *cmd = (struct iscsi_targ_text_rsp
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_rsvd_u32(4, cmd->rsvd4);
- print_rsvd_u64(5, cmd->rsvd5);
-}
-
-
-static void
-print_init_login_cmnd( char * buffer )
-{
- struct iscsi_init_login_cmnd *cmd = (struct iscsi_init_login_cmnd
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_version("Max", cmd->version_max);
- print_version("Min", cmd->version_min);
- print_dsl(cmd->length);
- print_isid_tsih(cmd->isid, cmd->tsih);
- print_itt(cmd->init_task_tag);
- print_cid(cmd->cid);
- print_rsvd_u16(1, cmd->rsvd1);
- print_cmdsn_expstatsn(cmd->cmd_sn ,cmd->exp_stat_sn);
- print_rsvd_u64(2, cmd->rsvd2);
- print_rsvd_u64(3, cmd->rsvd3);
-}
-
-
-static void
-print_targ_login_rsp( char * buffer )
-{
- struct iscsi_targ_login_rsp *cmd = (struct iscsi_targ_login_rsp
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_version("Max", cmd->version_max);
- print_version("Active", cmd->version_active);
- print_dsl(cmd->length);
- print_isid_tsih(cmd->isid, cmd->tsih);
- print_itt(cmd->init_task_tag);
- print_rsvd_u32(1, cmd->rsvd1);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- if( cmd->status_class != 0 )
- PRINT_BUFF_CAT("StatusClass: 0x%.2x ", cmd->status_class);
- if( cmd->status_detail != 0 )
- PRINT_BUFF_CAT("StatusDetail: 0x%.2x ", cmd->status_detail);
- print_rsvd_u16(2, cmd->rsvd2);
- print_rsvd_u64(3, cmd->rsvd3);
-}
-
-
-static void
-print_init_logout_cmnd( char * buffer )
-{
- struct iscsi_init_logout_cmnd *cmd =
- (struct iscsi_init_logout_cmnd *)buffer;
-
- print_opcode(cmd->opcode);
- PRINT_BUFF_CAT("reasoncod: 0x%.2x ", cmd->flags);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_cid(cmd->cid);
- print_rsvd_u16(2, cmd->rsvd2);
- print_cmdsn_expstatsn(cmd->cmd_sn ,cmd->exp_stat_sn);
- print_rsvd_u64(4, cmd->rsvd4);
- print_rsvd_u64(5, cmd->rsvd5);
-}
-
-
-static void
-print_targ_logout_rsp( char * buffer )
-{
- struct iscsi_targ_logout_rsp *cmd = (struct iscsi_targ_logout_rsp
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_response(cmd->response);
- print_rsvd_u8(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_rsvd_u32(3, cmd->rsvd3);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_rsvd_u32(4, cmd->rsvd4);
- PRINT_BUFF_CAT("Time2Wait: 0x%.8x ", be16_to_cpu(cmd->time2wait));
- PRINT_BUFF_CAT("Tm2Retain: 0x%.8x ",
be16_to_cpu(cmd->time2retain));
- print_rsvd_u32(5, cmd->rsvd5);
-}
-
-
-static void
-print_init_scsi_data_out( char * buffer )
-{
- struct iscsi_init_scsi_data_out *cmd =
- (struct iscsi_init_scsi_data_out *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_rsvd_u32(3, cmd->rsvd3);
- print_expstatsn(cmd->exp_stat_sn);
- print_rsvd_u32(4, cmd->rsvd4);
- print_datasn(cmd->data_sn);
- print_offset(cmd->offset,cmd->length);
- print_rsvd_u32(5, cmd->rsvd5);
-}
-
-
-static void
-print_targ_scsi_data_in( char * buffer )
-{
- struct iscsi_targ_scsi_data_in *cmd =
- (struct iscsi_targ_scsi_data_in *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u8(1, cmd->rsvd1);
- print_status(cmd->status);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_datasn(cmd->data_sn);
- print_offset(cmd->offset,cmd->length);
- print_residual(cmd->resid);
-}
-
-
-static void
-print_targ_rjt( char * buffer )
-{
- struct iscsi_targ_rjt *cmd = (struct iscsi_targ_rjt *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- if( cmd->reason != 0 )
- PRINT_BUFF_CAT("Reason: 0x%.2x ", cmd->reason);
- print_rsvd_u8(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_rsvd_u32(4, cmd->rsvd4);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_datasn(cmd->data_sn);
- print_rsvd_u64(4, cmd->rsvd4);
- print_rsvd_u64(5, cmd->rsvd5);
-}
-
-
-static void
-print_init_nopout( char * buffer )
-{
- struct iscsi_init_nopout *cmd = (struct iscsi_init_nopout *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_cmdsn_expstatsn(cmd->cmd_sn ,cmd->exp_stat_sn);
- print_rsvd_u64(2, cmd->rsvd2);
- print_rsvd_u64(3, cmd->rsvd3);
-}
-
-
-static void
-print_targ_nopin( char * buffer )
-{
- struct iscsi_targ_nopin *cmd = (struct iscsi_targ_nopin *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_statsn_exp_max(cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_rsvd_u32(2, cmd->rsvd2);
- print_rsvd_u64(3, cmd->rsvd3);
-}
-
-
-static void
-print_targ_r2t( char * buffer )
-{
- struct iscsi_targ_r2t *cmd = (struct iscsi_targ_r2t *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- PRINT_BUFF_CAT("R2TSN: %u ", be32_to_cpu(cmd->r2t_sn));
- print_offset(cmd->offset,cmd->xfer_len);
-}
-
-
-static void
-print_targ_async_msg( char * buffer )
-{
- struct iscsi_targ_async_msg *cmd = (struct iscsi_targ_async_msg
*)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(2, cmd->rsvd2);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_rsvd_u32(3, cmd->rsvd3);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- PRINT_BUFF_CAT("AsyncEvnt: %u ", cmd->async_event);
- PRINT_BUFF_CAT("AsyncVCod: %u ", cmd->async_vcode);
- if( cmd->parameter1 != 0 )
- PRINT_BUFF_CAT(" Param1: %u ", cmd->parameter1);
- if( cmd->parameter2 != 0 )
- PRINT_BUFF_CAT(" Param2: %u ", cmd->parameter2);
- if( cmd->parameter3 != 0 )
- PRINT_BUFF_CAT(" Param3: %u ", cmd->parameter3);
- print_rsvd_u32(5, cmd->rsvd5);
-}
-
-
-static void
-print_init_task_mgt_command( char * buffer )
-{
- struct iscsi_init_task_mgt_command *cmd =
- (struct iscsi_init_task_mgt_command *)buffer;
-
- print_opcode(cmd->opcode);
- PRINT_BUFF_CAT("Function: 0x%.2x ", cmd->function);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_rtt(cmd->ref_task_tag);
- print_cmdsn_expstatsn(cmd->cmd_sn, cmd->exp_stat_sn);
- if( cmd->ref_cmd_sn != 0 )
- PRINT_BUFF_CAT("RefCmdSN: %u ", be32_to_cpu(cmd->ref_cmd_sn));
- print_exp_data_sn(cmd->exp_data_sn);
- print_rsvd_u64(4, cmd->rsvd4);
-}
-
-
-static void
-print_targ_task_mgt_response( char * buffer )
-{
- struct iscsi_targ_task_mgt_response *cmd =
- (struct iscsi_targ_task_mgt_response *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_response(cmd->response);
- print_rsvd_u8(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_rsvd_u32(2, cmd->rsvd2);
- print_statsn_exp_max( cmd->stat_sn , cmd->exp_cmd_sn,
cmd->max_cmd_sn);
- print_rsvd_u32(4, cmd->rsvd4);
- print_rsvd_u64(5, cmd->rsvd5);
-}
-
-
-static void
-print_init_snack( char * buffer )
-{
- struct iscsi_init_snack *cmd = (struct iscsi_init_snack *)buffer;
-
- print_opcode(cmd->opcode);
- print_flags(cmd->flags);
- print_rsvd_u16(1, cmd->rsvd1);
- print_dsl(cmd->length);
- print_lun(cmd->lun);
- print_itt(cmd->init_task_tag);
- print_ttt(cmd->target_xfer_tag);
- print_rsvd_u32(2, cmd->rsvd2);
- print_expstatsn(cmd->exp_stat_sn);
- print_rsvd_u64(3, cmd->rsvd3);
- print_begrun(cmd->begrun);
- print_runlen(cmd->runlen);
-}
-
-
-/*---------------------------------------------------------------------
- */
-/*!
- @brief Prints out an iSCSI PDU - its BHS and, if supplied, the data
segment
-*/
-/*
--------------------------------------------------------------------- */
-void
-iser_pdu_print(char *prefix,
- void *p_id,
- char *p_bhs,
- struct iser_data_buf_t *p_data)
-{
- __u32 opcode;
- int max_data_print_len = iser_trace_get_data_max_print_len();
-
- PRINT_BUFF_CAT( prefix );
- if ( (char *)p_id != NULL )
- PRINT_BUFF_CAT( "(0x%p): ",(char *)p_id );
-
- opcode = p_bhs[0] & ISCSI_OPCODE_MASK;
-
- switch (opcode) {
- case ISCSI_OP_LOGIN_REQ:
- {
- PRINT_BUFF_CAT( "LOGIN REQUEST" );
- print_init_login_cmnd( p_bhs );
- break;
- }
-
- case ISCSI_OP_TEXT_REQ:
- {
- PRINT_BUFF_CAT( "TEXT REQUEST" );
- print_init_text_cmnd( p_bhs );
- break;
- }
-
- case ISCSI_OP_SCSI_CMD:
- {
- PRINT_BUFF_CAT( "SCSI COMMAND" );
- print_init_scsi_cmnd( p_bhs );
- break;
- }
-
- case ISCSI_OP_DATA_OUT:
- {
- PRINT_BUFF_CAT( "DATA_OUT" );
- print_init_scsi_data_out( p_bhs );
- break;
- }
-
- case ISCSI_OP_TASK_MGT_REQ:
- {
- PRINT_BUFF_CAT("TAST MNGT CMD" );
- print_init_task_mgt_command( p_bhs );
- break;
- }
-
- case ISCSI_OP_LOGOUT_REQ:
- {
- PRINT_BUFF_CAT( "LOGOUT REQUEST" );
- print_init_logout_cmnd( p_bhs );
- break;
- }
-
- case ISCSI_OP_NOP_OUT:
- {
- PRINT_BUFF_CAT( "NOP_OUT" );
- print_init_nopout( p_bhs );
- break;
- }
-
- /* SNACK Handling by Target - SAI */
- case ISCSI_OP_SNACK_REQ:
- {
- PRINT_BUFF_CAT( "SNACK Request" );
- print_init_snack( p_bhs );
- break;
- }
-
- case ISCSI_OP_NOP_IN:
- {
- PRINT_BUFF_CAT( "NOP_IN" );
- print_targ_nopin( p_bhs );
- break;
- }
-
- case ISCSI_OP_SCSI_RSP:
- {
- PRINT_BUFF_CAT( "SCSI RESPONSE" );
- print_targ_scsi_rsp( p_bhs );
- break;
- }
-
- case ISCSI_OP_TASK_MGT_RSP:
- {
- PRINT_BUFF_CAT( "MGMT RESPONSE" );
- print_targ_task_mgt_response( p_bhs );
- break;
- }
-
- case ISCSI_OP_LOGIN_RSP:
- {
- PRINT_BUFF_CAT( "LOGIN RESPONSE" );
- print_targ_login_rsp( p_bhs );
- break;
- }
-
- case ISCSI_OP_TEXT_RSP:
- {
- PRINT_BUFF_CAT( "TEXT RESPONSE" );
- print_targ_text_rsp( p_bhs );
- break;
- }
-
- case ISCSI_OP_DATA_IN:
- {
- PRINT_BUFF_CAT( "DATA_IN" );
- print_targ_scsi_data_in( p_bhs );
- break;
- }
-
- case ISCSI_OP_LOGOUT_RSP:
- {
- PRINT_BUFF_CAT( "LOGOUT RESPONSE" );
- print_targ_logout_rsp( p_bhs );
- break;
- }
-
- case ISCSI_OP_R2T:
- {
- PRINT_BUFF_CAT( "R2T" );
- print_targ_r2t( p_bhs );
- break;
- }
-
- case ISCSI_OP_ASYNC:
- {
- PRINT_BUFF_CAT( "ASYNC MSG" );
- print_targ_async_msg( p_bhs );
- break;
- }
-
- case ISCSI_OP_REJECT:
- {
- PRINT_BUFF_CAT( "TARGET REJECT");
- print_targ_rjt( p_bhs );
- break;
- }
-
- default:
- {
- PRINT_BUFF_CAT("UNKNOWN OPCODE");
- break;
- }
- }
- if (p_data != NULL) {
- PRINT_BUFF_CAT("DATA: 0x%p (sz: %d, ptr: 0x%p, type: %s)",
- p_data, p_data->size, p_data->p_buf,
- iser_data_buf_get_type_name(p_data));
- }
- PRINT_BUFF_OUT();
-
- /* Print data if available */
- if (max_data_print_len > 0 && p_data != NULL && p_data->size > 0) {
- char *p_chunk_buf = NULL;
- unsigned int chunk_len = 0;
- unsigned int len_to_print = 0;
- unsigned int chunk_printed_len = 0;
- unsigned int total_printed_len = 0;
- unsigned int cur_chunk = 0;
- int all_printed = 0;
-
- do {
- if (p_data->type == ISER_BUF_TYPE_SINGLE) {
- p_chunk_buf = p_data->p_buf + total_printed_len;
- len_to_print = min(p_data->size - total_printed_len,
- max_data_print_len -
total_printed_len);
- len_to_print = min(len_to_print,
- (unsigned int)
- ISER_PDU_PRINT_MAX_DATA_BLOCK_LEN);
-
- PRINT_BUFF_CAT("DATA(0x%p,SINGLE,%d+%d/%d): ",
- p_data, total_printed_len, len_to_print,
- p_data->size);
-
- /* Update counters */
- total_printed_len += len_to_print;
- if (total_printed_len == max_data_print_len ||
- total_printed_len == p_data->size) {
- all_printed = 1;
- }
- }
- else {
- switch (p_data->type) {
- case ISER_BUF_TYPE_IOVEC_VIRT: {
- p_chunk_buf =
-
iser_iovec_virt_entry_addr(p_data->p_buf,cur_chunk)
- + chunk_printed_len;
- chunk_len = iser_iovec_entry_len(p_data->p_buf,
- cur_chunk);
-
- len_to_print = min(chunk_len -
chunk_printed_len,
- max_data_print_len -
- total_printed_len);
- len_to_print = min(len_to_print,
- (unsigned int)
-
ISER_PDU_PRINT_MAX_DATA_BLOCK_LEN);
-
-
PRINT_BUFF_CAT("DATA(0x%p,IOVECVIRT[%d],%d+%d/%d): ",
- p_data, cur_chunk,
chunk_printed_len,
- len_to_print, chunk_len);
- break;
- }
- case ISER_BUF_TYPE_IOVEC_PHYS: {
- p_chunk_buf =
-
iser_iovec_phys_entry_to_virt(p_data->p_buf,
- cur_chunk) +
- chunk_printed_len;
- chunk_len = iser_iovec_entry_len(p_data->p_buf,
- cur_chunk);
-
- len_to_print = min(chunk_len -
chunk_printed_len,
- max_data_print_len -
- total_printed_len);
- len_to_print = min(len_to_print,
- (unsigned int)
-
ISER_PDU_PRINT_MAX_DATA_BLOCK_LEN);
-
-
PRINT_BUFF_CAT("DATA(0x%p,IOVECPHYS[%d],%d+%d/%d): ",
- p_data, cur_chunk,
- chunk_printed_len,
- len_to_print, chunk_len);
- break;
- }
- case ISER_BUF_TYPE_SCATTERLIST: {
- p_chunk_buf =
-
iser_scatterlist_entry_to_virt(p_data->p_buf,
- cur_chunk) +
- chunk_printed_len;
- chunk_len =
-
iser_scatterlist_entry_len(p_data->p_buf,cur_chunk);
-
- len_to_print = min(chunk_len -
chunk_printed_len,
- max_data_print_len -
- total_printed_len);
- len_to_print = min(len_to_print,
- (unsigned int)
-
ISER_PDU_PRINT_MAX_DATA_BLOCK_LEN);
-
-
PRINT_BUFF_CAT("DATA(0x%p,SCATTERLIST[%d],%d+%d/%d): ",
- p_data, cur_chunk,
chunk_printed_len,
- len_to_print, chunk_len);
- break;
- }
- default:
- all_printed = 1;
- break;
- } /* switch */
-
- /* Update counters */
- total_printed_len += len_to_print;
- if (total_printed_len == max_data_print_len) {
- all_printed = 1;
- }
- else {
- chunk_printed_len += len_to_print;
- if (chunk_printed_len == chunk_len) {
- chunk_printed_len = 0;
- cur_chunk++;
- if (cur_chunk == p_data->size) {
- all_printed = 1;
- }
- }
- }
- }
-
- if (p_chunk_buf != NULL && len_to_print > 0) {
- int i;
-
- for (i=0; i<len_to_print; i++) {
- PRINT_BUFF_CAT("%02X", p_chunk_buf[i]);
- if (i % 4 == 3) {
- PRINT_BUFF_CAT(" ");
- }
- }
- PRINT_BUFF_CAT("\n");
- PRINT_BUFF_OUT();
-
- if (opcode == ISCSI_OP_LOGIN_REQ ||
- opcode == ISCSI_OP_TEXT_REQ ||
- opcode == ISCSI_OP_LOGIN_RSP ||
- opcode == ISCSI_OP_TEXT_RSP) {
- PRINT_BUFF_CAT("TEXT(0x%p): ", p_data);
- for (i=0; i<len_to_print; i++) {
- PRINT_BUFF_CAT( "%c",
- (p_chunk_buf[i] == '\0' ? ' ' :
- p_chunk_buf[i]));
- }
- PRINT_BUFF_CAT("\n");
- PRINT_BUFF_OUT();
- }
- }
- else {
- all_printed = 1;
- }
- } while (!all_printed);
- }
-} /* iser_pdu_print */
-
-/*
- Copyright (C) 2001-2003 InterOperability Lab (IOL)
- University of New Hampshier (UNH)
- Durham, NH 03824
-
- This program is free software; you can redistribute it and/or
modify
- it under the terms of the GNU General Public License as published
by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307,
- USA.
-
- The name of IOL and/or UNH may not be used to endorse or promote
products
- derived from this software without specific prior written
permission.
-*/
-
Index: iser_socket.c
===================================================================
--- iser_socket.c (revision 0)
+++ iser_socket.c (revision 0)
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2005 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/tcp.h>
+#include <iser_api.h>
+
+#include "iser.h"
+#include "iser_conn.h"
+#include "iser_initiator.h"
+#include "iser_socket.h"
+
+#define PF_ISER AF_ISER
+
+static int iser_sock_create(struct socket *, int);
+static int iser_sock_release(struct socket *);
+static int iser_sock_connect(struct socket *, struct sockaddr *, int,
int);
+static int iser_sock_shutdown(struct socket *,int);
+static int iser_sock_getsockopt(struct socket *,int,int,char *,int *);
+static unsigned int iser_sock_poll(struct file *,struct socket *,
+ struct poll_table_struct *);
+
+struct iser_sock {
+ struct sock sock;
+ wait_queue_head_t conn_sleep_q;
+ struct iser_connection iser_conn;
+};
+
+static struct net_proto_family iser_proto_family = {
+ family: PF_ISER,
+ create: iser_sock_create,
+ authentication: 0,
+ encryption: 0,
+ encrypt_net: 0,
+};
+
+static struct proto_ops iser_proto_ops = {
+ family: AF_ISER,
+ owner: THIS_MODULE,
+
+ connect: iser_sock_connect,
+ release: iser_sock_release,
+ shutdown: iser_sock_shutdown,
+
+ bind: sock_no_bind,
+ poll: iser_sock_poll,
+ socketpair: sock_no_socketpair,
+ accept: sock_no_accept,
+ getname: sock_no_getname,
+ ioctl: sock_no_ioctl,
+ listen: sock_no_listen,
+ setsockopt: sock_setsockopt,
+ getsockopt: iser_sock_getsockopt,
+ sendmsg: sock_no_sendmsg,
+ recvmsg: sock_no_recvmsg,
+ mmap: sock_no_mmap,
+ sendpage: sock_no_sendpage,
+};
+
+static struct proto iser_sock_proto = {
+ name: "ib_iser",
+ owner: THIS_MODULE,
+ obj_size: sizeof(struct iser_sock),
+};
+
+struct iser_connection *iser_conn_from_sock(struct socket *sock)
+{
+ struct iser_sock *iser_sk = (struct iser_sock *)sock->sk;
+ return &iser_sk->iser_conn;
+} /* iser_conn_from_sock */
+
+struct socket *iser_conn_to_sock(struct iser_connection *p_iser_conn)
+{
+ struct iser_sock *iser_sk;
+ iser_sk = container_of(p_iser_conn,struct iser_sock,iser_conn);
+ return iser_sk->sock.sk_socket;
+} /* iser_conn_to_sock */
+
+int iser_register_sockets(void)
+{
+ int error = 0;
+
+ error = proto_register(&iser_sock_proto, 1);
+ if (error < 0) {
+ printk(KERN_ERR "proto_register failed (%d)\n", error);
+ goto register_iser_socket_exit;
+ }
+ error = sock_register(&iser_proto_family);
+ if (error < 0) {
+ printk(KERN_ERR "sock_register failed (%d)\n", error);
+ }
+
+ register_iser_socket_exit:
+ return error;
+} /* iser_register_sockets */
+
+void iser_unreg_sockets(void)
+{
+ sock_unregister(PF_ISER);
+ proto_unregister(&iser_sock_proto);
+} /* iser_unreg_sockets */
+
+static int iser_sock_create(struct socket *sock, int protocol)
+{
+ struct iser_sock *iser_sk = NULL;
+
+ if (sock->type != SOCK_STREAM)
+ return -ESOCKTNOSUPPORT;
+
+ iser_sk = (struct iser_sock *)sk_alloc(PF_INET, GFP_KERNEL,
+ &iser_sock_proto, 1);
+ if (iser_sk == NULL)
+ return -ENOBUFS;
+
+ sock_init_data(sock, &iser_sk->sock);
+ iser_sk->sock.sk_destruct = NULL;
+ iser_sk->sock.sk_family = PF_ISER;
+ iser_sk->sock.sk_sndbuf = 64*1024;
+
+ init_waitqueue_head(&iser_sk->conn_sleep_q);
+ iser_conn_init(&iser_sk->iser_conn);
+
+ sock->ops = &iser_proto_ops;
+ sock->state = SS_UNCONNECTED;
+ sock_graft(&iser_sk->sock, sock);
+
+ return 0;
+} /* iser_sock_create */
+
+int iser_sock_connect(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags)
+{
+ struct sockaddr_in *dst_addr = (struct sockaddr_in *)uservaddr;
+ struct iser_sock *iser_sk = (struct iser_sock *)sock->sk;
+ struct iser_connection *p_iser_conn = &iser_sk->iser_conn;
+ int iser_err = 0;
+
+ dst_addr->sin_port = htons(dst_addr->sin_port);
+ printk("%s: ip = %d.%d.%d.%d, port = %d\n", __func__,
+ NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port);
+
+ iser_err = iser_conn_establish(p_iser_conn, dst_addr, NULL);
+ if (iser_err) {
+ printk(KERN_ERR "conn_establish failed: %d\n",iser_err);
+ goto iser_connect_exit;
+ }
+
+ /* Sleep until the connection is established or rejected */
+ wait_event_interruptible(iser_sk->conn_sleep_q,
+ atomic_read(&p_iser_conn->state) != ISER_CONN_PENDING);
+
+ if (atomic_read(&p_iser_conn->state) != ISER_CONN_UP) {
+ iser_err = -EIO;
+ }
+
+ iser_connect_exit:
+ return iser_err;
+} /* iser_sock_connect */
+
+int iser_conn_establish_notify(struct iser_connection *p_iser_conn)
+{
+ struct iser_sock *iser_sk;
+
+ iser_sk = container_of(p_iser_conn,struct iser_sock,iser_conn);
+ wake_up_interruptible(&iser_sk->conn_sleep_q);
+
+ return 0;
+} /* iser_conn_establish_notify */
+
+static inline void iser_sock_free(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ sock->sk = NULL;
+ sock_orphan(sk);
+ sk_free(sk);
+}
+
+int iser_sock_release(struct socket *sock)
+{
+ struct iser_sock *iser_sock = (struct iser_sock *)sock->sk;
+ struct iser_connection *p_iser_conn = &iser_sock->iser_conn;
+ int iser_err = 0;
+
+ if (atomic_read(&p_iser_conn->state) == ISER_CONN_DOWN) {
+ iser_sock_free(sock);
+ } else {
+ iser_err = -EPERM;
+ }
+ return iser_err;
+} /* iser_sock_release */
+
+int iser_sock_shutdown(struct socket *sock, int how)
+{
+ return 0;
+} /* iser_sock_shutdown */
+
+static int iser_sock_getsockopt(struct socket *sock, int level, int
optname,
+ char *optval, int *optlen)
+{
+ return 0;
+} /* iser_sock_getsockopt */
+
+static unsigned int iser_sock_poll(struct file *file, struct socket
*sock,
+ struct poll_table_struct *wait)
+{
+ return POLLOUT;
+} /* iser_sock_poll */
Index: iser_socket.h
===================================================================
--- iser_socket.h (revision 0)
+++ iser_socket.h (revision 0)
@@ -0,0 +1,56 @@
+
+/*
+ * Copyright (c) 2004, 2005 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.
+ *
+ */
+
+#ifndef __ISER_SOCKETS_H__
+#define __ISER_SOCKETS_H__
+
+#include <linux/net.h>
+#include "iser.h"
+
+enum iscsi_iser_conn_status {
+ ISER_SOCK_INVALID,
+ ISER_SOCK_PENDING,
+ ISER_SOCK_CONNECTED,
+ ISER_SOCK_DISCONNECTING,
+ ISER_SOCK_DISCONNECTED
+};
+
+int iser_register_sockets(void);
+void iser_unreg_sockets(void);
+
+struct iser_connection *iser_conn_from_sock(struct socket *sock);
+struct socket *iser_conn_to_sock(struct iser_connection *p_iser_conn);
+int iser_conn_establish_notify(struct iser_connection *p_iser_conn);
+
+#endif /* __ISER_SOCKETS_H__ */
Index: iser_conn.c
===================================================================
--- iser_conn.c (revision 3404)
+++ iser_conn.c (working copy)
@@ -31,9 +31,16 @@
*
*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+
#include "iser.h"
#include "iser_initiator.h"
#include "iser_conn.h"
+#include "iser_socket.h"
#include "iser_task.h"
#include "iser_dto.h"
#include "iser_kdapl.h"
@@ -67,22 +74,12 @@
} /* iser_conn_get_state_name */
/**
- * iser_conn_alloc - Allocates and initializes a conn descriptor
+ * iser_conn_init - initializes connection structure
*
- * returns iSER conn descriptor, or NULL on failure
+ * returns conn name string
*/
-struct iser_connection *iser_conn_alloc()
+void iser_conn_init(struct iser_connection *p_iser_conn)
{
- struct iser_connection *p_iser_conn;
-
- /* Allocate iSER conn structure */
- p_iser_conn = kmem_cache_alloc(ig.conn_mem_cache,
- GFP_KERNEL | __GFP_NOFAIL);
- if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX "Failed to alloc iSER conn
descriptor.\n");
- return NULL;
- }
-
memset(p_iser_conn, 0, sizeof(struct iser_connection));
ITRACE(ISER_TRACE_CONN, "memset at 0x%p to 0x%lX\n",
p_iser_conn,
((long)p_iser_conn) + sizeof(struct iser_connection));
@@ -94,7 +91,6 @@
INIT_LIST_HEAD(&p_iser_conn->task_list);
INIT_LIST_HEAD(&p_iser_conn->hash_list);
INIT_LIST_HEAD(&p_iser_conn->adaptor_list);
- INIT_LIST_HEAD(&p_iser_conn->entity_list);
atomic_set(&p_iser_conn->post_recv_buf_count, 0);
atomic_set(&p_iser_conn->post_send_buf_count, 0);
@@ -119,13 +115,435 @@
p_iser_conn->param.DataPDUInOrder = defaultDataPDUInOrder;
p_iser_conn->param.DataSequenceInOrder =
defaultDataSequenceInOrder;
p_iser_conn->param.ErrorRecoveryLevel =
defaultErrorRecoveryLevel;
-
init_waitqueue_head(&p_iser_conn->disconnect_wait_q);
+} /* iser_conn_init */
+/**
+ * iser_adaptor_init - Initializes iSER adaptor structure.
+ *
+ *
+ * Creates adaptor-scope objects (Interface Adaptor, Protection Zone,
+ * Public Service Points).
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_adaptor_init(struct iser_adaptor *p_iser_adaptor,
+ char *name)
+{
+ if (p_iser_adaptor == NULL)
+ return -1;
+
+ memset(p_iser_adaptor, 0, sizeof(struct iser_adaptor));
+ ITRACE(ISER_TRACE_CONN, "memset at 0x%p to 0x%lX\n",
+ p_iser_adaptor,
+ ((long)p_iser_adaptor) + sizeof(struct iser_adaptor));
+
+ /* Initialize waiting queue for the event handler thread */
+ init_waitqueue_head(&p_iser_adaptor->dat_events_wait_q);
+ init_waitqueue_head(&p_iser_adaptor->connect_wait_q);
+
+ /* Initialize list of conns */
+ spin_lock_init(&p_iser_adaptor->conn_lock);
+ INIT_LIST_HEAD(&p_iser_adaptor->conn_list);
+
+ /* Create IA, PZ, EVD */
+ if (iser_create_ia_pz_evd(p_iser_adaptor) != 0) {
+ return -1;
+ }
+
+ /* Allocate pool of pre-registered iSER headers */
+ p_iser_adaptor->header_pool =
+ iser_small_bpool_create(p_iser_adaptor, "headers",
+ ISER_TOTAL_HEADERS_LEN, 0, 1);
+ if (p_iser_adaptor->header_pool == NULL) {
+ iser_adaptor_release(p_iser_adaptor);
+ return -1;
+ }
+
+ /* Initizlize the pre-registered buffers cache */
+ iser_reg_all_mem(p_iser_adaptor);
+
+ /* Start the event thread */
+ p_iser_adaptor->terminate_thread = 0;
+ init_MUTEX_LOCKED(&p_iser_adaptor->startstop_sem);
+ p_iser_adaptor->event_thrd_pid =
+ kernel_thread(iser_event_handler_thread,
+ p_iser_adaptor,
+ CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND);
+
+ if (p_iser_adaptor->event_thrd_pid <= 0) {
+ printk(KERN_ERR PFX "Failed to start event kernel
thread\n");
+ iser_adaptor_release(p_iser_adaptor);
+ return -1;
+ }
+ printk("p1\n");
+ /* wait for the event thread to start */
+ down(&p_iser_adaptor->startstop_sem);
+
+ return 0;
+} /* iser_adaptor_init */
+
+/**
+ * iser_adaptor_release - Releases all adaptor-related res.
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_adaptor_release(struct iser_adaptor *p_iser_adaptor)
+{
+ struct iser_connection *p_iser_conn;
+
+ /* Free all conns and associated objects,
+ must be done before freeing adaptor objects */
+ while (!list_empty(&p_iser_adaptor->conn_list)) {
+ p_iser_conn = list_entry(p_iser_adaptor->conn_list.next,
+ struct iser_connection,
adaptor_list);
+ /* Connection should be shut down before releasing res
*/
+ iser_conn_sync_terminate(p_iser_conn);
+ iser_conn_release(p_iser_conn);
+ }
+ /* Release buffer pool and unregister its memory */
+ if (p_iser_adaptor->header_pool != NULL) {
+ iser_bpool_destroy(p_iser_adaptor->header_pool);
+ p_iser_adaptor->header_pool = NULL;
+ }
+
+ if (iser_unreg_all_mem(p_iser_adaptor) != 0) {
+ ITRACE(ISER_TRACE_ERRORS,
+ "iser_unreg_all_mem failed\n");
+ }
+
+ /* Free adaptor-related objects */
+ if (iser_free_ia_pz_evd(p_iser_adaptor) != 0) {
+ return -1;
+ }
+
+ /* kill event thread (if exists) */
+ if (p_iser_adaptor->event_thrd_pid > 0) {
+ ITRACE(ISER_TRACE_EVENT_THREAD,
+ "start terminating event thread\n");
+ lock_kernel();
+ init_MUTEX_LOCKED(&p_iser_adaptor->startstop_sem);
+ mb();
+ p_iser_adaptor->terminate_thread = 1;
+ mb();
+ kill_proc(p_iser_adaptor->event_thrd_pid, SIGKILL, 1);
+ ITRACE(ISER_TRACE_EVENT_THREAD,
+ "waiting for event thread to terminate down\n");
+ down(&p_iser_adaptor->startstop_sem);
+ unlock_kernel();
+ ITRACE(ISER_TRACE_EVENT_THREAD, "event thread
terminated\n");
+ }
+
+ return 0;
+} /* iser_adaptor_release */
+
+/**
+ * iser_adaptor_add_conn - Adds a conn to adaptor
+ */
+void iser_adaptor_add_conn(struct iser_adaptor *p_iser_adaptor,
+ struct iser_connection *p_iser_conn)
+{
+ p_iser_conn->p_adaptor = p_iser_adaptor;
+ spin_lock(&p_iser_adaptor->conn_lock);
+ list_add(&p_iser_conn->adaptor_list,
&p_iser_adaptor->conn_list);
+ spin_unlock(&p_iser_adaptor->conn_lock);
+
+} /* iser_adaptor_add_conn */
+
+/**
+ * iser_adaptor_find_conn - Adds a conn to adaptor
+ *
+ * returns 0 on success, -1 on failure
+ */
+struct iser_connection *iser_adaptor_find_conn(struct iser_adaptor
+ *p_iser_adaptor,
+ void *ep_handle)
+{
+
+ struct iser_connection *p_iser_conn = NULL;
+ struct list_head *p_list;
+
+ spin_lock(&p_iser_adaptor->conn_lock);
+ p_list = p_iser_adaptor->conn_list.next;
+ while (p_list != &p_iser_adaptor->conn_list) {
+ p_iser_conn = list_entry(p_list, struct iser_connection,
+ adaptor_list);
+ if (((void *)p_iser_conn->ep_handle) == ep_handle)
+ break;
+ p_iser_conn = NULL;
+ p_list = p_list->next;
+ }
+ spin_unlock(&p_iser_adaptor->conn_lock);
+
return p_iser_conn;
-} /* iser_conn_alloc */
+} /* iser_adaptor_find_conn */
/**
+ * iser_adaptor_remove_conn - Removes a conn from adaptor
+ */
+void iser_adaptor_remove_conn(struct iser_connection *p_iser_conn)
+{
+ struct iser_adaptor *p_iser_adaptor;
+
+ if (!list_empty(&p_iser_conn->adaptor_list)) {
+ p_iser_adaptor = p_iser_conn->p_adaptor;
+ if (p_iser_adaptor == NULL) {
+ IPANIC("NULL adaptor in conn: 0x%p\n",
p_iser_conn);
+ }
+ spin_lock(&p_iser_adaptor->conn_lock);
+ list_del(&p_iser_conn->adaptor_list);
+ spin_unlock(&p_iser_adaptor->conn_lock);
+ }
+
+} /* iser_adaptor_remove_conn */
+
+/**
+ * iser_conn_establish - establish iser connection
+ */
+int iser_conn_establish(struct iser_connection *p_iser_conn,
+ struct sockaddr_in *dst_addr,
+ struct sockaddr_in *src_addr)
+{
+ struct iser_adaptor *p_adaptor;
+ char bufpool_name[128];
+ int ep_create_ret;
+ int iser_err = 0;
+
+ p_adaptor = &ig.adaptor[0];
+ iser_adaptor_add_conn(p_adaptor, p_iser_conn);
+
+ /* Allocate post-receive buffers for the login phase */
+ sprintf(bufpool_name, "login-pdu-data");
+ p_iser_conn->post_recv_pool =
+ iser_large_bpool_create(p_iser_conn->p_adaptor,
bufpool_name,
+ ISER_LOGIN_PHASE_PDU_DATA_LEN, 4,
0);
+ if (p_iser_conn->post_recv_pool == NULL) {
+ printk(KERN_ERR PFX "login pool = NULL\n");
+ iser_err = -ENOMEM;
+ goto iser_conn_establish_failure;
+ }
+
+ /* During the login phase data for sent PDUs is drawn from */
+ /* the same buffer pool as recv */
+ p_iser_conn->send_data_pool = p_iser_conn->post_recv_pool;
+
+ ep_create_ret = iser_create_ep(p_iser_conn);
+ if (ep_create_ret != 0) {
+ iser_err = -EIO;
+ goto iser_conn_establish_failure;
+ }
+
+ if (dst_addr != NULL) {
+ sprintf(p_iser_conn->name, "%d.%d.%d.%d",
+ NIPQUAD(dst_addr->sin_addr));
+ } else {
+ sprintf(p_iser_conn->name, "Unknown");
+ }
+ ITRACE(ISER_TRACE_CONN, "Connecting to: %s, port 0x%x\n",
+ p_iser_conn->name, dst_addr->sin_port);
+
+ atomic_set(&p_iser_conn->state, ISER_CONN_PENDING);
+
+ if (iser_connect(p_iser_conn, dst_addr, src_addr) != 0) {
+ printk(KERN_ERR PFX "iser_connect failed\n");
+ goto iser_conn_establish_failure;
+ }
+ return 0;
+
+iser_conn_establish_failure:
+ if (p_iser_conn) {
+ atomic_set(&p_iser_conn->state, ISER_CONN_DOWN);
+ }
+ printk(KERN_ERR PFX "%s: failed\n", __FUNCTION__);
+ return iser_err;
+} /* iser_conn_establish */
+
+/**
+ * iser_conn_bind - iSER API.
+ * Binds iSER connection and previosuly connected socket
+ * Exchanges connection handles with iSCSI layer.
+ *
+ */
+int iser_conn_bind(void *iscsi_conn_h, /* IN */
+ struct socket *sock, /* IN */
+ void **iser_conn_h) /* OUT */
+{
+ struct iser_connection *p_iser_conn;
+
+ p_iser_conn = iser_conn_from_sock(sock);
+ p_iser_conn->iscsi_conn_h = iscsi_conn_h;
+ *iser_conn_h = p_iser_conn;
+ return 0;
+} /* iser_conn_bind */
+
+/**
+ * iser_conn_enable_rdma - iSER API. Implements
+ * Allocate_Connection_Resources and Enable_Datamover primitives.
+ *
+ */
+int iser_conn_enable_rdma(void *iser_conn_h,
+ struct iser_conn_res *conn_res)
+{
+ struct iser_connection *p_iser_conn = iser_conn_h;
+ int iser_err = 0;
+ int i;
+ char bufpool_name[ISER_BUF_POOL_NAME_SIZE];
+
+ if (p_iser_conn == NULL) {
+ printk(KERN_ERR PFX "NULL iser conn handle\n");
+ iser_err = -EINVAL;
+ goto conn_enable_rdma_exit;
+ }
+
+ p_iser_conn->max_outstand_cmds = conn_res->max_outstand_cmds;
+ p_iser_conn->alloc_post_recv_bufs_num = ISER_EP_AVG_POST_RECV +
2;
+ p_iser_conn->initial_post_recv_bufs_num = ISER_INITIAL_POST_RECV
+ 2;
+
+ ITRACE(ISER_TRACE_CONN,
+ "Max outst. cmds: %d, Allocate post recv bufs:"
+ "%d, Initially post: %d\n",
+ p_iser_conn->max_outstand_cmds,
+ p_iser_conn->alloc_post_recv_bufs_num,
+ p_iser_conn->initial_post_recv_bufs_num);
+
+ /* Allocate post-receive buffers for the full-featured phase */
+ snprintf(bufpool_name, ISER_BUF_POOL_NAME_SIZE,
"%s-%s-post-recv",
+ ig.provider_name, p_iser_conn->name);
+
+ p_iser_conn->spare_post_recv_pool =
+ iser_small_bpool_create(p_iser_conn->p_adaptor,
+ bufpool_name,
+ 128,
+
p_iser_conn->alloc_post_recv_bufs_num,
+ 0);
+ if (p_iser_conn->spare_post_recv_pool == NULL) {
+ printk(KERN_ERR PFX "Failed to alloc the post receive
buffer "
+ "pool for conn = 0x%p, iscsi_h = 0x%p\n",
+ p_iser_conn, p_iser_conn->iscsi_conn_h);
+ iser_err = -EINVAL;
+ }
+
+ /* Allocate send-data buffers for the full-featured phase */
+ snprintf(bufpool_name, ISER_BUF_POOL_NAME_SIZE,
"%s-%s-send-data",
+ ig.provider_name, p_iser_conn->name);
+
+ /* ToDo: TargetMaxRecvDSL */
+ p_iser_conn->spare_send_data_pool =
+ iser_large_bpool_create(p_iser_conn->p_adaptor,
bufpool_name,
+ 8 * 1024,
+ ISER_MAX_NOP_OUT +
ISER_MAX_TASK_MGT_REQ,
+ 0);
+ if (p_iser_conn->spare_send_data_pool == NULL) {
+ printk(KERN_ERR PFX
+ "Failed to alloc the send data buffer pool "
+ "for conn = 0x%p, iscsi_h = 0x%p\n", p_iser_conn,
+ p_iser_conn->iscsi_conn_h);
+ iser_err = -EINVAL;
+ }
+
+ /* Check that there is no posted recv or send buffers left - */
+ /* they must be consumed during the login phase */
+ if (atomic_read(&p_iser_conn->post_recv_buf_count) != 0) {
+ IPANIC("Number of currently posted recv bufs
non-zero\n");
+ }
+ if (atomic_read(&p_iser_conn->post_send_buf_count) != 0) {
+ IPANIC("Number of currently posted send bufs
non-zero\n");
+ }
+ /* If a buffer pool has been allocd for loginphase, destroy it
*/
+ if (p_iser_conn->post_recv_pool != NULL) {
+ iser_bpool_destroy(p_iser_conn->post_recv_pool);
+ }
+
+ /* Switch to the main post-recv buffer pool */
+ p_iser_conn->post_recv_pool = p_iser_conn->spare_post_recv_pool;
+ p_iser_conn->spare_post_recv_pool = NULL;
+
+ /* Switch to the main send-data buffer pool */
+ p_iser_conn->send_data_pool = p_iser_conn->spare_send_data_pool;
+ p_iser_conn->spare_send_data_pool = NULL;
+
+ /* Initial Post-Receive buffers */
+ for (i = 0; i < p_iser_conn->initial_post_recv_bufs_num; i++) {
+ if (iser_post_receive_control(p_iser_conn) != 0) {
+ printk(KERN_ERR PFX "Failed to post recv
buffers\n");
+ iser_err = -ENOMEM;
+ goto conn_enable_rdma_exit;
+ }
+ }
+ ITRACE(ISER_TRACE_CONN, "Allocated %d post recv bufs\n", i);
+
+ conn_enable_rdma_exit:
+ return iser_err;
+} /* iser_conn_enable_rdma */
+
+/**
+ * iser_conn_term - iSER API. Implements
+ * Connection_Terminate primitive.
+ *
+ * Starts conn teardown process. Waits until all previously posted
+ * buffers get flushed. Deallocs all conn res.
+ */
+int iser_conn_term(void *iser_conn_h)
+{
+ struct iser_connection *p_iser_conn = iser_conn_h;
+ struct iser_dto *p_recv_dto;
+ struct iser_task *p_iser_task;
+ int iser_err = 0;
+
+ if (p_iser_conn == NULL) {
+ iser_err = -EINVAL;
+ goto iser_conn_term_exit;
+ }
+ if (atomic_read(&p_iser_conn->state) != ISER_CONN_UP) {
+ iser_err = -EPERM;
+ goto iser_conn_term_exit;
+ }
+
+ /* Release all receive control DTOs passed to Control_Notify */
+ spin_lock(&p_iser_conn->conn_lock);
+ while (!list_empty(&p_iser_conn->ctrl_notify_dto_list)) {
+ /* Get the next rcv buffer & remove it
+ from the list */
+ p_recv_dto =
+ list_entry(p_iser_conn->
+ ctrl_notify_dto_list.next,
+ struct iser_dto, dto_list);
+ list_del(&p_recv_dto->dto_list);
+ spin_unlock(&p_iser_conn->conn_lock);
+
+ /* Get the recv DTO descriptor coupled
+ with the PDU */
+ if (p_recv_dto->type != ISER_DTO_RCV) {
+ IPANIC("Releasing non-RECV type dto: "
+ "0x%p, type: %d\n",
+ p_recv_dto, p_recv_dto->type);
+ }
+
+ /* Release the buffers and dto descriptor */
+ iser_dto_free(p_recv_dto);
+
+ /* It this is the last DTO in a completed
+ task then free the task itself */
+ p_iser_task = p_recv_dto->p_task;
+ if (p_iser_task != NULL &&
+ iser_task_ctrl_notify_count_dec_and_test
+ (p_iser_task)) {
+ iser_task_free(p_iser_task);
+ }
+
+ spin_lock(&p_iser_conn->conn_lock);
+ }
+ spin_unlock(&p_iser_conn->conn_lock);
+
+ /* We need to terminate the conn synchronously */
+ iser_conn_sync_terminate(p_iser_conn);
+ iser_conn_release(p_iser_conn);
+
+ iser_conn_term_exit:
+ return iser_err;
+} /* iser_conn_term */
+
+/**
* iser_dealloc_conn_res - iSER API.
* Implements Dealloc_Connection_Resources primitive.
*
@@ -133,29 +551,19 @@
* Deallocs conn res previously allocd using
* alloc_conn_res(), if the conn becomes
* unnecessary.
- *
- * @returns iSER status (ISER_SUCCESS, ISER_FAILURE, ISER_INVALID_CONN)
*/
-iser_status iser_dealloc_conn_res(void *iscsi_conn_h)
+int iser_dealloc_conn_res(void *iser_conn_h)
{
- iser_status iser_ret = ISER_SUCCESS;
- struct iser_connection *p_iser_conn;
+ struct iser_connection *p_iser_conn = iser_conn_h;
+ int iser_err = 0;
- /* Find the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
- if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX
- "Failed to find iSER conn, for iscsi_h = 0x%p\n",
- iscsi_conn_h);
- return ISER_INVALID_CONN;
- goto dealloc_conn_res_exit;
+ if (p_iser_conn != NULL) {
+ iser_conn_release(p_iser_conn);
+ } else {
+ printk(KERN_ERR PFX "NULL conn handle\n");
+ iser_err = -EINVAL;
}
-
- /* Dealloc all res, free conn descriptor */
- iser_conn_free(p_iser_conn);
-
- dealloc_conn_res_exit:
- return iser_ret;
+ return iser_err;
} /* iser_dealloc_conn_res */
/**
@@ -179,26 +587,19 @@
*
* An iSCSI layer requests its local iSER datamover layer
* to take note of the negotiated values of the listed keys.
- *
- * returns iSER status (ISER_SUCCESS, ISER_FAILURE,
- * ISER_INVALID_CONN, ISER_ILLEGAL_PARAM)
*/
-iser_status iser_notice_key_values(void *iscsi_conn_h, char *key, char
*value)
+int iser_notice_key_values(void *iser_conn_h, char *key, char *value)
{
- struct iser_connection *p_iser_conn;
+ struct iser_connection *p_iser_conn = iser_conn_h;
int num_val;
- /* Find the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX "Connection not found, conn_h:
%ld\n",
- (unsigned long)iscsi_conn_h);
- return ISER_INVALID_CONN;
+ printk(KERN_ERR PFX "NULL conn handle \n");
+ return -EINVAL;
}
-
if (key == NULL || value == NULL) {
printk(KERN_ERR PFX "NULL key or value\n");
- return ISER_ILLEGAL_PARAM;
+ return -EINVAL;
}
/* Compare key to the supported key p_iser_connnames
@@ -250,15 +651,15 @@
p_iser_conn->param.ErrorRecoveryLevel = num_val;
} else {
printk(KERN_ERR PFX "Unsupported key name: %s\n", key);
- return ISER_INVALID_KEY;
+ return -EINVAL;
}
ITRACE(ISER_TRACE_CONN, "Set %s to %d\n", key, num_val);
- return ISER_SUCCESS;
+ return 0;
- notice_key_values_invalid_val:
+ notice_key_values_invalid_val:
printk(KERN_ERR PFX "Invalid value: %s for key %s\n", value,
key);
- return ISER_INVALID_VALUE;
+ return -EINVAL;
} /* iser_notice_key_values */
@@ -337,26 +738,22 @@
*
* returns allocd DTO descriptor
*/
-iser_status
-iser_release_control(void *iscsi_conn_h, struct iser_recv_pdu
*p_ctrl_pdu)
+int
+iser_release_control(void *iser_conn_h, struct iser_recv_pdu
*p_ctrl_pdu)
{
- struct iser_connection *p_iser_conn;
+ struct iser_connection *p_iser_conn = iser_conn_h;
struct iser_dto *p_recv_dto;
struct iser_task *p_iser_task;
- iser_status iser_ret = ISER_SUCCESS;
+ int iser_err = 0;
- /* Find the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
if (p_iser_conn == NULL) {
- iser_ret = ISER_INVALID_CONN;
+ iser_err = -EINVAL;
goto release_control_exit;
}
-
if (p_ctrl_pdu == NULL) {
- printk(KERN_ERR PFX
- "NULL receive control to release, conn: 0x%p\n",
- iscsi_conn_h);
- iser_ret = ISER_ILLEGAL_PARAM;
+ printk(KERN_ERR PFX "NULL recv ctrl to release, conn:
0x%p\n",
+ p_iser_conn);
+ iser_err = -EINVAL;
goto release_control_exit;
}
@@ -384,13 +781,14 @@
}
release_control_exit:
- return iser_ret;
+ return iser_err;
} /* iser_release_control */
/**
* iser_conn_wait_for_disconn - Sleep on queue and wait
* until the conn is fully disconnected
- **/
+ *
+ */
void iser_conn_wait_for_disconn(struct iser_connection *p_iser_conn)
{
ITRACE(ISER_TRACE_CONN, "Waiting for the disconnect event,
p_conn: "
@@ -400,23 +798,19 @@
ISER_CONN_DOWN));
ITRACE(ISER_TRACE_CONN, "Got the disconnect event, p_conn:
0x%p\n",
p_iser_conn);
+} /* iser_conn_wait_for_disconn */
- /* Destroy the conn finally */
- /*iser_conn_free(p_iser_conn); */
-}
-
/**
- * iser_conn_sync_terminate - Triggers start of the disconn procedures
+ * iser_conn_sync_terminate - Triggers start of the disconnect
procedures
*/
int iser_conn_sync_terminate(struct iser_connection *p_iser_conn)
{
- int ret_val = -1;
+ int ret_val = 0;
switch (atomic_read(&p_iser_conn->state)) {
case ISER_CONN_UP:
case ISER_CONN_PENDING:
/* Signal that the conn is being terminated
synchronously */
- /*p_iser_conn->state = ISER_CONN_SYNC_TERM; */
atomic_set(&p_iser_conn->state, ISER_CONN_SYNC_TERM);
/* Start the disconnect procedures */
ret_val = iser_disconnect(p_iser_conn);
@@ -432,25 +826,23 @@
case ISER_CONN_SYNC_TERM:
iser_conn_wait_for_disconn(p_iser_conn);
- ret_val = 0;
break;
case ISER_CONN_ASYNC_TERM:
/* Signal that the conn is being terminated
synchronously */
- /*p_iser_conn->state = ISER_CONN_SYNC_TERM; */
atomic_set(&p_iser_conn->state, ISER_CONN_SYNC_TERM);
/* Sleep on queue and wait until the conn
is fully disconnected */
iser_conn_wait_for_disconn(p_iser_conn);
- ret_val = 0;
break;
case ISER_CONN_DOWN:
- ret_val = 0; /* this may happen only when the iSCSI
is
- being currently notified */
+ /* this may happen only when iSCSI is being notified */
+ break;
default:
printk(KERN_ERR PFX "called when in state %s\n",
iser_conn_get_state_name(p_iser_conn));
+ ret_val = -EPERM;
break;
}
@@ -481,116 +873,40 @@
} /* iser_conn_async_terminate */
/**
- * iser_connectionerminate - iSER API. Implements
- * Connection_Terminate primitive.
- *
- *
- * Starts conn teardown process. Waits until all previously posted
- * buffers get flushed. Deallocs all conn res.
- *
- * returns iSER status (ISER_SUCCESS, ISER_FAILURE, ISER_INVALID_CONN)
- */
-iser_status iser_connectionerminate(void *iscsi_conn_h)
-{
- iser_status iser_ret = ISER_SUCCESS;
- struct iser_connection *p_iser_conn;
-
- /* Find the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
- if (p_iser_conn != NULL) {
- struct iser_dto *p_recv_dto;
- struct iser_task *p_iser_task;
-
- /* Release all receive control DTOs passed to
Control_Notify */
- spin_lock(&p_iser_conn->conn_lock);
- while (!list_empty(&p_iser_conn->ctrl_notify_dto_list))
{
- /* Get the next rcv buffer & remove it
- from the list */
- p_recv_dto =
- list_entry(p_iser_conn->
- ctrl_notify_dto_list.next,
- struct iser_dto, dto_list);
- list_del(&p_recv_dto->dto_list);
- spin_unlock(&p_iser_conn->conn_lock);
-
- /* Get the recv DTO descriptor coupled
- with the PDU */
- if (p_recv_dto->type != ISER_DTO_RCV) {
- IPANIC("Releasing non-RECV type dto: "
- "0x%p, type: %d\n",
- p_recv_dto, p_recv_dto->type);
- }
-
- /* Release the buffers and dto descriptor */
- iser_dto_free(p_recv_dto);
-
- /* It this is the last DTO in a completed
- task then free the task itself */
- p_iser_task = p_recv_dto->p_task;
- if (p_iser_task != NULL &&
- iser_task_ctrl_notify_count_dec_and_test
- (p_iser_task)) {
- iser_task_free(p_iser_task);
- }
-
- spin_lock(&p_iser_conn->conn_lock);
- }
- spin_unlock(&p_iser_conn->conn_lock);
-
- /* We need to terminate the conn syncronously */
- if (iser_conn_sync_terminate(p_iser_conn) != 0) {
- iser_ret = ISER_FAILURE;
- }
- } else {
- iser_ret = ISER_INVALID_CONN;
- }
-
- return iser_ret;
-} /* iser_connectionerminate */
-
-/**
- * iser_conn_free - Frees all conn objects and
+ * iser_conn_release - Frees all conn objects and
* deallocs conn descriptor
*/
-void iser_conn_free(struct iser_connection *p_iser_conn)
+void iser_conn_release(struct iser_connection *p_iser_conn)
{
-
if (atomic_read(&p_iser_conn->state) == ISER_CONN_DOWN) {
- /* Free all previosly allocd kDAPL objects, */
- /* this may be not the first call */
- /* but the end-point is freed only once */
- iser_free_ep(p_iser_conn);
-
- /* Detach from the adaptor conns list */
+ iser_free_ep(p_iser_conn); /* ep is freed only once */
iser_adaptor_remove_conn(p_iser_conn);
- /* Detach from the entity conns list */
- iser_entity_remove_conn(p_iser_conn);
-
- /* Detach from conns hash */
- hash_delete_iser_conn(p_iser_conn);
-
/* Destroy the buffer pools */
if (p_iser_conn->post_recv_pool != NULL) {
iser_bpool_destroy(p_iser_conn->post_recv_pool);
+ if (p_iser_conn->post_recv_pool ==
+ p_iser_conn->send_data_pool) {
+ p_iser_conn->send_data_pool = NULL;
+ }
+ p_iser_conn->post_recv_pool = NULL;
}
- if (p_iser_conn->send_data_pool != NULL &&
- p_iser_conn->send_data_pool !=
- p_iser_conn->post_recv_pool) {
+ if (p_iser_conn->send_data_pool != NULL) {
iser_bpool_destroy(p_iser_conn->send_data_pool);
+ p_iser_conn->send_data_pool = NULL;
}
-
if (p_iser_conn->spare_post_recv_pool != NULL) {
iser_bpool_destroy(p_iser_conn->spare_post_recv_pool);
+ p_iser_conn->spare_post_recv_pool = NULL;
}
if (p_iser_conn->spare_send_data_pool != NULL) {
iser_bpool_destroy(p_iser_conn->spare_send_data_pool);
+ p_iser_conn->spare_send_data_pool = NULL;
}
- /* Return the memory to the slab */
- kmem_cache_free(ig.conn_mem_cache, p_iser_conn);
+ sock_release(iser_conn_to_sock(p_iser_conn));
}
-} /* iser_conn_free */
+} /* iser_conn_release */
/**
* iser_complete_conn_termination - Checks if the conn
@@ -631,9 +947,7 @@
/* If the conn was terminated asynchronously, */
/* notify the upper layer */
if (cur_conn_state == ISER_CONN_ASYNC_TERM) {
- p_iser_conn->p_entity->
- api_cb.conn_terminate_notify(p_iser_conn->
- iscsi_conn_h);
+
ig.api_cb.conn_term_notify(p_iser_conn->iscsi_conn_h);
}
/* Free all tasks in this conn */
@@ -647,15 +961,11 @@
}
spin_unlock(&p_iser_conn->conn_lock);
- /* Destroy the conn finally */
- iser_conn_free(p_iser_conn);
-
if (cur_conn_state == ISER_CONN_SYNC_TERM) {
- /* If the conn was terminated syncronously, wake
up
- the upper layer (waiting on a sleep queue) */
wake_up_interruptible(&p_iser_conn->disconnect_wait_q);
+ } else {
+ iser_conn_release(p_iser_conn);
}
-
retval = 0;
} else {
ITRACE(ISER_TRACE_CONN,
@@ -665,7 +975,6 @@
send_buf_count,
iser_conn_get_state_name(p_iser_conn));
retval = -1;
}
-
return retval;
} /* iser_complete_conn_termination */
Index: iser_utils.c
===================================================================
--- iser_utils.c (revision 3404)
+++ iser_utils.c (working copy)
@@ -35,8 +35,8 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
-#include <asm/io.h> /* struct iovec */
-#include <asm/scatterlist.h> /* struct scatterlist */
+#include <asm/io.h>
+#include <asm/scatterlist.h>
#include "iser.h"
#include "iser_utils.h"
@@ -134,7 +134,6 @@
*/
void hash_delete_iser_task(struct iser_task *it)
{
-
spin_lock(&ig.task_hash.lock);
if (!list_empty(&it->hash_list))
list_del_init(&it->hash_list);
@@ -143,128 +142,10 @@
} /* hash_delete_iser_task */
/*
---------------------------------------------------------------------
- * ISER CONNECTION-SPECIFIC HASH MANAGEMENT
+ * BUFFERS
* ------------------------------------------------------------------
*/
/**
- * hash_add_iser_conn - Add iSER conn descriptor to the
- * conns hash table
- */
-void hash_add_iser_conn(struct iser_connection *iser_conn)
-{
- int hash_val;
-
- hash_val = hash_func((u32) (long)iser_conn->iscsi_conn_h);
-
- spin_lock(&ig.conn_hash.lock);
- INIT_LIST_HEAD(&iser_conn->hash_list);
- list_add_tail(&iser_conn->hash_list,
- &(ig.conn_hash.bucket_head[hash_val]));
- spin_unlock(&ig.conn_hash.lock);
-
-} /* hash_add_iser_conn */
-
-/**
- * hash_find_iser_conn - Find am iSER conn descriptor
- * in the conns hash table.
- *
- * Use conn handle supplied by iSCSI as the key.
- *
- * returns found conn decriptor or NULL.
- */
-struct iser_connection *hash_find_iser_conn(void *iscsi_conn_h)
-{
- int hash_val;
- struct list_head *p_bucket;
- struct list_head *p_list;
- struct iser_connection *iser_conn = NULL;
-
- hash_val = hash_func((u32) (long)iscsi_conn_h);
- p_bucket = &(ig.conn_hash.bucket_head[hash_val]);
-
- spin_lock(&ig.conn_hash.lock);
- p_list = p_bucket->next;
- while (p_list != p_bucket) {
- iser_conn =
- list_entry(p_list, struct iser_connection,
hash_list);
- if (iser_conn->iscsi_conn_h == iscsi_conn_h)
- break;
- iser_conn = NULL;
- p_list = p_list->next;
- }
- spin_unlock(&ig.conn_hash.lock);
-
- return iser_conn;
-} /* hash_find_iser_conn */
-
-/*
- * Removes an iSER conn from the conns hash
- */
-void hash_delete_iser_conn(struct iser_connection *iser_conn)
-{
-
- spin_lock(&ig.conn_hash.lock);
- if (!list_empty(&iser_conn->hash_list)) {
- list_del_init(&iser_conn->hash_list);
- }
- spin_unlock(&ig.conn_hash.lock);
-
-} /* hash_delete_iser_conn */
-
-/**
- * iser_get_data_total_length - Calculates the total buffer
- * length for different buffer
- * descriptor types
- *
- * returns total buffer length in bytes
- */
-unsigned long iser_get_data_total_length(struct iser_data_buf *p_data,
- int skip, int count)
-{
- unsigned long total_len = 0;
-
- if (p_data == NULL) {
- IPANIC("NULL data buffer descriptor\n");
- }
- switch (p_data->type) {
- case ISER_BUF_TYPE_SINGLE:
- total_len = p_data->size;
- break;
-
- case ISER_BUF_TYPE_SCATTERLIST:{
- struct scatterlist *p_sg =
- (struct scatterlist *)p_data->p_buf;
- int i, last;
-
- if (p_sg == NULL) {
- IPANIC("NULL data buffer's sglist\n");
- }
-
- last = skip + count;
- /* check for last>p_mem->size error ? */
- for (i = skip; i < last; i++) {
- total_len += (unsigned
long)p_sg[i].length;
- }
- break;
- }
-
- default:
- IPANIC("Unsupported buffer type: %d\n", p_data->type);
- break;
- }
-
- ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "calculated total length=%ld for p_data->type = %d\n",
- total_len, p_data->type);
- /* total_len is expected to be > 0 */
- if (total_len == 0) {
- IPANIC("total_len is 0\n");
- }
-
- return total_len;
-} /* iser_get_data_total_length */
-
-/**
* iser_single_virt_to_phys - Translates virtual addresses from a
* single pointer to
* physical addresses in a user-supplied output array
@@ -290,7 +171,7 @@
}
ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "Translating data: 0x%p, single virt: " "0x%p, data size:
%d\n",
+ "Translating data:0x%p, single virt:0x%p, data sz: %d\n",
p_data, p_data->p_buf, p_data->size);
/* compute the offset of first element */
@@ -310,8 +191,8 @@
for (i = 0, page = fpage; page < lpage; page += PAGE_SIZE, i++)
{
p_phys->addrs[i] = page;
ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "SINGLE VIRT ADDED page[%d]=0x%lX " "at pmt
%p\n", i,
- (long)page, p_phys);
+ "SINGLE VIRT ADDED page[%d]=0x%lX at phys_desc
%p\n",
+ i, (long)page, p_phys);
}
p_phys->data_size = p_data->size;
@@ -322,12 +203,13 @@
/**
* iser_sglist_virt_to_phys - Translates scatterlist entries to
* physical addresses
+ *
* returns the length of resulting physical address array (may be less
- * than the original
- * due to possible compaction).
+ * than the original due to possible compaction).
*/
int iser_sglist_virt_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip, int
count)
+ struct iser_phys_mem *p_phys,
+ int skip, int count)
{
struct scatterlist *p_sg;
unsigned int cur_phys = 0;
@@ -382,16 +264,17 @@
return cur_phys;
} /* iser_sglist_virt_to_phys */
-#define MASK_4K ((1UL << 12) - 1) /* 0xFFF */
-#define IS_PAGE_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0)
+#define MASK_4K ((1UL << 12) - 1) /* 0xFFF */
+#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & MASK_4K) == 0)
/**
- * iser_iovec_aligned_length - Tries to determine the maximal
+ * iser_data_aligned_length - Tries to determine the maximal
* correctly aligned sub-list of a
* scatter-gather list of memory buffers
* returns the number of entries which are aligned correctly
*/
-unsigned int iser_iovec_aligned_length(struct iser_data_buf *p_data,
int skip)
+unsigned int iser_data_aligned_length(struct iser_data_buf *p_data,
+ int skip)
{
unsigned int ret_len = 0;
int i, count;
@@ -427,7 +310,7 @@
"Checking sg iobuf end address "
"0x%08lX\n", end_addr);
if ((i + 1 < p_data->size)
- && !IS_PAGE_ALIGNED(end_addr)) {
+ && !IS_4K_ALIGNED(end_addr)) {
ret_len = count + 1;
break;
}
@@ -447,15 +330,15 @@
ret_len, p_data->size, p_data);
return ret_len;
-} /* iser_iovec_aligned_length */
+} /* iser_data_aligned_length */
/**
- * iser_iovec_contig_length - Tries to determine the maximal
+ * iser_data_contig_length - Tries to determine the maximal
* contiguous sub-list of a
* scatter-gather list of memory buffers
* returns the number of entries which are aligned correctly
*/
-unsigned int iser_iovec_contig_length(struct iser_data_buf *p_data, int
skip,
+unsigned int iser_data_contig_length(struct iser_data_buf *p_data, int
skip,
uint64_t * start_addr, int *size)
{
unsigned int ret_len = 0;
@@ -509,75 +392,25 @@
return ret_len;
}
-/**
- * iser_phys_to_virt - Translates physical address to virtual kernel
address
- * returns virtual kernel address
- */
-inline void *iser_phys_to_virt(void *phys_addr)
-{
- return phys_to_virt((unsigned long)phys_addr);
-}
/**
- * iser_page_to_virt - Translates page descriptor to virtual kernel
address
- * returns virtual kernel address
- */
-inline void *iser_page_to_virt(struct page *page)
-{
- return phys_to_virt(page_to_phys(page));
-}
-
-/**
- * iser_iovec_virt_entry_addr - Retrieves address of a single
IOVEC_VIRT entry
- * returns IOVEC_VIRT entry address
- */
-inline void *iser_iovec_virt_entry_addr(void *p_iovec_virt, int i)
-{
- struct iovec *p_iovec;
- p_iovec = (struct iovec *)p_iovec_virt;
- return p_iovec[i].iov_base;
-}
-
-/**
- * iser_iovec_phys_entry_to_virt - Translates address of a single
- * IOVEC_PHYS entry to virtual kernel address
- * returns IOVEC_PHYS entry virtual address
- */
-inline void *iser_iovec_phys_entry_to_virt(void *p_iovec_phys, int i)
-{
- struct iovec *p_iovec;
- p_iovec = (struct iovec *)p_iovec_phys;
- return phys_to_virt((unsigned long)p_iovec[i].iov_base);
-}
-
-/**
* iser_sglist_entry_to_virt - Translates address of a single
* SCATTERLIST entry to virtual kernel address
* returns SCATTERLIST entry virtual address
*/
-inline void *iser_sglist_entry_to_virt(void *p_sglist, int i)
+static inline void *iser_sglist_entry_to_virt(void *p_sglist, int i)
{
struct scatterlist *p_sg;
p_sg = (struct scatterlist *)p_sglist;
return phys_to_virt(page_to_phys(p_sg[i].page) +
p_sg[i].offset);
}
-/**
- * iser_iovec_entry_len - Retrieves length of a single IOVEC_PHYS/VIRT
entry
- * returns IOVEC_PHYS/VIRT entry lengths
- */
-inline unsigned long iser_iovec_entry_len(void *p_iovec_arr, int i)
-{
- struct iovec *p_iovec;
- p_iovec = (struct iovec *)p_iovec_arr;
- return (unsigned long)p_iovec[i].iov_len;
-}
/**
* iser_sglist_entry_len - Retrieves length of a single SCATTERLIST
entry
* returns SCATTERLIST entry lengths
*/
-inline unsigned long iser_sglist_entry_len(void *p_sglist, int i)
+static inline unsigned long iser_sglist_entry_len(void *p_sglist, int
i)
{
struct scatterlist *p_sg;
p_sg = (struct scatterlist *)p_sglist;
@@ -592,9 +425,6 @@
struct iser_data_buf *p_src_data,
unsigned long *p_total_copied_sz)
{
- unsigned char *chunk_addr = 0;
- unsigned int chunk_size = 0;
- int i;
if (p_src_data->type == ISER_BUF_TYPE_SINGLE) {
ITRACE(ISER_TRACE_PHYS_MEM_REG,
"copy SINGLE virt: 0x%p -> 0x%p, " "sz: %d\n",
@@ -603,66 +433,90 @@
if (p_total_copied_sz != NULL) {
*p_total_copied_sz = p_src_data->size;
}
- return;
}
+ else {
+ unsigned char *chunk_addr = 0;
+ unsigned int chunk_size = 0;
+ unsigned long total_sz = 0;
+ int i;
- if (p_total_copied_sz != NULL) {
- *p_total_copied_sz = 0;
- }
-
- for (i = 0; i < p_src_data->size; i++) {
- switch (p_src_data->type) {
- case ISER_BUF_TYPE_SCATTERLIST:
+ for (i = 0; i < p_src_data->size; i++) {
chunk_addr = (unsigned char *)
iser_sglist_entry_to_virt(p_src_data->p_buf,
i);
chunk_size =
iser_sglist_entry_len(p_src_data->p_buf, i);
- break;
-
- default:
- IPANIC("Unexpected buffer type\n");
- break;
+ ITRACE(ISER_TRACE_PHYS_MEM_REG,
+ "copy SG[%d]: 0x%p -> 0x%p, sz: %d\n",
+ i, chunk_addr, p_dst_buf, chunk_size);
+ memcpy(p_dst_buf, chunk_addr, chunk_size);
+ p_dst_buf += chunk_size;
+ total_sz += chunk_size;
}
-
- ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "copy IOVEC[%d] virt: 0x%p -> 0x%p, sz: %d\n", i,
- chunk_addr, p_dst_buf, chunk_size);
- memcpy(p_dst_buf, chunk_addr, chunk_size);
- p_dst_buf += chunk_size;
if (p_total_copied_sz != NULL) {
- *p_total_copied_sz += chunk_size;
+ *p_total_copied_sz = total_sz;
}
}
}
+void iser_data_desc_dump(struct iser_data_buf *p_data)
+{
+ if (p_data->type == ISER_BUF_TYPE_SINGLE) {
+ IINFO("single addr:0x%p sz:%d\n",
+ p_data->p_buf, p_data->size);
+ } else {
+ struct scatterlist *p_sg = (struct scatterlist
*)p_data->p_buf;
+ int i;
+ for (i = 0; i < p_data->size; i++) {
+ IINFO("sg[%d] dma_addr:0x%lX page:0x%p off:%d
sz:%d\n",
+ i, (unsigned long)p_sg[i].dma_address,
+ p_sg[i].page,
+ p_sg[i].offset,
+ p_sg[i].length);
+ }
+ }
+} /* iser_data_desc_dump */
+
/**
- * iser_data_buf_get_type_name - Retrieves name of a iSER data buffer
type
- * returns name string
+ * iser_sg_subset_len - Calculates the total buffer length
+ * for different buffer types
+ *
+ * returns total buffer length in bytes
*/
-static char *iser_data_bufype_name[ISER_BUF_TYPES_NUM + 1] = {
- "SINGLE", /* ISER_BUF_TYPE_SINGLE */
- "SCATTERLIST", /* ISER_BUF_TYPE_SCATTERLIST */
-
- "ILLEGAL" /* ISER_BUF_TYPES_NUM */
-};
-
-char *iser_data_buf_get_type_name(struct iser_data_buf *p_data)
+unsigned long iser_sg_subset_len(struct iser_data_buf *p_data,
+ int skip_entries,
+ int count_entries)
{
- if (p_data != NULL && p_data->type < ISER_BUF_TYPES_NUM) {
- return iser_data_bufype_name[p_data->type];
- } else {
- return iser_data_bufype_name[ISER_BUF_TYPES_NUM];
+ struct scatterlist *p_sg = (struct scatterlist *)p_data->p_buf;
+ unsigned long total_len = 0;
+ int last_entry;
+ int i;
+
+ if (p_sg == NULL) {
+ IPANIC("NULL data buffer's sglist\n");
}
-} /* iser_data_buf_get_type_name */
+ last_entry = skip_entries + count_entries;
+ /* check for last>p_mem->size error ? */
+ for (i = skip_entries; i < last_entry; i++) {
+ total_len += (unsigned long)p_sg[i].length;
+ }
+ ITRACE(ISER_TRACE_PHYS_MEM_REG,
+ "calculated total length=%ld for p_data->type = %d\n",
+ total_len, p_data->type);
+ /* total_len is expected to be > 0 */
+ if (total_len == 0) {
+ IPANIC("total_len is 0\n");
+ }
+ return total_len;
+} /* iser_sg_subset_len */
/**
- * iser_alloc_phys_mem - alloc phys_mem structure and page array
+ * iser_alloc_phys_desc - alloc phys_mem structure and page array
* large enough to contain the translated iser data buffer
*/
-struct iser_phys_mem *iser_alloc_phys_mem(struct iser_data_buf *p_data,
+struct iser_phys_mem *iser_alloc_phys_desc(struct iser_data_buf
*p_data,
int skip, int count)
{
- struct iser_phys_mem *pmt;
+ struct iser_phys_mem *phys_desc;
int pages, total_size;
/* compute number of elements that should be in the array */
@@ -670,49 +524,52 @@
IPANIC("count == 0 - do not expect that\n");
}
- total_size = iser_get_data_total_length(p_data, skip, count);
+ if (p_data->type == ISER_BUF_TYPE_SINGLE) {
+ total_size = p_data->size;
+ }
+ else {
+ total_size = iser_sg_subset_len(p_data, skip, count);
+ }
pages = total_size / PAGE_SIZE + 2;
/* alloc a structure and the array */
- pmt = kmalloc(sizeof(struct iser_phys_mem) + sizeof(uint64_t) *
pages,
- GFP_KERNEL | __GFP_NOFAIL);
- if (pmt == NULL) {
+ phys_desc = kmalloc(sizeof(struct iser_phys_mem) +
+ (sizeof(uint64_t) * pages),
+ GFP_KERNEL | __GFP_NOFAIL);
+ if (phys_desc == NULL) {
IPANIC("Failed to alloc phys_mem for data size=%d "
"in approximately %d pages\n", total_size,
pages);
return NULL;
}
- pmt->addrs = (uint64_t *) (pmt + 1);
- pmt->data_size = total_size;
- pmt->length = 0;
- pmt->offset = 0;
+ phys_desc->addrs = (uint64_t *) (phys_desc + 1);
+ phys_desc->data_size = total_size;
+ phys_desc->length = 0;
+ phys_desc->offset = 0;
ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "Allocated phys_mem %p for "
- "data size=%d in approximately %d pages\n", pmt,
total_size,
- pages);
+ "Allocated phys_mem %p for size=%d in appr. %d pages\n",
+ phys_desc, total_size, pages);
- return pmt;
-}
+ return phys_desc;
+} /* iser_alloc_phys_desc */
-void iser_free_phys_mem(struct iser_phys_mem *pmt)
+void iser_free_phys_desc(struct iser_phys_mem *phys_desc)
{
-
- if (pmt == NULL) {
+ if (phys_desc == NULL) {
IPANIC("Called with NULL phys_mem\n");
}
+ ITRACE(ISER_TRACE_PHYS_MEM_REG, "Freeing phys_mem %p\n",
phys_desc);
+ kfree(phys_desc);
+} /* iser_free_phys_desc */
- ITRACE(ISER_TRACE_PHYS_MEM_REG, "Freeing phys_mem %p\n", pmt);
- kfree(pmt);
-
-}
-
/**
- * iser_convert_mem_to_phys - expand iov/sg elements into an
+ * iser_data_convert_to_phys - expand iov/sg elements into an
* array of physical addresses
* @return number of addresses in the expanded array
*/
-int iser_convert_mem_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip, int
count)
+int iser_data_convert_to_phys(struct iser_data_buf *p_data,
+ struct iser_phys_mem *p_phys,
+ int skip, int count)
{
int phys_vec_len = 0;
@@ -742,4 +599,5 @@
p_phys->length = phys_vec_len;
return phys_vec_len;
-}
+} /* iser_data_convert_to_phys */
+
Index: iser_kdapl.h
===================================================================
--- iser_kdapl.h (revision 3404)
+++ iser_kdapl.h (working copy)
@@ -80,7 +80,7 @@
ISER_EVD_MAX_REQ_DTOS)
#define ISER_MAX_ASYNC_QLEN 8
-#define ISER_MAX_TOTAL_QLEN (ISER_MAX_ENTITIES * ISER_MAX_QLEN)
+#define ISER_MAX_TOTAL_QLEN ISER_MAX_QLEN
int iser_create_ia_pz_evd(struct iser_adaptor *p_adaptor);
@@ -97,13 +97,6 @@
int iser_event_handler_thread(void *arg_unused);
-int iser_register_virt_mem(struct iser_adaptor *p_adaptor,
- void *p_buf,
- unsigned long data_sz,
- enum dat_mem_priv_flags priv_flags,
- struct iser_mem_handles *mem_reg,
- DAT_RMR_CONTEXT * rmr_ctxt);
-
int iser_register_phys_mem(struct iser_adaptor *p_adaptor,
struct iser_phys_mem *p_phys_vec,
enum dat_mem_priv_flags priv_flags,
Index: iser_initiator.c
===================================================================
--- iser_initiator.c (revision 3404)
+++ iser_initiator.c (working copy)
@@ -31,12 +31,6 @@
*
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <linux/delay.h>
-#include <linux/smp_lock.h>
-
#include "iser.h"
#include "iser_conn.h"
#include "iser_task.h"
@@ -45,123 +39,15 @@
#include "iser_memory.h"
#include "iser_utils.h"
-struct iser_global ig;
-
-iser_status iser_conn_establish(void *api_h,
- void *iscsi_conn_h,
- struct sockaddr_in *dst_addr,
- struct sockaddr_in *src_addr);
-
-iser_status iser_alloc_conn_res(void *conn_h, struct iser_conn_res
*conn_res);
-
-iser_status iser_enable_datamover(void *iser_conn_h, void *tport_conn);
-
-iser_status iser_conn_accept(void *conn_req_h, void *iscsi_conn_h, int
accept);
-
-iser_status iser_send_control(void *iscsi_conn_h,
- struct iser_send_pdu *p_ctrl_pdu);
-
-void iser_adaptor_add_conn(struct iser_adaptor *p_iser_adaptor,
- struct iser_connection *p_iser_conn);
-
-void iser_entity_add_conn(struct iser_entity *p_entity,
- struct iser_connection *p_iser_conn);
-
-int iser_adaptor_init(struct iser_adaptor *p_iser_adaptor, char *name);
-
-int iser_adaptor_release(struct iser_adaptor *p_iser_adaptor);
-int ig_init(void);
-int ig_release(void);
-
/**
- * iser_conn_establish - Initiates conn establishment process.
- *
- * returns iSER status (ISER_SUCCESS, ISER_FAILURE,
ISER_ILLEGAL_PARAM)
- */
-iser_status iser_conn_establish(void *api_h,
- void *iscsi_conn_h,
- struct sockaddr_in *dst_addr,
- struct sockaddr_in *src_addr)
-{
- struct iser_entity *p_entity;
- struct iser_connection *p_iser_conn;
- struct iser_adaptor *p_adaptor;
- char bufpool_name[128];
- int ep_create_ret;
-
- if (api_h == NULL || api_h == ISER_INVALID_API_H) {
- printk(KERN_ERR PFX "API Handle is illegal: 0x%p\n",
api_h);
- return ISER_ILLEGAL_PARAM;
- }
- p_entity = (struct iser_entity *)api_h;
-
- /* Allocate and initialize iSER conn structure */
- p_iser_conn = iser_conn_alloc();
- if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX "iser_conn_alloc failed\n");
- goto iser_conn_establish_failure;
- }
-
- p_iser_conn->iscsi_conn_h = iscsi_conn_h;
- p_iser_conn->p_entity = p_entity;
- p_adaptor = &ig.adaptor[0];
-
- iser_adaptor_add_conn(p_adaptor, p_iser_conn);
- iser_entity_add_conn(p_entity, p_iser_conn);
- hash_add_iser_conn(p_iser_conn);
-
- /* Allocate post-receive buffers for the login phase */
- sprintf(bufpool_name, "%s-login-pdu-data",
p_entity->provider_name);
- p_iser_conn->post_recv_pool =
- iser_large_bpool_create(p_iser_conn->p_adaptor,
bufpool_name,
- ISER_LOGIN_PHASE_PDU_DATA_LEN, 4,
0);
- if (p_iser_conn->post_recv_pool == NULL) {
- printk(KERN_ERR PFX "login pool = NULL\n");
- goto iser_conn_establish_failure;
- }
-
- /* During the login phase data for sent PDUs is drawn from */
- /* the same buffer pool as recv */
- p_iser_conn->send_data_pool = p_iser_conn->post_recv_pool;
-
- ep_create_ret = iser_create_ep(p_iser_conn);
- if (ep_create_ret != 0)
- goto iser_conn_establish_failure;
-
- if (dst_addr != NULL) {
- sprintf(p_iser_conn->name, "%d.%d.%d.%d",
- NIPQUAD(dst_addr->sin_addr));
- } else {
- sprintf(p_iser_conn->name, "Unknown");
- }
- ITRACE(ISER_TRACE_CONN, "Connecting to: %s, port 0x%x\n",
- p_iser_conn->name, dst_addr->sin_port);
-
- atomic_set(&p_iser_conn->state, ISER_CONN_PENDING);
-
- if (iser_connect(p_iser_conn, dst_addr, src_addr) != 0) {
- printk(KERN_ERR PFX "iser_connect failed\n");
- goto iser_conn_establish_failure;
- }
- return ISER_SUCCESS;
-
- iser_conn_establish_failure:
- if (p_iser_conn) {
- atomic_set(&p_iser_conn->state, ISER_CONN_DOWN);
- iser_conn_free(p_iser_conn);
- }
- printk(KERN_ERR PFX "%s: failed\n", __FUNCTION__);
- return ISER_FAILURE;
-} /* iser_conn_establish */
-
-/**
* iser_reg_rdma_mem - Registers memory
* intended for RDMA, obtaining RMR context
*
* returns 0 on success, -1 on failure
*/
int iser_reg_rdma_mem(struct iser_task *p_iser_task,
- enum iser_data_dir cmd_dir, struct iser_data_buf
*p_mem)
+ enum iser_data_dir cmd_dir,
+ struct iser_data_buf *p_mem)
{
struct iser_dto *p_dto = NULL;
struct iser_regd_buf *p_rdma_regd = NULL;
@@ -187,40 +73,26 @@
cmd_dir, p_iser_task);
}
- p_phys_vec = iser_alloc_phys_mem(p_mem, 0, p_mem->size);
+ p_phys_vec = iser_alloc_phys_desc(p_mem, 0, p_mem->size);
if (p_mem->type != ISER_BUF_TYPE_SINGLE) {
ITRACE(ISER_TRACE_SEND_CONTROL,
"converting non-single to phys\n");
- /* Determine an aligned stretch and check that
- the entire vector is aligned correctly */
- aligned_len = iser_iovec_aligned_length(p_mem, 0);
+ aligned_len = iser_data_aligned_length(p_mem, 0);
if (aligned_len != p_mem->size) {
- int i;
- /* Get the input iovec array */
- struct iovec *p_iovec_phys =
- (struct iovec *)p_mem->p_buf;;
-
- printk(KERN_ERR PFX
- "Can't register for rdma because of
alignment "
- "violation\n");
- for (i = 0; i < p_mem->size; i++) {
- IINFO("iov[%d] addr=0x%lX size=%ld\n",
- i,
- (unsigned
long)p_iovec_phys[i].iov_base,
- (unsigned
long)p_iovec_phys[i].iov_len);
- }
+ printk(KERN_ERR PFX "Can't register for rdma, "
+ "alignment violation\n");
+ iser_data_desc_dump(p_mem);
ret_val = -1;
goto register_rdma_memory_exit;
}
- phys_vec_len = iser_convert_mem_to_phys(p_mem,
p_phys_vec, 0,
- aligned_len);
+ phys_vec_len = iser_data_convert_to_phys(p_mem,
p_phys_vec,
+ 0,
aligned_len);
} else {
ITRACE(ISER_TRACE_SEND_CONTROL, "converting single to
phys\n");
- phys_vec_len =
- iser_convert_mem_to_phys(p_mem, p_phys_vec, 0, 0);
+ phys_vec_len = iser_data_convert_to_phys(p_mem,
p_phys_vec,
+ 0, 0);
}
-
/* Start initializing the RDMA regsitered memory descriptor */
memset(p_rdma_regd, 0, sizeof(struct iser_regd_buf));
ITRACE(ISER_TRACE_CONN, "memset at 0x%p to 0x%lX\n",
p_rdma_regd,
@@ -259,7 +131,7 @@
spin_unlock(&p_iser_task->task_lock);
register_rdma_memory_exit:
- iser_free_phys_mem(p_phys_vec);
+ iser_free_phys_desc(p_phys_vec);
return ret_val;
} /* iser_reg_rdma_mem */
@@ -439,49 +311,42 @@
* operating in the remote iSCSI node. The iSER datamover layer sends
* the PDU after adding its own protocol header.
*/
-iser_status iser_send_control(void *iscsi_conn_h,
- struct iser_send_pdu * p_ctrl_pdu)
+int iser_send_control(void *iser_conn_h,
+ struct iser_send_pdu * p_ctrl_pdu)
{
- iser_status iser_ret = ISER_SUCCESS;
+ struct iser_connection *p_iser_conn = iser_conn_h;
union iser_pdu_bhs *p_bhs;
- struct iser_connection *p_iser_conn = NULL;
struct iser_dto *p_send_dto = NULL;
struct iser_task *p_iser_task = NULL;
unsigned long buf_offset;
unsigned long data_seg_len;
unsigned int itt;
unsigned char opcode;
+ int iser_err = 0;
int ret_val;
- /* Check the parameters correctness */
+ if (p_iser_conn == NULL) {
+ printk(KERN_ERR PFX "NULL conn handle\n");
+ iser_err = -EINVAL;
+ goto send_control_error;
+ }
if (p_ctrl_pdu == NULL) {
printk(KERN_ERR PFX "NULL control PDU descriptor\n");
- iser_ret = ISER_ILLEGAL_PARAM;
+ iser_err = -EINVAL;
goto send_control_error;
}
p_bhs = p_ctrl_pdu->p_bhs;
if (p_bhs == NULL) {
printk(KERN_ERR PFX "NULL BHS in control PDU
descriptor\n");
- iser_ret = ISER_ILLEGAL_PARAM;
+ iser_err = -EINVAL;
goto send_control_error;
}
- /* Look up the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
-
- if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX "Failed to find conn, iscsi_conn_h:
%lX\n",
- (unsigned long)iscsi_conn_h);
- iser_ret = ISER_INVALID_CONN;
- goto send_control_error;
- }
if (atomic_read(&p_iser_conn->state) != ISER_CONN_UP) {
- printk(KERN_ERR PFX
- "Failed to send_control as conn is not up, "
- "iscsi_conn_h: %lX, p_conn: 0x%p\n",
- (unsigned long)iscsi_conn_h, p_iser_conn);
+ printk(KERN_ERR PFX "Failed to send, conn: 0x%p is not
up\n",
+ p_iser_conn);
p_iser_conn = NULL; /* Inhibits conn shutdown */
- iser_ret = ISER_FAILURE;
+ iser_err = -EPERM;
goto send_control_error;
}
@@ -491,7 +356,7 @@
if (p_send_dto == NULL) {
printk(KERN_ERR PFX "Failed to create send DTO, conn:
0x%p\n",
p_iser_conn);
- iser_ret = ISER_FAILURE;
+ iser_err = -ENOMEM;
goto send_control_error;
}
@@ -509,7 +374,7 @@
/* Retrieve ExpectedDataTransferLength from
the Command BHS */
- edtl =
ntohl(p_bhs->dword.other[ISCSI_CMD_FIELD_EDTL]);
+ edtl =
ntohl(p_bhs->dword.other[ISCSI_CMD_F_EDTL]);
/* Allocate new task descriptor */
p_iser_task = iser_task_alloc(p_iser_conn, itt);
@@ -517,7 +382,7 @@
printk(KERN_ERR PFX
"Failed to alloc iser task, conn:
"
"0x%p, itt: %d\n", p_iser_conn,
itt);
- iser_ret = ISER_FAILURE;
+ iser_err = -ENOMEM;
goto send_control_error;
}
p_send_dto->p_task = p_iser_task;
@@ -532,11 +397,11 @@
edtl,
p_iser_header);
if (ret_val) {
- iser_ret = ISER_FAILURE;
+ iser_err = -EINVAL;
goto send_control_error;
}
- }
- /* read cmd */
+ } /* read cmd */
+
if
(IS_SET_ISCSI_FLAG_WRITE_CMD(p_bhs->byte.flags)) {
ret_val =
iser_prepare_write_cmd(p_iser_task,
p_ctrl_pdu,
@@ -544,10 +409,10 @@
edtl,
p_iser_header);
if (ret_val) {
- iser_ret = ISER_FAILURE;
+ iser_err = -EINVAL;
goto send_control_error;
}
- } /* write cmd */
+ } /* write cmd */
}
break; /* ISCSI_OP_SCSI_CMD */
@@ -557,15 +422,14 @@
}
/* Retrive BufferOffset from Data-OUT BHS */
- buf_offset =
- ntohl(p_ctrl_pdu->p_bhs->
- dword.other[ISCSI_DATA_OUT_FIELD_OFFSET]);
+ buf_offset = ntohl(
+
p_ctrl_pdu->p_bhs->dword.other[ISCSI_DOUT_F_OFFSET]);
/* Find task in the hash */
p_iser_task = hash_find_iser_task(p_iser_conn, itt);
if (p_iser_task == NULL) {
printk(KERN_ERR PFX "Task not found, itt=%d\n",
itt);
- iser_ret = ISER_INVALID_ITT;
+ iser_err = -EINVAL;
goto send_control_error;
}
if (!p_iser_task->dir[ISER_DIR_OUT]) {
@@ -589,7 +453,7 @@
"len (%ld), itt=%d\n",
buf_offset, data_seg_len,
p_iser_task->data_len[ISER_DIR_OUT],
itt);
- iser_ret = ISER_ILLEGAL_PARAM;
+ iser_err = -EINVAL;
goto send_control_error;
}
@@ -615,29 +479,22 @@
/* Allocate data regd buffer and copy the user
data */
iser_dto_copy_send_data(p_send_dto,
&p_ctrl_pdu->data.tx.buf);
-
- /* We compare the actual buf size (total_buf_sz)
- * to the dsl in the BHS (data_seg_len).
- * We assume that padding (up to 4 bytes)
- * may be used
- */
}
break;
default:
printk(KERN_ERR PFX "Unsupported opcode = %d\n",
opcode);
- iser_ret = ISER_ILLEGAL_PARAM;
+ iser_err = -EINVAL;
goto send_control_error;
break;
+ }
- } /* switch p_bhs->byte.opcode */
-
/* Post-Receive buffer for a reply PDU */
/* ToDo: account for different types of NOP-OUT (req, resp) */
if (opcode != ISCSI_OP_DATA_OUT) {
if (iser_post_receive_control(p_iser_conn) != 0) {
printk(KERN_ERR PFX "post_rcv_buff failed!\n");
- iser_ret = ISER_FAILURE;
+ iser_err = -ENOMEM;
/* ISER_ERROR: 12.1.3.1 (insufficient res) */
goto send_control_error;
}
@@ -653,11 +510,11 @@
}
if (iser_start_dto(p_send_dto) != 0) {
printk(KERN_ERR PFX "Failed to start send DTO\n");
- iser_ret = ISER_FAILURE;
+ iser_err = -EIO;
goto send_control_error;
}
- return ISER_SUCCESS;
+ return 0;
send_control_error:
if (p_send_dto != NULL) {
@@ -671,14 +528,19 @@
iser_conn_async_terminate(p_iser_conn);
}
- return iser_ret;
+ return iser_err;
} /* iser_send_control */
+/**
+ * iser_rcv_dto_task: task-related recv DTO completion
+ *
+ */
void
-iser_task_rcv_dto(struct iser_dto *p_dto,
+iser_rcv_dto_task(struct iser_dto *p_dto,
struct iser_connection *p_iser_conn,
- int itt, unsigned char opcode)
+ int itt,
+ unsigned char opcode)
{
struct iser_task *p_iser_task = NULL;
unsigned int rx_count;
@@ -693,11 +555,9 @@
return;
p_iser_task = hash_find_iser_task(p_iser_conn, itt);
-
if (p_iser_task == NULL)
return;
- /* The rcv buffer belongs now to the task */
p_dto->p_task = p_iser_task;
/* Account for the used up posted recv buffer */
iser_task_recvd_pdu_count_inc(p_iser_task);
@@ -716,18 +576,21 @@
itt, rx_count);
}
iser_task_ctrl_notify_count_inc(p_iser_task);
-}
+} /* iser_rcv_dto_task */
-void iser_dto_rcv(struct iser_dto *p_dto, unsigned long dto_xfer_len)
+/**
+ * iser_rcv_dto_completion - recv DTO completion
+ *
+ */
+void iser_rcv_dto_completion(struct iser_dto *p_dto,
+ unsigned long dto_xfer_len)
{
+ struct iser_connection *p_iser_conn = p_dto->p_conn;
union iser_pdu_bhs *p_bhs;
- struct iser_connection *p_iser_conn;
unsigned char opcode;
unsigned int itt;
- p_iser_conn = p_dto->p_conn;
-
- /* Number of posted receive buffers has decreased by one */
+ /* Number of posted receive buffers has decreased by one */
atomic_dec(&p_iser_conn->post_recv_buf_count);
/* Create descriptor for the received PDU */
@@ -739,24 +602,24 @@
/* Retrieve opcode */
opcode = p_bhs->byte.opcode & ISCSI_OPCODE_MASK;
- iser_task_rcv_dto(p_dto, p_iser_conn, itt, opcode);
+ iser_rcv_dto_task(p_dto, p_iser_conn, itt, opcode);
/* Notify iSCSI layer */
iser_conn_add_recv_ctrl_dto(p_iser_conn, p_dto);
ITRACE(ISER_TRACE_CTRL_NOTIFY,
"Control notify, DTO:0x%p, as PDU:0x%p\n",
p_dto, &p_dto->as.recv.pdu);
- p_iser_conn->p_entity->api_cb.
- control_notify(p_iser_conn->iscsi_conn_h,
&p_dto->as.recv.pdu);
-}
-void iser_dto_snd(struct iser_dto *p_dto, unsigned long dto_xfer_len)
+ ig.api_cb.control_notify(p_iser_conn->iscsi_conn_h,
+ &p_dto->as.recv.pdu);
+} /* iser_rcv_dto_completion */
+
+void iser_snd_dto_completion(struct iser_dto *p_dto,
+ unsigned long dto_xfer_len)
{
+ struct iser_connection *p_iser_conn = p_dto->p_conn;
struct iser_task *p_iser_task = NULL;
- struct iser_connection *p_iser_conn;
- p_iser_conn = p_dto->p_conn;
-
ITRACE(ISER_TRACE_SEND_DTO, "Initiator, Data sent p_dto=0x%p\n",
p_dto);
/* One posted send DTO less */
@@ -773,724 +636,26 @@
iser_task_post_send_count_dec_and_test(p_iser_task)) {
iser_task_free(p_iser_task);
}
-}
+} /* iser_snd_dto_completion */
/**
* iser_dto_completion - Handle a successful
* DTO completion at Initiator
*
- * returns 0 on success, -1 on failure
*/
-int iser_dto_completion(struct iser_dto *p_dto, unsigned long
dto_xfer_len)
+void iser_dto_completion(struct iser_dto *p_dto,
+ unsigned long dto_xfer_len)
{
-
- if (p_dto->p_conn == NULL) {
- IPANIC("NULL conn in p_dto: 0x%p\n", p_dto);
- }
-
switch (p_dto->type) {
case ISER_DTO_RCV:
- iser_dto_rcv(p_dto, dto_xfer_len);
+ iser_rcv_dto_completion(p_dto, dto_xfer_len);
break;
- case ISER_DTO_SEND: /* handle sent messages */
- iser_dto_snd(p_dto, dto_xfer_len);
+ case ISER_DTO_SEND:
+ iser_snd_dto_completion(p_dto, dto_xfer_len);
+ break;
default:
IPANIC("Illegal initiator iSER DTO type: %d\n",
p_dto->type);
break;
}
-
- return 0;
} /* iser_dto_completion */
-/**
- * iser_alloc_conn_res - iSER API. Implements
- * Allocate_Connection_Resources primitive.
- *
- * Performs exchange of API functions. Allocates additional receive
- * buffers. Performs static memory registration if instructed to do
so.
- *
- * returns iSER status (ISER_SUCCESS, ISER_FAILURE, ISER_INVALID_CONN)
- */
-iser_status iser_alloc_conn_res(void *iscsi_conn_h,
- struct iser_conn_res * conn_res)
-{
- struct iser_entity *p_entity;
- struct iser_connection *p_iser_conn;
- int uncache_buf_pools = 0;
- iser_status iser_ret = ISER_SUCCESS;
- char bufpool_name[ISER_BUF_POOL_NAME_SIZE];
-
- p_entity = (struct iser_entity *)conn_res->api_h;
- if (p_entity == NULL) {
- printk(KERN_ERR PFX "NULL API handle\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto alloc_conn_res_exit;
- }
-
- if (conn_res->max_recv_pdu_sz > 256 * 1024) {
- printk(KERN_ERR PFX "max_recv_pdu_sz too large\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto alloc_conn_res_exit;
- }
-
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
- if (p_iser_conn == NULL) {
- printk(KERN_ERR PFX
- "Could not find iSER conn for iscsi_h = 0x%p\n",
- iscsi_conn_h);
- iser_ret = ISER_INVALID_CONN;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto alloc_conn_res_exit;
- }
- if (p_iser_conn->p_entity != p_entity) {
- printk(KERN_ERR PFX "Entity in conn_res does not match "
- "conn for iscsi_h = 0x%p\n",
p_iser_conn->iscsi_conn_h);
- iser_ret = ISER_ILLEGAL_PARAM;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto alloc_conn_res_exit;
- }
-
- p_iser_conn->max_outstand_cmds = conn_res->max_outstand_cmds;
-
- if (p_iser_conn->param.InitiatorRecvDataSegmentLength ==
- defaultInitiatorRecvDataSegmentLength) {
- p_iser_conn->param.InitiatorRecvDataSegmentLength =
- conn_res->max_recv_pdu_sz;
- } else if (p_iser_conn->param.InitiatorRecvDataSegmentLength !=
- conn_res->max_recv_pdu_sz) {
- printk(KERN_ERR PFX
- "max_recv_pdu_sz(%d) does not match non-default
value "
- "of InitiatorRecvDataSegmentLength(%d)\n",
- conn_res->max_recv_pdu_sz,
-
p_iser_conn->param.InitiatorRecvDataSegmentLength);
- iser_ret = ISER_ILLEGAL_PARAM;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto alloc_conn_res_exit;
- }
-
- p_iser_conn->alloc_post_recv_bufs_num = ISER_EP_AVG_POST_RECV +
2;
- p_iser_conn->initial_post_recv_bufs_num = ISER_INITIAL_POST_RECV
+ 2;
-
- ITRACE(ISER_TRACE_CONN,
- "Max outst. cmds: %d, Allocate post recv bufs:"
- "%d, Initially post: %d\n",
- p_iser_conn->max_outstand_cmds,
- p_iser_conn->alloc_post_recv_bufs_num,
- p_iser_conn->initial_post_recv_bufs_num);
-
- /* Allocate post-receive buffers for the full-featured phase */
- snprintf(bufpool_name, ISER_BUF_POOL_NAME_SIZE,
"%s-%s-post-recv",
- p_entity->provider_name, p_iser_conn->name);
-
- p_iser_conn->spare_post_recv_pool =
- iser_small_bpool_create(p_iser_conn->p_adaptor,
- bufpool_name,
- 128,
-
p_iser_conn->alloc_post_recv_bufs_num,
- uncache_buf_pools);
- if (p_iser_conn->spare_post_recv_pool == NULL) {
- printk(KERN_ERR PFX "Failed to alloc the post receive
buffer "
- "pool for conn = 0x%p, iscsi_h = 0x%p\n",
- p_iser_conn, p_iser_conn->iscsi_conn_h);
- iser_ret = ISER_ILLEGAL_PARAM;
- }
-
- /* Allocate send-data buffers for the full-featured phase */
- snprintf(bufpool_name, ISER_BUF_POOL_NAME_SIZE,
"%s-%s-send-data",
- p_entity->provider_name, p_iser_conn->name);
-
- /* ToDo: TargetMaxRecvDSL */
- p_iser_conn->spare_send_data_pool =
- iser_large_bpool_create(p_iser_conn->p_adaptor,
bufpool_name,
- 8 * 1024,
- ISER_MAX_NOP_OUT +
ISER_MAX_TASK_MGT_REQ,
- uncache_buf_pools);
- if (p_iser_conn->spare_send_data_pool == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc the send data buffer pool "
- "for conn = 0x%p, iscsi_h = 0x%p\n", p_iser_conn,
- p_iser_conn->iscsi_conn_h);
- iser_ret = ISER_ILLEGAL_PARAM;
- }
-
- alloc_conn_res_exit:
- return iser_ret;
-} /* iser_alloc_conn_res */
-
-/**
- * iser_enable_datamover - iSER API. Implements
- * Enable_Datamover primitive.
- *
- * Posts receive buffers.
- * Upgrades the conn to RDMA-assisted.
- *
- * returns iSER status (ISER_SUCCESS, ISER_FAILURE, ISER_INVALID_CONN)
- */
-iser_status iser_enable_datamover(void *iscsi_conn_h, void *tport_conn)
-{
- iser_status iser_ret = ISER_SUCCESS;
- struct iser_connection *p_iser_conn;
- int i;
-
- /* Find the conn */
- p_iser_conn = hash_find_iser_conn(iscsi_conn_h);
- if (p_iser_conn == NULL) {
- iser_ret = ISER_INVALID_CONN;
- /* ISER_ERROR: 12.1.3.1 (insufficient res) */
- goto enable_data_mover_exit;
- }
-
- /* Check that there is no posted recv or send buffers left - */
- /* they must be consumed during the login phase */
- if (atomic_read(&p_iser_conn->post_recv_buf_count) != 0) {
- IPANIC
- ("Number of currently posted receive buffers
non-zero\n");
- }
- if (atomic_read(&p_iser_conn->post_send_buf_count) != 0) {
- IPANIC("Number of currently posted send buffers
non-zero\n");
- }
- /* If a buffer pool has been allocd for loginphase, destroy it
*/
- if (p_iser_conn->post_recv_pool != NULL) {
- iser_bpool_destroy(p_iser_conn->post_recv_pool);
- }
-
- /* Switch to the main post-recv buffer pool */
- p_iser_conn->post_recv_pool = p_iser_conn->spare_post_recv_pool;
- p_iser_conn->spare_post_recv_pool = NULL;
-
- /* Switch to the main send-data buffer pool */
- p_iser_conn->send_data_pool = p_iser_conn->spare_send_data_pool;
- p_iser_conn->spare_send_data_pool = NULL;
-
- /* Initial Post-Receive buffers */
- for (i = 0; i < p_iser_conn->initial_post_recv_bufs_num; i++) {
- if (iser_post_receive_control(p_iser_conn) != 0) {
- printk(KERN_ERR PFX "Failed to post recv
buffers\n");
- /* ToDo: recovery? */
- iser_ret = ISER_FAILURE;
- goto enable_data_mover_exit;
- }
- }
- ITRACE(ISER_TRACE_CONN, "Allocated %d post recv bufs\n", i);
-
- enable_data_mover_exit:
- return iser_ret;
-} /* iser_enable_datamover */
-
-/* -- from ig.c */
-/**
- * iser_adaptor_init - Initializes iSER adaptor structure.
- *
- *
- * Creates adaptor-scope objects (Interface Adaptor, Protection Zone,
- * Public Service Points).
- *
- * returns 0 on success, -1 on failure
- */
-int iser_adaptor_init(struct iser_adaptor *p_iser_adaptor, char *name)
-{
- if (p_iser_adaptor == NULL)
- return -1;
-
- memset(p_iser_adaptor, 0, sizeof(struct iser_adaptor));
- ITRACE(ISER_TRACE_CONN, "memset at 0x%p to 0x%lX\n",
- p_iser_adaptor,
- ((long)p_iser_adaptor) + sizeof(struct iser_adaptor));
-
- /* Initialize waiting queue for the event handler thread */
- init_waitqueue_head(&p_iser_adaptor->dat_events_wait_q);
- init_waitqueue_head(&p_iser_adaptor->connect_wait_q);
-
- /* Initialize list of conns */
- spin_lock_init(&p_iser_adaptor->conn_lock);
- INIT_LIST_HEAD(&p_iser_adaptor->conn_list);
-
- /* Create IA, PZ, EVD */
- if (iser_create_ia_pz_evd(p_iser_adaptor) != 0) {
- return -1;
- }
-
- /* Allocate pool of pre-registered iSER headers */
- p_iser_adaptor->header_pool =
- iser_small_bpool_create(p_iser_adaptor, "headers",
- ISER_TOTAL_HEADERS_LEN, 0, 1);
- if (p_iser_adaptor->header_pool == NULL) {
- iser_adaptor_release(p_iser_adaptor);
- return -1;
- }
-
- /* Initizlize the pre-registered buffers cache */
- iser_init_regd_buff_cache(p_iser_adaptor);
-
- /* Start the event thread */
- p_iser_adaptor->terminate_thread = 0;
- init_MUTEX_LOCKED(&p_iser_adaptor->startstop_sem);
- p_iser_adaptor->event_thrd_pid =
- kernel_thread(iser_event_handler_thread,
- p_iser_adaptor,
- CLONE_VM | CLONE_FS | CLONE_FILES |
CLONE_SIGHAND);
-
- if (p_iser_adaptor->event_thrd_pid <= 0) {
- printk(KERN_ERR PFX "Failed to start event kernel
thread\n");
- iser_adaptor_release(p_iser_adaptor);
- return -1;
- }
- printk("p1\n");
- /* wait for the event thread to start */
- down(&p_iser_adaptor->startstop_sem);
-
- return 0;
-} /* iser_adaptor_init */
-
-/**
- * iser_adaptor_release - Releases all adaptor-related res.
- *
- * returns 0 on success, -1 on failure
- */
-int iser_adaptor_release(struct iser_adaptor *p_iser_adaptor)
-{
- struct iser_connection *p_iser_conn;
-
- /* Free all conns and associated objects,
- must be done before freeing adaptor objects */
- while (!list_empty(&p_iser_adaptor->conn_list)) {
- p_iser_conn = list_entry(p_iser_adaptor->conn_list.next,
- struct iser_connection,
adaptor_list);
- /* Connection should be shut down before releasing res
*/
- iser_conn_sync_terminate(p_iser_conn);
- iser_conn_free(p_iser_conn);
- }
- /* Release buffer pool and unregister its memory */
- if (p_iser_adaptor->header_pool != NULL) {
- iser_bpool_destroy(p_iser_adaptor->header_pool);
- p_iser_adaptor->header_pool = NULL;
- }
-
- if (iser_release_regd_buff_cache(p_iser_adaptor) != 0) {
- ITRACE(ISER_TRACE_ERRORS,
- "iser_release_regd_buff_cache failed\n");
- }
-
- /* Free adaptor-related objects */
- if (iser_free_ia_pz_evd(p_iser_adaptor) != 0) {
- return -1;
- }
-
- /* DAN: kill event thread (if exists) */
- if (p_iser_adaptor->event_thrd_pid > 0) {
- ITRACE(ISER_TRACE_EVENT_THREAD,
- "start terminating event thread\n");
- lock_kernel();
- init_MUTEX_LOCKED(&p_iser_adaptor->startstop_sem);
- mb();
- p_iser_adaptor->terminate_thread = 1;
- mb();
- kill_proc(p_iser_adaptor->event_thrd_pid, SIGKILL, 1);
- ITRACE(ISER_TRACE_EVENT_THREAD,
- "waiting for event thread to terminate down\n");
- down(&p_iser_adaptor->startstop_sem);
- unlock_kernel();
- ITRACE(ISER_TRACE_EVENT_THREAD, "event thread
terminated\n");
- }
-
- return 0;
-} /* iser_adaptor_release */
-
-/**
- * iser_adaptor_add_conn - Adds a conn to adaptor
- */
-void iser_adaptor_add_conn(struct iser_adaptor *p_iser_adaptor,
- struct iser_connection *p_iser_conn)
-{
- p_iser_conn->p_adaptor = p_iser_adaptor;
- spin_lock(&p_iser_adaptor->conn_lock);
- list_add(&p_iser_conn->adaptor_list,
&p_iser_adaptor->conn_list);
- spin_unlock(&p_iser_adaptor->conn_lock);
-
-} /* iser_adaptor_add_conn */
-
-/**
- * iser_adaptor_find_conn - Adds a conn to adaptor
- *
- * returns 0 on success, -1 on failure
- */
-struct iser_connection *iser_adaptor_find_conn(struct iser_adaptor
- *p_iser_adaptor,
- void *ep_handle)
-{
-
- struct iser_connection *p_iser_conn = NULL;
- struct list_head *p_list;
-
- spin_lock(&p_iser_adaptor->conn_lock);
- p_list = p_iser_adaptor->conn_list.next;
- while (p_list != &p_iser_adaptor->conn_list) {
- p_iser_conn = list_entry(p_list, struct iser_connection,
- adaptor_list);
- if (((void *)p_iser_conn->ep_handle) == ep_handle)
- break;
- p_iser_conn = NULL;
- p_list = p_list->next;
- }
- spin_unlock(&p_iser_adaptor->conn_lock);
-
- return p_iser_conn;
-} /* iser_adaptor_find_conn */
-
-/**
- * iser_adaptor_remove_conn - Removes a conn from adaptor
- */
-void iser_adaptor_remove_conn(struct iser_connection *p_iser_conn)
-{
- struct iser_adaptor *p_iser_adaptor;
-
- if (!list_empty(&p_iser_conn->adaptor_list)) {
- p_iser_adaptor = p_iser_conn->p_adaptor;
- if (p_iser_adaptor == NULL) {
- IPANIC("NULL adaptor in conn: 0x%p\n",
p_iser_conn);
- }
- spin_lock(&p_iser_adaptor->conn_lock);
- list_del(&p_iser_conn->adaptor_list);
- spin_unlock(&p_iser_adaptor->conn_lock);
- }
-
-} /* iser_adaptor_remove_conn */
-
-/**
- * iser_entity_add_conn - Adds a conn to entity
- */
-void iser_entity_add_conn(struct iser_entity *p_entity,
- struct iser_connection *p_iser_conn)
-{
- p_iser_conn->p_entity = p_entity;
- spin_lock(&p_entity->conn_lock);
- list_add(&p_iser_conn->entity_list, &p_entity->conn_list);
- spin_unlock(&p_entity->conn_lock);
-
-} /* iser_entity_add_conn */
-
-/**
- * iser_entity_remove_conn - Removes a conn from adaptor
- */
-void iser_entity_remove_conn(struct iser_connection *p_iser_conn)
-{
- struct iser_entity *p_entity;
-
- if (!list_empty(&p_iser_conn->entity_list)) {
- p_entity = p_iser_conn->p_entity;
- if (p_entity == NULL) {
- IPANIC("NULL entity in conn: 0x%p\n",
p_iser_conn);
- }
- spin_lock(&p_entity->conn_lock);
- list_del(&p_iser_conn->entity_list);
- spin_unlock(&p_entity->conn_lock);
- }
-} /* iser_entity_remove_conn */
-
-/**
- * ig_init - Initializes the global iSER context structure.
- *
- * returns 0 on success, -1 on failure
- */
-int ig_init()
-{
- memset(&ig, 0, sizeof(struct iser_global));
-
- /* Allocate adaptors; currently single adaptor */
- ig.num_adaptors = 1;
- if (iser_adaptor_init(&ig.adaptor[0], "InfiniHost0") != 0) {
- printk(KERN_ERR PFX "initializing iser failed!\n");
- iser_adaptor_release(&ig.adaptor[0]);
- return -1;
- }
-
- /* Start with no entities defined */
- ig.num_entities = 0;
-
- /* Allocate kmem_cache for iser_connection structures */
- ig.conn_mem_cache =
- kmem_cache_create("iser_conn", sizeof(struct
iser_connection), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ig.conn_mem_cache == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc conn_mem_cache, name:
iser_conn\n");
- return -1;
- }
-
- /* Allocate kmem_cache for iser_task structures */
- ig.task_mem_cache =
- kmem_cache_create("iser_task", sizeof(struct iser_task), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
-
- if (ig.task_mem_cache == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc task_mem_cache, name:
iser_task\n");
- return -1;
- }
-
- /* Allocate kmem_cache for iser_dto structures, for post-recv */
- ig.recv_dto_mem_cache =
- kmem_cache_create("iser_recv_dto",
- sizeof(struct iser_dto),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ig.recv_dto_mem_cache == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc recv_dto_mem_cache, "
- "name: iser_recv_dto\n");
- return -1;
- }
-
- /* Allocate kmem_cache for iser_dto structures, for send */
- ig.send_dto_mem_cache =
- kmem_cache_create("iser_send_dto",
- sizeof(struct iser_dto),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ig.send_dto_mem_cache == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc send_dto_mem_cache,
iser_send_dto\n");
- return -1;
- }
-
- /* Allocate kmem_cache for iser_regd_buf structures */
- ig.regd_buf_mem_cache =
- kmem_cache_create("iser_regbuf",
- sizeof(struct iser_regd_buf),
- 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (ig.regd_buf_mem_cache == NULL) {
- printk(KERN_ERR PFX
- "Failed to alloc regd_buf_mem_cache, "
- "name: iser_regbuf\n");
- return -1;
- }
-
- /* Initialize task hash table */
- hash_init(&ig.task_hash);
- /* Initialize conns hash table */
- hash_init(&ig.conn_hash);
-
- return 0;
-} /* ig_init */
-
-/**
- * ig_release - Releases all res through
- * the global iSER context structure.
- *
- * returns 0 on success, -1 on failure
- */
-int ig_release()
-{
-
- /* Are all entities released? */
- if (ig.num_entities > 0) {
- printk(KERN_ERR PFX
- "Some entities did not unregister. "
- "Can't release module.\n");
- return -1;
- }
- /* Release all adaptors */
- iser_adaptor_release(&ig.adaptor[0]);
- ig.num_adaptors = 0;
-
- if (ig.conn_mem_cache != NULL) {
- kmem_cache_destroy(ig.conn_mem_cache);
- ig.conn_mem_cache = NULL;
- }
-
- if (ig.task_mem_cache != NULL) {
- kmem_cache_destroy(ig.task_mem_cache);
- ig.task_mem_cache = NULL;
- }
-
- if (ig.recv_dto_mem_cache != NULL) {
- kmem_cache_destroy(ig.recv_dto_mem_cache);
- ig.recv_dto_mem_cache = NULL;
- }
-
- if (ig.send_dto_mem_cache != NULL) {
- kmem_cache_destroy(ig.send_dto_mem_cache);
- ig.send_dto_mem_cache = NULL;
- }
-
- if (ig.regd_buf_mem_cache != NULL) {
- kmem_cache_destroy(ig.regd_buf_mem_cache);
- ig.regd_buf_mem_cache = NULL;
- }
-
- return 0;
-} /* ig_release */
-
-/**
- * iser_find_regd_entity - Look for an iSCSI entity
- * using its type and provider name as the key.
- *
- * returns entity descriptor if found, NULL - if not found
- */
-struct iser_entity *iser_find_regd_entity(char *provider_name)
-{
- struct iser_entity *p_entity = NULL;
- int i;
-
- for (i = 0; i < ISER_MAX_ENTITIES; i++) {
- if (ig.entity[i].registered &&
- strncmp(provider_name,
- ig.entity[i].provider_name, 64) == 0) {
- p_entity = &ig.entity[i];
- break;
- }
- }
-
- return p_entity;
-} /* iser_find_regd_entity */
-
-/**
- * iser_find_free_entity - Look for a free entity
- * descriptor within the global context struct.
- *
- * returns index into the entities array if found, -1 if not found
- */
-
-static int iser_find_free_entity(void)
-{
- int i;
-
- for (i = 0; i < ISER_MAX_ENTITIES; i++) {
- if (!ig.entity[i].registered)
- return i;
- }
- /* no free entities */
- return -1;
-} /* iser_find_free_entity */
-
-/**
- * iser_api_register - register with iser extended api
- *
- * returns iSER status
- */
-iser_status
-iser_api_register(char *provider_name,
- struct iser_api * api,
- struct iser_api_cb * api_cb, void **p_api_h)
-{
- iser_status iser_ret = ISER_SUCCESS;
- struct iser_entity *p_entity;
- int entity_num;
-
- if (p_api_h == NULL) {
- printk(KERN_ERR PFX "NULL *p_api_h \n");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_register_exit;
- }
- *p_api_h = ISER_INVALID_API_H;
-
- if (provider_name == NULL) {
- printk(KERN_ERR PFX "NULL *provider_name\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_register_exit;
- }
- if (api == NULL) {
- printk(KERN_ERR PFX "NULL *api structure\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_register_exit;
- }
- if (api_cb == NULL) {
- printk(KERN_ERR PFX "NULL *api_cb structure\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_register_exit;
- }
-
- api->conn_establish = iser_conn_establish;
- api->send_control = iser_send_control;
- api->release_control = iser_release_control;
- api->alloc_conn_res = iser_alloc_conn_res;
- api->notice_key_values = iser_notice_key_values;
- api->enable_datamover = iser_enable_datamover;
- api->conn_terminate = iser_connectionerminate;
- api->dealloc_conn_res = iser_dealloc_conn_res;
- api->dealloc_task_res = iser_dealloc_task_res;
-
- p_entity = iser_find_regd_entity(provider_name);
- if (p_entity != NULL) {
- printk(KERN_ERR PFX "This entity is already registered:
%s\n",
- provider_name);
- iser_ret = ISER_FAILURE;
- goto api_register_exit;
- }
- entity_num = iser_find_free_entity();
- if (entity_num < 0) {
- printk(KERN_ERR PFX
- "Failed to find a free entity entry for: %s\n",
- provider_name);
- iser_ret = ISER_FAILURE;
- goto api_register_exit;
- }
- p_entity = &ig.entity[entity_num];
- memset(p_entity, 0, sizeof(struct iser_entity));
-
- p_entity->api_cb.conn_establish_notify =
api_cb->conn_establish_notify;
- p_entity->api_cb.conn_terminate_notify =
api_cb->conn_terminate_notify;
- p_entity->api_cb.control_notify = api_cb->control_notify;
- p_entity->registered = 1;
- *p_api_h = (void *)p_entity;
-
- ig.num_entities++;
- strncpy(p_entity->provider_name, provider_name, 64);
- spin_lock_init(&p_entity->conn_lock);
- INIT_LIST_HEAD(&p_entity->conn_list);
-
- api_register_exit:
- return iser_ret;
-} /* iser_api_register */
-
-/**
- * iser_api_unregister - Unregister API entity
- *
- * returns iSER status
- */
-iser_status iser_api_unregister(void *api_h)
-{
- iser_status iser_ret = ISER_SUCCESS;
- struct iser_entity *p_entity;
- struct iser_connection *p_iser_conn;
-
- if (api_h == NULL || api_h == ISER_INVALID_API_H) {
- printk(KERN_ERR PFX "Invalid API registration handle");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_unregister_exit;
- }
- p_entity = (struct iser_entity *)api_h;
-
- if (!p_entity->registered) {
- printk(KERN_ERR PFX
- "Trying to deregister unregistered entity\n");
- iser_ret = ISER_ILLEGAL_PARAM;
- goto api_unregister_exit;
- }
-
- /* Terminate and release all conns on that entity */
- spin_lock(&p_entity->conn_lock);
- while (!list_empty(&p_entity->conn_list)) {
- p_iser_conn = list_entry(p_entity->conn_list.next,
- struct iser_connection,
entity_list);
- spin_unlock(&p_entity->conn_lock);
- /* ToDo: we'll have to wait - is it OK? */
- iser_conn_sync_terminate(p_iser_conn);
- spin_lock(&p_entity->conn_lock);
- }
- spin_unlock(&p_entity->conn_lock);
-
- p_entity->registered = 0;
- if (ig.num_entities > 0) {
- ig.num_entities--;
- } else {
- IPANIC("Zero registered entities when "
- "trying to unregister one\n");
- }
-
- api_unregister_exit:
- return iser_ret;
-} /* iser_api_unregister */
-
-EXPORT_SYMBOL(iser_api_unregister);
-EXPORT_SYMBOL(iser_api_register);
Index: iser_conn.h
===================================================================
--- iser_conn.h (revision 3404)
+++ iser_conn.h (working copy)
@@ -36,40 +36,42 @@
#include "iser.h"
-/* iSER API Functions */
+/* adaptor-related */
+int iser_adaptor_init(struct iser_adaptor *p_iser_adaptor, char *name);
+int iser_adaptor_release(struct iser_adaptor *p_iser_adaptor);
+struct iser_connection *iser_adaptor_find_conn(
+ struct iser_adaptor *p_iser_adaptor, void *ep_handle);
-iser_status iser_notice_key_values(void *conn_h, char *key, char
*value);
-iser_status iser_connectionerminate(void *iscsi_conn_h);
+/* iSER connection related API */
+int iser_conn_bind(void *iscsi_conn_h,
+ struct socket *sock,
+ void **iser_conn_h);
+int iser_conn_enable_rdma(void *iser_conn_h,
+ struct iser_conn_res *conn_res);
+int iser_notice_key_values(void *iser_conn_h, char *key, char *value);
+int iser_release_control(void *iser_conn_h,
+ struct iser_recv_pdu *p_ctrl_pdu);
+int iser_conn_term(void *iser_conn_h);
+int iser_dealloc_conn_res(void *iser_conn_h);
-iser_status iser_dealloc_conn_res(void *iscsi_conn_h);
-
-/* Extension */
-iser_status iser_release_control(void *iscsi_conn_h,
- struct iser_recv_pdu *p_ctrl_pdu);
-
-/* Internal iSER Functions */
-
-struct iser_connection *iser_conn_alloc(void);
-void iser_conn_free(struct iser_connection *iser_conn);
-
+/* internal connection handling */
+void iser_conn_init(struct iser_connection *p_iser_conn);
+int iser_conn_establish(struct iser_connection *p_iser_conn,
+ struct sockaddr_in *dst_addr,
+ struct sockaddr_in *src_addr);
+void iser_conn_release(struct iser_connection *p_iser_conn);
void iser_conn_add_task(struct iser_connection *p_iser_conn,
struct iser_task *p_iser_task);
-
void iser_conn_delete_task(struct iser_connection *p_iser_conn,
struct iser_task *p_iser_task);
-
void iser_conn_add_recv_ctrl_dto(struct iser_connection *p_iser_conn,
struct iser_dto *p_ctrl_dto);
-
void iser_conn_delete_recv_ctrl_dto(struct iser_connection
*p_iser_conn,
struct iser_dto *p_ctrl_dto);
-
-int iser_complete_conn_termination(struct iser_connection
*p_iser_conn);
-
int iser_post_receive_control(struct iser_connection *p_iser_conn);
char *iser_conn_get_state_name(struct iser_connection *p_iser_conn);
-
int iser_conn_async_terminate(struct iser_connection *p_iser_conn);
int iser_conn_sync_terminate(struct iser_connection *p_iser_conn);
+int iser_complete_conn_termination(struct iser_connection
*p_iser_conn);
#endif /* __ISER_CONN_H__ */
Index: iser_task.c
===================================================================
--- iser_task.c (revision 3404)
+++ iser_task.c (working copy)
@@ -361,15 +361,23 @@
/**
* iser_dealloc_task_res - Deallocs task res
*/
-iser_status iser_dealloc_task_res(void *conn_h, unsigned int itt)
+int iser_dealloc_task_res(void *iser_conn_h, unsigned int itt)
{
- struct iser_connection *p_iser_conn;
+ struct iser_connection *p_iser_conn = iser_conn_h;
struct iser_task *p_iser_task;
+ int iser_err = 0;
- p_iser_conn = hash_find_iser_conn(conn_h);
- p_iser_task = hash_find_iser_task(p_iser_conn, itt);
-
- iser_task_free(p_iser_task);
-
- return ISER_SUCCESS;
+ if (p_iser_conn != NULL) {
+ p_iser_task = hash_find_iser_task(p_iser_conn, itt);
+ if (p_iser_task != NULL) {
+ iser_task_free(p_iser_task);
+ }
+ else {
+ iser_err = -EINVAL;
+ }
+ }
+ else {
+ iser_err = -EINVAL;
+ }
+ return iser_err;
} /* iser_dealloc_task_res */
Index: iser_utils.h
===================================================================
--- iser_utils.h (revision 3404)
+++ iser_utils.h (working copy)
@@ -54,66 +54,35 @@
void hash_delete_iser_task(struct iser_task *iser_task);
/*
---------------------------------------------------------------------
- * ISER CONNECTION-SPECIFIC HASH MANAGEMENT
- * ------------------------------------------------------------------
*/
-
-struct iser_connection *hash_find_iser_conn(void *iscsi_conn_h);
-
-void hash_add_iser_conn(struct iser_connection *iser_conn);
-
-void hash_delete_iser_conn(struct iser_connection *iser_conn);
-
-/*
---------------------------------------------------------------------
* BUFFER DESCRIPTORS
* ------------------------------------------------------------------
*/
-unsigned long
-iser_get_data_total_length(struct iser_data_buf *p_data, int skip, int
count);
+unsigned int iser_data_contig_length(struct iser_data_buf *p_data,
+ int skip,
+ uint64_t *start_addr,
+ int *size);
-int
-iser_iovec_virt_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip, int
count);
+unsigned long iser_sg_subset_len(struct iser_data_buf *p_data,
+ int skip_entries,
+ int count_entries);
-int
-iser_sglist_virt_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip, int
count);
-unsigned int
-iser_iovec_contig_length(struct iser_data_buf *p_data,
- int skip, uint64_t * start_addr, int *size);
+int iser_data_convert_to_phys(struct iser_data_buf *p_data,
+ struct iser_phys_mem *p_phys,
+ int skip,
+ int count);
-int
-iser_iovec_phys_copy_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip,
- int count);
-int iser_convert_mem_to_phys(struct iser_data_buf *p_data,
- struct iser_phys_mem *p_phys, int skip,
- int count);
+unsigned int iser_data_aligned_length(struct iser_data_buf *p_data,
+ int skip);
-unsigned int iser_iovec_aligned_length(struct iser_data_buf *p_data,
int skip);
+void iser_data_buf_memcpy(unsigned char *p_dst_buf,
+ struct iser_data_buf *p_src_data,
+ unsigned long *p_total_copied_sz);
-void *iser_phys_to_virt(void *phys_addr);
+void iser_data_desc_dump(struct iser_data_buf *p_data);
-void *iser_page_to_virt(struct page *page);
+struct iser_phys_mem *iser_alloc_phys_desc(struct iser_data_buf
*p_data,
+ int skip,
+ int count);
+void iser_free_phys_desc(struct iser_phys_mem *phys_desc);
-void *iser_iovec_virt_entry_addr(void *p_iovec_virt, int i);
-
-void *iser_iovec_phys_entry_to_virt(void *p_iovec_phys, int i);
-
-void *iser_sglist_entry_to_virt(void *p_sglist, int i);
-
-unsigned long iser_iovec_entry_len(void *p_iovec_arr, int i);
-
-unsigned long iser_sglist_entry_len(void *p_sglist, int i);
-
-void
-iser_data_buf_memcpy(unsigned char *p_dst_buf,
- struct iser_data_buf *p_src_data,
- unsigned long *p_total_copied_sz);
-
-char *iser_data_buf_get_type_name(struct iser_data_buf *p_data);
-
-struct iser_phys_mem *iser_alloc_phys_mem(struct iser_data_buf *p_data,
- int skip, int count);
-void iser_free_phys_mem(struct iser_phys_mem *pmt);
-
#endif /* __ISER_UTILS_H__ */
Index: iser_task.h
===================================================================
--- iser_task.h (revision 3404)
+++ iser_task.h (working copy)
@@ -36,32 +36,20 @@
#include "iser.h"
-/* iSER API Functions */
+int iser_dealloc_task_res(void *conn_h, unsigned int itt);
-iser_status iser_dealloc_task_res(void *conn_h, unsigned int itt);
-/* Internal iSER Functions */
-
struct iser_task *iser_task_alloc(struct iser_connection *iser_conn,
unsigned int itt);
void iser_task_ctrl_notify_count_inc(struct iser_task *p_iser_task);
-
int iser_task_ctrl_notify_count_dec_and_test(struct iser_task
*p_iser_task);
-
void iser_task_post_send_count_inc(struct iser_task *p_iser_task);
-
int iser_task_post_send_count_dec_and_test(struct iser_task
*p_iser_task);
-
void iser_task_recvd_pdu_count_inc(struct iser_task *p_iser_task);
-
int iser_task_recvd_pdu_count_reset(struct iser_task *p_iser_task);
-
-void
-iser_task_set_status(struct iser_task *p_iser_task,
- enum iser_task_status status);
+void iser_task_set_status(struct iser_task *p_iser_task,
+ enum iser_task_status status);
void iser_task_free(struct iser_task *iser_task);
-
void iser_task_release_recv_buffers(struct iser_task *p_iser_task);
-
void iser_task_release_send_buffers(struct iser_task *p_iser_task);
#endif /* __ISER_TASK_H__ */
Index: iser_lkdapl.c
===================================================================
--- iser_lkdapl.c (revision 3404)
+++ iser_lkdapl.c (working copy)
@@ -47,6 +47,7 @@
#include "iser_kdapl.h"
#include "iser_utils.h"
#include "iser_memory.h"
+#include "iser_socket.h"
#include "iser_initiator.h"
/* Service ID generation */
@@ -152,7 +153,7 @@
ITRACE(ISER_TRACE_KDAPL, "failed to find a working
adaptor\n");
kfree(list);
kfree(tmem);
- return -1;
+ return -ENODEV;
}
/* done with lists */
@@ -437,61 +438,11 @@
} /* iser_disconnect */
/**
- * iser_register_virt_mem - Register a memory buffer.
+ * iser_register_ia_mem - Register a memory buffer using IA method.
*
* returns: 0 on success, -1 on failure
*/
int
-iser_register_virt_mem(struct iser_adaptor *p_adaptor,
- void *p_buf,
- unsigned long data_sz,
- enum dat_mem_priv_flags priv_flags,
- struct iser_mem_handles *p_mem_reg,
- DAT_RMR_CONTEXT * p_rmr_ctxt)
-{
- DAT_REGION_DESCRIPTION mem_region;
- u32 dat_ret;
- DAT_RMR_CONTEXT dummy_rmr;
- int ret_val = 0;
-
- mem_region.for_va = p_buf;
- dat_ret = dat_lmr_kcreate(p_adaptor->ia_handle,
- DAT_MEM_TYPE_VIRTUAL,
- mem_region,
- data_sz,
- p_adaptor->pz_handle,
- priv_flags,
- DAT_MEM_OPTIMIZE_DONT_CARE,
- &p_mem_reg->lmr_handle,
- &p_mem_reg->lmr_triplet.lmr_context,
- p_rmr_ctxt == NULL ? &dummy_rmr :
p_rmr_ctxt,
-
&p_mem_reg->lmr_triplet.segment_length,
-
&p_mem_reg->lmr_triplet.virtual_address);
-
- ITRACE(ISER_TRACE_PHYS_MEM_REG,
- "VIRTUAL Mem.register [SINGLE p_buf: 0x%p, sz: %ld] "
- "-> [lkey: 0x%08X lmr_h: 0x%p va: 0x%08lX sz: %ld]\n",
- p_buf, data_sz,
- (unsigned int)p_mem_reg->lmr_triplet.lmr_context,
- p_mem_reg->lmr_handle,
- (unsigned long)p_mem_reg->lmr_triplet.virtual_address,
- (unsigned long)p_mem_reg->lmr_triplet.segment_length);
-
- if (dat_ret) {
- printk(KERN_ERR PFX "dat_lmr_kcreate VIRTUAL failed
ret=%d\n",
- dat_ret);
- ret_val = -1;
- }
-
- return ret_val;
-} /* iser_register_virt_mem */
-
-/**
- * iser_register_ia_mem - Register a virtual memory buffer using IA
method.
- *
- * returns: 0 on success, -1 on failure
- */
-int
iser_register_ia_mem(struct iser_adaptor *p_adaptor,
void *virt_addr,
unsigned long data_sz,
@@ -640,11 +591,11 @@
} /* iser_unregister_memory */
/**
- * iser_dtoo_iov - Posts a receive buffer.
+ * iser_dto_to_iov - Posts a receive buffer.
*
* returns 0 on success, -1 on failure
*/
-static void iser_dtoo_iov(struct iser_dto *p_dto, struct
dat_lmr_triplet *iov)
+static void iser_dto_to_iov(struct iser_dto *p_dto, struct
dat_lmr_triplet *iov)
{
int i;
@@ -697,7 +648,7 @@
(unsigned int)iov[i].lmr_context,
p_dto->regd[i]->mem_reg.lmr_handle);
}
-} /* iser_dtoo_iov */
+} /* iser_dto_to_iov */
/**
* iser_post_recv - Posts a receive buffer.
@@ -726,7 +677,7 @@
IPANIC("DTO regd_vector_len exceeds maximal IOV len\n");
}
- iser_dtoo_iov(p_recv_dto, iov);
+ iser_dto_to_iov(p_recv_dto, iov);
/* Post rcv buffers */
spin_lock(&p_iser_conn->post_rx_lock);
@@ -784,7 +735,7 @@
IPANIC("DTO regd_vector_len exceeds maximal IOV len\n");
}
- iser_dtoo_iov(p_dto, iov);
+ iser_dto_to_iov(p_dto, iov);
switch (p_dto->type) {
case ISER_DTO_SEND:
@@ -1009,11 +960,8 @@
switch (event_number) {
case DAT_CONNECTION_EVENT_ESTABLISHED:
- /* Set the new conn state */
atomic_set(&p_iser_conn->state, ISER_CONN_UP);
- /* Notify about conn establishment */
- p_iser_conn->p_entity->api_cb.
- conn_establish_notify(p_iser_conn->iscsi_conn_h, 1);
+ iser_conn_establish_notify(p_iser_conn);
break;
case DAT_CONNECTION_EVENT_DISCONNECTED:
@@ -1025,10 +973,8 @@
the iSCSI layer's perspective. */
if (atomic_read(&p_iser_conn->state) ==
ISER_CONN_PENDING) {
atomic_set(&p_iser_conn->state, ISER_CONN_DOWN);
- p_iser_conn->p_entity->api_cb.
-
conn_establish_notify(p_iser_conn->iscsi_conn_h,
- 0);
- iser_conn_free(p_iser_conn);
+ iser_conn_establish_notify(p_iser_conn);
+ iser_conn_release(p_iser_conn);
} else {
if (atomic_read(&p_iser_conn->state) ==
ISER_CONN_UP) {
atomic_set(&p_iser_conn->state,
@@ -1051,10 +997,8 @@
case DAT_CONNECTION_EVENT_UNREACHABLE:
if (atomic_read(&p_iser_conn->state) ==
ISER_CONN_PENDING) {
atomic_set(&p_iser_conn->state, ISER_CONN_DOWN);
- p_iser_conn->p_entity->api_cb.
-
conn_establish_notify(p_iser_conn->iscsi_conn_h,
- 0);
- iser_conn_free(p_iser_conn);
+ iser_conn_establish_notify(p_iser_conn);
+ iser_conn_release(p_iser_conn);
break;
} else {
printk(KERN_ERR PFX
@@ -1138,13 +1082,7 @@
dto_xfer_len,
ev->event_data.dto_completion_event_data.ep);
- /* Handle successful DTO completion */
- ret_val = iser_dto_completion(p_dto, dto_xfer_len);
-
- if (ret_val != 0) {
- printk(KERN_ERR PFX "Failed to handle "
- "successful DTO completion\n");
- }
+ iser_dto_completion(p_dto, dto_xfer_len);
break;
case DAT_DTO_ERR_FLUSHED:
Index: iser_initiator.h
===================================================================
--- iser_initiator.h (revision 3404)
+++ iser_initiator.h (working copy)
@@ -36,18 +36,10 @@
#include "iser.h"
-int ig_init(void);
-int ig_release(void);
+int iser_send_control(void *iser_conn_h,
+ struct iser_send_pdu *p_ctrl_pdu);
-struct iser_connection *iser_adaptor_find_conn(struct iser_adaptor
- *p_iser_adaptor,
- void *ep_handle);
-void iser_adaptor_remove_conn(struct iser_connection *p_iser_conn);
+void iser_dto_completion(struct iser_dto *p_dto,
+ unsigned long dto_xfer_len);
-void iser_entity_add_conn(struct iser_entity *p_entity,
- struct iser_connection *p_iser_conn);
-void iser_entity_remove_conn(struct iser_connection *p_iser_conn);
-
-int iser_dto_completion(struct iser_dto *p_dto, unsigned long
dto_xfer_len);
-
#endif /* __ISER_INITIATOR_H__ */
Index: iser_memory.c
===================================================================
--- iser_memory.c (revision 3404)
+++ iser_memory.c (working copy)
@@ -35,8 +35,8 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
-#include <asm/io.h> /* struct iovec */
-#include <asm/scatterlist.h> /* struct scatterlist */
+#include <asm/io.h>
+#include <asm/scatterlist.h>
#include "iser.h"
#include "iser_memory.h"
@@ -157,24 +157,14 @@
p_pool_region->gfp_order = gfp_order;
p_pool_region->id = ++p_bufpool->num_regions;
- /* Register the memory */
-#if VIRTUAL_SUPPORTED
- /* remote ctxt */
- ret_val =
- iser_register_virt_mem(p_bufpool->p_adaptor, p_pool_mem,
gfp_size,
- DAT_MEM_PRIV_ALL_FLAG,
- &p_pool_region->mem_reg, NULL);
-#else /* DAN */
- /* remote ctxt */
- ret_val =
- iser_register_ia_mem(p_bufpool->p_adaptor, p_pool_mem,
gfp_size,
- DAT_MEM_PRIV_ALL_FLAG,
- &p_pool_region->mem_reg, NULL);
-#endif
-
+ ret_val = iser_register_ia_mem(p_bufpool->p_adaptor,
+ p_pool_mem,
+ gfp_size,
+ DAT_MEM_PRIV_ALL_FLAG,
+ &p_pool_region->mem_reg,
+ NULL);
if (ret_val != 0) {
- printk(KERN_ERR PFX
- "Failed to register buffer pool memory: 0x%p, "
+ printk(KERN_ERR PFX "Failed to register buff pool
mem:0x%p, "
"sz: %ld, region: 0x%p\n",
p_pool_mem, gfp_size, p_pool_region);
iser_bufpool_region_destroy(p_pool_region);
@@ -750,12 +740,12 @@
} /* iser_regd_buff_release */
/**
- * iser_init_regd_buff_cache - Pre-registers the entire memory buffers,
+ * Pre-registers the entire memory buffers,
* for single buffers lookup
*
* returns 0 on success, -1 otherwise
*/
-int iser_init_regd_buff_cache(struct iser_adaptor *p_iser_adaptor)
+int iser_reg_all_mem(struct iser_adaptor *p_iser_adaptor)
{
struct sysinfo si;
int phys_mem_size;
@@ -779,9 +769,9 @@
}
return ret_val;
-} /* iser_init_regd_buff_cache */
+} /* iser_reg_all_mem */
-int iser_release_regd_buff_cache(struct iser_adaptor *p_iser_adaptor)
+int iser_unreg_all_mem(struct iser_adaptor *p_iser_adaptor)
{
int ret_val = 0;
@@ -794,7 +784,7 @@
}
return ret_val;
-} /* iser_release_regd_buff_cache */
+} /* iser_unreg_all_mem */
/**
* iser_regd_buff_lookup - Checks if a memory buffer is contained
Index: Makefile
===================================================================
--- Makefile (revision 3404)
+++ Makefile (working copy)
@@ -10,5 +10,6 @@
iser_task.o \
iser_utils.o \
iser_dto.o \
- iser_lkdapl.o
+ iser_lkdapl.o \
+ iser_socket.o
More information about the general
mailing list