/* * This file is part of iser target kernel module. * * Copyright (c) 2013 - 2014 Mellanox Technologies. All rights reserved. * Copyright (c) 2013 - 2014 Yan Burman (yanb@mellanox.com) * * 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_H__ #define __ISER_H__ #include #include #include #ifndef INSIDE_KERNEL_TREE #include #endif #if defined(RHEL_MAJOR) && RHEL_MAJOR -0 == 5 static inline u16 vlan_dev_vlan_id(const void *dev) { BUG(); return 0; } #endif #include #include "iser_hdr.h" enum isert_portal_state { ISERT_PORTAL_ACTIVE, ISERT_PORTAL_INACTIVE }; struct isert_portal { struct rdma_cm_id *cm_id; struct sockaddr_storage addr; struct list_head list_node; /* in portals list */ /* protected by dev_list_mutex */ struct list_head conn_list; /* head of conns list */ enum isert_portal_state state; int refcnt; }; struct isert_buf { int sg_cnt ____cacheline_aligned; struct scatterlist *sg; u8 *addr; size_t size; enum dma_data_direction dma_dir; unsigned int is_alloced:1; unsigned int is_pgalloced:1; unsigned int is_malloced:1; }; enum isert_wr_op { ISER_WR_RECV, ISER_WR_SEND, ISER_WR_RDMA_WRITE, ISER_WR_RDMA_READ, }; struct isert_device; struct isert_connection; struct isert_wr { enum isert_wr_op wr_op; struct isert_buf *buf; struct isert_connection *conn; struct isert_cmnd *pdu; struct isert_device *isert_dev; struct ib_sge *sge_list; union { struct ib_recv_wr recv_wr; #ifdef USE_PRE_440_WR_STRUCTURE struct ib_send_wr send_wr; #else struct ib_rdma_wr send_wr; #endif }; } ____cacheline_aligned; #define ISER_SQ_SIZE 128 #define ISER_MAX_WCE 2048 #define ISER_MIN_SQ_SIZE 16 struct isert_cmnd { struct iscsi_cmnd iscsi ____cacheline_aligned; struct isert_buf buf; struct isert_buf rdma_buf; struct isert_wr *wr; struct ib_sge *sg_pool; int n_wr; int n_sge; struct isert_hdr *isert_hdr ____cacheline_aligned; struct iscsi_hdr *bhs; void *ahs; void *data; u8 isert_opcode; u8 iscsi_opcode; u8 is_rstag_valid; u8 is_wstag_valid; u32 rem_write_stag; /* write rkey */ u64 rem_write_va; u32 rem_read_stag; /* read rkey */ u64 rem_read_va; int is_fake_rx; struct list_head pool_node; /* pool list */ }; enum isert_conn_state { ISER_CONN_INIT = 0, ISER_CONN_HANDSHAKE, ISER_CONN_ACTIVE, ISER_CONN_CLOSING, }; struct isert_cq { struct ib_cq *cq ____cacheline_aligned; struct ib_wc wc[ISER_SQ_SIZE]; struct isert_device *dev; struct workqueue_struct *cq_workqueue; struct work_struct cq_comp_work; int idx; }; #define ISERT_CONNECTION_ABORTED 0 #define ISERT_DRAIN_POSTED 1 #define ISERT_DISCON_CALLED 2 #define ISERT_DRAINED_RQ 3 #define ISERT_DRAINED_SQ 4 #define ISERT_CONNECTION_CLOSE 5 #define ISERT_IN_PORTAL_LIST 6 struct isert_connection { struct iscsi_conn iscsi ____cacheline_aligned; int repost_threshold ____cacheline_aligned; /* access to the following 3 fields is guarded by post_recv_lock */ int to_post_recv; struct isert_wr *post_recv_first; struct isert_wr *post_recv_curr; spinlock_t post_recv_lock; spinlock_t tx_lock ____cacheline_aligned; /* Following two protected by tx_lock */ struct list_head tx_free_list; struct list_head tx_busy_list; struct rdma_cm_id *cm_id; struct isert_device *isert_dev; struct ib_qp *qp; struct isert_cq *cq_desc; enum isert_conn_state state; struct mutex state_mutex; u32 responder_resources; u32 initiator_depth; u32 max_sge; /* * Unprotected. Accessed only before login response is sent and when * freeing connection */ struct list_head rx_buf_list; struct isert_cmnd *login_req_pdu; struct isert_cmnd *login_rsp_pdu; struct isert_wr *saved_wr; int queue_depth; int immediate_data; unsigned int target_recv_data_length; int initiator_recv_data_length; int initial_r2t; unsigned int first_burst_length; struct sockaddr_storage peer_addr; size_t peer_addrsz; struct sockaddr_storage self_addr; struct list_head portal_node; unsigned long flags; struct work_struct close_work; struct work_struct drain_work; struct work_struct discon_work; struct work_struct free_work; struct isert_wr drain_wr_sq; struct isert_wr drain_wr_rq; struct kref kref; struct isert_portal *portal; void *priv_data; /* for connection tracking */ }; struct isert_device { struct ib_device *ib_dev; struct ib_pd *pd; #ifndef IB_PD_HAS_LOCAL_DMA_LKEY struct ib_mr *mr; #endif u32 lkey; struct list_head devs_node; /* conn_list and refcnt protected by dev_list_mutex */ struct list_head conn_list; int refcnt; struct ib_device_attr device_attr; int num_cqs; int *cq_qps; struct isert_cq *cq_desc; }; struct isert_global { spinlock_t portal_lock; /* protected by portal_lock */ struct list_head portal_list; /* Number of live portal objects. Protected by portal_lock. */ int portal_cnt; wait_queue_head_t portal_wq; /* protected by dev_list_mutex */ struct list_head dev_list; struct workqueue_struct *conn_wq; }; #define _ptr_to_u64(p) (u64)(unsigned long)(p) #define _u64_to_ptr(v) (void *)(unsigned long)(v) /* global iser scope */ int isert_global_init(void); int isert_datamover_cleanup(void); void isert_portal_list_add(struct isert_portal *portal); void isert_portal_list_remove(struct isert_portal *portal); void isert_decrease_portal_cnt(void); void isert_wait_for_portal_release(void); void isert_dev_list_add(struct isert_device *isert_dev); void isert_dev_list_remove(struct isert_device *isert_dev); struct isert_device *isert_device_find(struct ib_device *ib_dev); void isert_conn_queue_work(struct work_struct *w); extern struct kmem_cache *isert_cmnd_cache; extern struct kmem_cache *isert_conn_cache; /* iser portal */ struct isert_portal *isert_portal_create(void); int isert_portal_listen(struct isert_portal *portal, struct sockaddr *sa, size_t addr_len); void isert_portal_release(struct isert_portal *portal); void isert_portal_list_release_all(void); struct isert_portal *isert_portal_start(struct sockaddr *sa, size_t addr_len); /* iser connection */ int isert_post_recv(struct isert_connection *isert_conn, struct isert_wr *first_wr, int num_wr); int isert_post_send(struct isert_connection *isert_conn, struct isert_wr *first_wr, int num_wr); int isert_alloc_conn_resources(struct isert_connection *isert_conn); void isert_free_conn_resources(struct isert_connection *isert_conn); void isert_conn_free(struct isert_connection *isert_conn); void isert_conn_disconnect(struct isert_connection *isert_conn); void isert_post_drain(struct isert_connection *isert_conn); void isert_sched_conn_free(struct isert_connection *isert_conn); static inline struct isert_connection *isert_conn_zalloc(void) { return kmem_cache_zalloc(isert_conn_cache, GFP_KERNEL); } static inline void isert_conn_kfree(struct isert_connection *isert_conn) { kmem_cache_free(isert_conn_cache, isert_conn); } /* iser buf */ int isert_buf_alloc_data_buf(struct ib_device *ib_dev, struct isert_buf *isert_buf, size_t size, enum dma_data_direction dma_dir); void isert_wr_set_fields(struct isert_wr *wr, struct isert_connection *isert_conn, struct isert_cmnd *pdu); int isert_wr_init(struct isert_wr *wr, enum isert_wr_op wr_op, struct isert_buf *isert_buf, struct isert_connection *isert_conn, struct isert_cmnd *pdu, struct ib_sge *sge, int sg_offset, int sg_cnt, int buff_offset); void isert_wr_release(struct isert_wr *wr); void isert_buf_release(struct isert_buf *isert_buf); static inline void isert_buf_init_sg(struct isert_buf *isert_buf, struct scatterlist *sg, int sg_cnt, size_t size) { isert_buf->sg_cnt = sg_cnt; isert_buf->sg = sg; isert_buf->size = size; } /* iser pdu */ static inline struct isert_cmnd *isert_pdu_alloc(void) { return kmem_cache_zalloc(isert_cmnd_cache, GFP_KERNEL); } static inline void isert_pdu_kfree(struct isert_cmnd *cmnd) { kmem_cache_free(isert_cmnd_cache, cmnd); } struct isert_cmnd *isert_rx_pdu_alloc(struct isert_connection *isert_conn, size_t size); struct isert_cmnd *isert_tx_pdu_alloc(struct isert_connection *isert_conn, size_t size); void isert_tx_pdu_init(struct isert_cmnd *isert_pdu, struct isert_connection *isert_conn); int isert_pdu_send(struct isert_connection *isert_conn, struct isert_cmnd *tx_pdu); int isert_prepare_rdma(struct isert_cmnd *isert_pdu, struct isert_connection *isert_conn, enum isert_wr_op op); int isert_pdu_post_rdma_write(struct isert_connection *isert_conn, struct isert_cmnd *isert_cmd, struct isert_cmnd *isert_rsp, int wr_cnt); int isert_pdu_post_rdma_read(struct isert_connection *isert_conn, struct isert_cmnd *isert_cmd, int wr_cnt); void isert_pdu_free(struct isert_cmnd *pdu); int isert_rx_pdu_done(struct isert_cmnd *pdu); void isert_tx_pdu_convert_from_iscsi(struct isert_cmnd *isert_cmnd, struct iscsi_cmnd *iscsi_cmnd); void isert_tx_pdu_init_iscsi(struct isert_cmnd *isert_pdu); /* global */ void isert_global_cleanup(void); int isert_get_addr_size(struct sockaddr *sa, size_t *size); #endif