/* * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved. * Copyright (C) 2008 - 2011 Bart Van Assche <[email protected]>. * * 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/init.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/ctype.h> #include <linux/kthread.h> #include <linux/string.h> #include <linux/delay.h> #include <linux/atomic.h> #include <linux/inet.h> #include <rdma/ib_cache.h> #include <scsi/scsi_proto.h> #include <scsi/scsi_tcq.h> #include <target/target_core_base.h> #include <target/target_core_fabric.h> #include "ib_srpt.h" /* Name of this kernel module. */ #define DRV_NAME … #define SRPT_ID_STRING … #undef pr_fmt #define pr_fmt(fmt) … MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* * Global Variables */ static u64 srpt_service_guid; static DEFINE_SPINLOCK(srpt_dev_lock); /* Protects srpt_dev_list. */ static LIST_HEAD(srpt_dev_list); /* List of srpt_device structures. */ static unsigned srp_max_req_size = …; module_param(srp_max_req_size, int, 0444); MODULE_PARM_DESC(…) …; static int srpt_srq_size = …; module_param(srpt_srq_size, int, 0444); MODULE_PARM_DESC(…) …; static int srpt_set_u64_x(const char *buffer, const struct kernel_param *kp) { … } static int srpt_get_u64_x(char *buffer, const struct kernel_param *kp) { … } module_param_call(…); MODULE_PARM_DESC(…) …; static struct ib_client srpt_client; /* Protects both rdma_cm_port and rdma_cm_id. */ static DEFINE_MUTEX(rdma_cm_mutex); /* Port number RDMA/CM will bind to. */ static u16 rdma_cm_port; static struct rdma_cm_id *rdma_cm_id; static void srpt_release_cmd(struct se_cmd *se_cmd); static void srpt_free_ch(struct kref *kref); static int srpt_queue_status(struct se_cmd *cmd); static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc); static void srpt_process_wait_list(struct srpt_rdma_ch *ch); /* * The only allowed channel state changes are those that change the channel * state into a state with a higher numerical value. Hence the new > prev test. */ static bool srpt_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state new) { … } /** * srpt_event_handler - asynchronous IB event callback function * @handler: IB event handler registered by ib_register_event_handler(). * @event: Description of the event that occurred. * * Callback function called by the InfiniBand core when an asynchronous IB * event occurs. This callback may occur in interrupt context. See also * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand * Architecture Specification. */ static void srpt_event_handler(struct ib_event_handler *handler, struct ib_event *event) { … } /** * srpt_srq_event - SRQ event callback function * @event: Description of the event that occurred. * @ctx: Context pointer specified at SRQ creation time. */ static void srpt_srq_event(struct ib_event *event, void *ctx) { … } static const char *get_ch_state_name(enum rdma_ch_state s) { … } /** * srpt_qp_event - QP event callback function * @event: Description of the event that occurred. * @ptr: SRPT RDMA channel. */ static void srpt_qp_event(struct ib_event *event, void *ptr) { … } /** * srpt_set_ioc - initialize a IOUnitInfo structure * @c_list: controller list. * @slot: one-based slot number. * @value: four-bit value. * * Copies the lowest four bits of value in element slot of the array of four * bit elements called c_list (controller list). The index slot is one-based. */ static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value) { … } /** * srpt_get_class_port_info - copy ClassPortInfo to a management datagram * @mad: Datagram that will be sent as response to DM_ATTR_CLASS_PORT_INFO. * * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture * Specification. */ static void srpt_get_class_port_info(struct ib_dm_mad *mad) { … } /** * srpt_get_iou - write IOUnitInfo to a management datagram * @mad: Datagram that will be sent as response to DM_ATTR_IOU_INFO. * * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture * Specification. See also section B.7, table B.6 in the SRP r16a document. */ static void srpt_get_iou(struct ib_dm_mad *mad) { … } /** * srpt_get_ioc - write IOControllerprofile to a management datagram * @sport: HCA port through which the MAD has been received. * @slot: Slot number specified in DM_ATTR_IOC_PROFILE query. * @mad: Datagram that will be sent as response to DM_ATTR_IOC_PROFILE. * * See also section 16.3.3.4 IOControllerProfile in the InfiniBand * Architecture Specification. See also section B.7, table B.7 in the SRP * r16a document. */ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, struct ib_dm_mad *mad) { … } /** * srpt_get_svc_entries - write ServiceEntries to a management datagram * @ioc_guid: I/O controller GUID to use in reply. * @slot: I/O controller number. * @hi: End of the range of service entries to be specified in the reply. * @lo: Start of the range of service entries to be specified in the reply.. * @mad: Datagram that will be sent as response to DM_ATTR_SVC_ENTRIES. * * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture * Specification. See also section B.7, table B.8 in the SRP r16a document. */ static void srpt_get_svc_entries(u64 ioc_guid, u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad) { … } /** * srpt_mgmt_method_get - process a received management datagram * @sp: HCA port through which the MAD has been received. * @rq_mad: received MAD. * @rsp_mad: response MAD. */ static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad, struct ib_dm_mad *rsp_mad) { … } /** * srpt_mad_send_handler - MAD send completion callback * @mad_agent: Return value of ib_register_mad_agent(). * @mad_wc: Work completion reporting that the MAD has been sent. */ static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent, struct ib_mad_send_wc *mad_wc) { … } /** * srpt_mad_recv_handler - MAD reception callback function * @mad_agent: Return value of ib_register_mad_agent(). * @send_buf: Not used. * @mad_wc: Work completion reporting that a MAD has been received. */ static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent, struct ib_mad_send_buf *send_buf, struct ib_mad_recv_wc *mad_wc) { … } static int srpt_format_guid(char *buf, unsigned int size, const __be64 *guid) { … } /** * srpt_refresh_port - configure a HCA port * @sport: SRPT HCA port. * * Enable InfiniBand management datagram processing, update the cached sm_lid, * lid and gid values, and register a callback function for processing MADs * on the specified port. * * Note: It is safe to call this function more than once for the same port. */ static int srpt_refresh_port(struct srpt_port *sport) { … } /** * srpt_unregister_mad_agent - unregister MAD callback functions * @sdev: SRPT HCA pointer. * @port_cnt: number of ports with registered MAD * * Note: It is safe to call this function more than once for the same device. */ static void srpt_unregister_mad_agent(struct srpt_device *sdev, int port_cnt) { … } /** * srpt_alloc_ioctx - allocate a SRPT I/O context structure * @sdev: SRPT HCA pointer. * @ioctx_size: I/O context size. * @buf_cache: I/O buffer cache. * @dir: DMA data direction. */ static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev, int ioctx_size, struct kmem_cache *buf_cache, enum dma_data_direction dir) { … } /** * srpt_free_ioctx - free a SRPT I/O context structure * @sdev: SRPT HCA pointer. * @ioctx: I/O context pointer. * @buf_cache: I/O buffer cache. * @dir: DMA data direction. */ static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx, struct kmem_cache *buf_cache, enum dma_data_direction dir) { … } /** * srpt_alloc_ioctx_ring - allocate a ring of SRPT I/O context structures * @sdev: Device to allocate the I/O context ring for. * @ring_size: Number of elements in the I/O context ring. * @ioctx_size: I/O context size. * @buf_cache: I/O buffer cache. * @alignment_offset: Offset in each ring buffer at which the SRP information * unit starts. * @dir: DMA data direction. */ static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev, int ring_size, int ioctx_size, struct kmem_cache *buf_cache, int alignment_offset, enum dma_data_direction dir) { … } /** * srpt_free_ioctx_ring - free the ring of SRPT I/O context structures * @ioctx_ring: I/O context ring to be freed. * @sdev: SRPT HCA pointer. * @ring_size: Number of ring elements. * @buf_cache: I/O buffer cache. * @dir: DMA data direction. */ static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring, struct srpt_device *sdev, int ring_size, struct kmem_cache *buf_cache, enum dma_data_direction dir) { … } /** * srpt_set_cmd_state - set the state of a SCSI command * @ioctx: Send I/O context. * @new: New I/O context state. * * Does not modify the state of aborted commands. Returns the previous command * state. */ static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx, enum srpt_command_state new) { … } /** * srpt_test_and_set_cmd_state - test and set the state of a command * @ioctx: Send I/O context. * @old: Current I/O context state. * @new: New I/O context state. * * Returns true if and only if the previous command state was equal to 'old'. */ static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx, enum srpt_command_state old, enum srpt_command_state new) { … } /** * srpt_post_recv - post an IB receive request * @sdev: SRPT HCA pointer. * @ch: SRPT RDMA channel. * @ioctx: Receive I/O context pointer. */ static int srpt_post_recv(struct srpt_device *sdev, struct srpt_rdma_ch *ch, struct srpt_recv_ioctx *ioctx) { … } /** * srpt_zerolength_write - perform a zero-length RDMA write * @ch: SRPT RDMA channel. * * A quote from the InfiniBand specification: C9-88: For an HCA responder * using Reliable Connection service, for each zero-length RDMA READ or WRITE * request, the R_Key shall not be validated, even if the request includes * Immediate data. */ static int srpt_zerolength_write(struct srpt_rdma_ch *ch) { … } static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc) { … } static int srpt_alloc_rw_ctxs(struct srpt_send_ioctx *ioctx, struct srp_direct_buf *db, int nbufs, struct scatterlist **sg, unsigned *sg_cnt) { … } static void srpt_free_rw_ctxs(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx) { … } static inline void *srpt_get_desc_buf(struct srp_cmd *srp_cmd) { … } /** * srpt_get_desc_tbl - parse the data descriptors of a SRP_CMD request * @recv_ioctx: I/O context associated with the received command @srp_cmd. * @ioctx: I/O context that will be used for responding to the initiator. * @srp_cmd: Pointer to the SRP_CMD request data. * @dir: Pointer to the variable to which the transfer direction will be * written. * @sg: [out] scatterlist for the parsed SRP_CMD. * @sg_cnt: [out] length of @sg. * @data_len: Pointer to the variable to which the total data length of all * descriptors in the SRP_CMD request will be written. * @imm_data_offset: [in] Offset in SRP_CMD requests at which immediate data * starts. * * This function initializes ioctx->nrbuf and ioctx->r_bufs. * * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors; * -ENOMEM when memory allocation fails and zero upon success. */ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx, struct srpt_send_ioctx *ioctx, struct srp_cmd *srp_cmd, enum dma_data_direction *dir, struct scatterlist **sg, unsigned int *sg_cnt, u64 *data_len, u16 imm_data_offset) { … } /** * srpt_init_ch_qp - initialize queue pair attributes * @ch: SRPT RDMA channel. * @qp: Queue pair pointer. * * Initialized the attributes of queue pair 'qp' by allowing local write, * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT. */ static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp) { … } /** * srpt_ch_qp_rtr - change the state of a channel to 'ready to receive' (RTR) * @ch: channel of the queue pair. * @qp: queue pair to change the state of. * * Returns zero upon success and a negative value upon failure. * * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system. * If this structure ever becomes larger, it might be necessary to allocate * it dynamically instead of on the stack. */ static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp) { … } /** * srpt_ch_qp_rts - change the state of a channel to 'ready to send' (RTS) * @ch: channel of the queue pair. * @qp: queue pair to change the state of. * * Returns zero upon success and a negative value upon failure. * * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system. * If this structure ever becomes larger, it might be necessary to allocate * it dynamically instead of on the stack. */ static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp) { … } /** * srpt_ch_qp_err - set the channel queue pair state to 'error' * @ch: SRPT RDMA channel. */ static int srpt_ch_qp_err(struct srpt_rdma_ch *ch) { … } /** * srpt_get_send_ioctx - obtain an I/O context for sending to the initiator * @ch: SRPT RDMA channel. */ static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch) { … } /** * srpt_abort_cmd - abort a SCSI command * @ioctx: I/O context associated with the SCSI command. */ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx) { … } /** * srpt_rdma_read_done - RDMA read completion callback * @cq: Completion queue. * @wc: Work completion. * * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping * the data that has been transferred via IB RDMA had to be postponed until the * check_stop_free() callback. None of this is necessary anymore and needs to * be cleaned up. */ static void srpt_rdma_read_done(struct ib_cq *cq, struct ib_wc *wc) { … } /** * srpt_build_cmd_rsp - build a SRP_RSP response * @ch: RDMA channel through which the request has been received. * @ioctx: I/O context associated with the SRP_CMD request. The response will * be built in the buffer ioctx->buf points at and hence this function will * overwrite the request data. * @tag: tag of the request for which this response is being generated. * @status: value for the STATUS field of the SRP_RSP information unit. * * Returns the size in bytes of the SRP_RSP response. * * An SRP_RSP response contains a SCSI status or service response. See also * section 6.9 in the SRP r16a document for the format of an SRP_RSP * response. See also SPC-2 for more information about sense data. */ static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx, u64 tag, int status) { … } /** * srpt_build_tskmgmt_rsp - build a task management response * @ch: RDMA channel through which the request has been received. * @ioctx: I/O context in which the SRP_RSP response will be built. * @rsp_code: RSP_CODE that will be stored in the response. * @tag: Tag of the request for which this response is being generated. * * Returns the size in bytes of the SRP_RSP response. * * An SRP_RSP response contains a SCSI status or service response. See also * section 6.9 in the SRP r16a document for the format of an SRP_RSP * response. */ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, struct srpt_send_ioctx *ioctx, u8 rsp_code, u64 tag) { … } static int srpt_check_stop_free(struct se_cmd *cmd) { … } /** * srpt_handle_cmd - process a SRP_CMD information unit * @ch: SRPT RDMA channel. * @recv_ioctx: Receive I/O context. * @send_ioctx: Send I/O context. */ static void srpt_handle_cmd(struct srpt_rdma_ch *ch, struct srpt_recv_ioctx *recv_ioctx, struct srpt_send_ioctx *send_ioctx) { … } static int srp_tmr_to_tcm(int fn) { … } /** * srpt_handle_tsk_mgmt - process a SRP_TSK_MGMT information unit * @ch: SRPT RDMA channel. * @recv_ioctx: Receive I/O context. * @send_ioctx: Send I/O context. * * Returns 0 if and only if the request will be processed by the target core. * * For more information about SRP_TSK_MGMT information units, see also section * 6.7 in the SRP r16a document. */ static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch, struct srpt_recv_ioctx *recv_ioctx, struct srpt_send_ioctx *send_ioctx) { … } /** * srpt_handle_new_iu - process a newly received information unit * @ch: RDMA channel through which the information unit has been received. * @recv_ioctx: Receive I/O context associated with the information unit. */ static bool srpt_handle_new_iu(struct srpt_rdma_ch *ch, struct srpt_recv_ioctx *recv_ioctx) { … } static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc) { … } /* * This function must be called from the context in which RDMA completions are * processed because it accesses the wait list without protection against * access from other threads. */ static void srpt_process_wait_list(struct srpt_rdma_ch *ch) { … } /** * srpt_send_done - send completion callback * @cq: Completion queue. * @wc: Work completion. * * Note: Although this has not yet been observed during tests, at least in * theory it is possible that the srpt_get_send_ioctx() call invoked by * srpt_handle_new_iu() fails. This is possible because the req_lim_delta * value in each response is set to one, and it is possible that this response * makes the initiator send a new request before the send completion for that * response has been processed. This could e.g. happen if the call to * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or * if IB retransmission causes generation of the send completion to be * delayed. Incoming information units for which srpt_get_send_ioctx() fails * are queued on cmd_wait_list. The code below processes these delayed * requests one at a time. */ static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc) { … } /** * srpt_create_ch_ib - create receive and send completion queues * @ch: SRPT RDMA channel. */ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) { … } static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) { … } /** * srpt_close_ch - close a RDMA channel * @ch: SRPT RDMA channel. * * Make sure all resources associated with the channel will be deallocated at * an appropriate time. * * Returns true if and only if the channel state has been modified into * CH_DRAINING. */ static bool srpt_close_ch(struct srpt_rdma_ch *ch) { … } /* * Change the channel state into CH_DISCONNECTING. If a channel has not yet * reached the connected state, close it. If a channel is in the connected * state, send a DREQ. If a DREQ has been received, send a DREP. Note: it is * the responsibility of the caller to ensure that this function is not * invoked concurrently with the code that accepts a connection. This means * that this function must either be invoked from inside a CM callback * function or that it must be invoked with the srpt_port.mutex held. */ static int srpt_disconnect_ch(struct srpt_rdma_ch *ch) { … } /* Send DREQ and wait for DREP. */ static void srpt_disconnect_ch_sync(struct srpt_rdma_ch *ch) { … } static void __srpt_close_all_ch(struct srpt_port *sport) { … } /* * Look up (i_port_id, t_port_id) in sport->nexus_list. Create an entry if * it does not yet exist. */ static struct srpt_nexus *srpt_get_nexus(struct srpt_port *sport, const u8 i_port_id[16], const u8 t_port_id[16]) { … } static void srpt_set_enabled(struct srpt_port *sport, bool enabled) __must_hold(&sport->mutex) { … } static void srpt_drop_sport_ref(struct srpt_port *sport) { … } static void srpt_free_ch(struct kref *kref) { … } /* * Shut down the SCSI target session, tell the connection manager to * disconnect the associated RDMA channel, transition the QP to the error * state and remove the channel from the channel list. This function is * typically called from inside srpt_zerolength_write_done(). Concurrent * srpt_zerolength_write() calls from inside srpt_close_ch() are possible * as long as the channel is on sport->nexus_list. */ static void srpt_release_channel_work(struct work_struct *w) { … } /** * srpt_cm_req_recv - process the event IB_CM_REQ_RECEIVED * @sdev: HCA through which the login request was received. * @ib_cm_id: IB/CM connection identifier in case of IB/CM. * @rdma_cm_id: RDMA/CM connection identifier in case of RDMA/CM. * @port_num: Port through which the REQ message was received. * @pkey: P_Key of the incoming connection. * @req: SRP login request. * @src_addr: GID (IB/CM) or IP address (RDMA/CM) of the port that submitted * the login request. * * Ownership of the cm_id is transferred to the target session if this * function returns zero. Otherwise the caller remains the owner of cm_id. */ static int srpt_cm_req_recv(struct srpt_device *const sdev, struct ib_cm_id *ib_cm_id, struct rdma_cm_id *rdma_cm_id, u8 port_num, __be16 pkey, const struct srp_login_req *req, const char *src_addr) { … } static int srpt_ib_cm_req_recv(struct ib_cm_id *cm_id, const struct ib_cm_req_event_param *param, void *private_data) { … } static int srpt_rdma_cm_req_recv(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) { … } static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch, enum ib_cm_rej_reason reason, const u8 *private_data, u8 private_data_len) { … } /** * srpt_cm_rtu_recv - process an IB_CM_RTU_RECEIVED or USER_ESTABLISHED event * @ch: SRPT RDMA channel. * * An RTU (ready to use) message indicates that the connection has been * established and that the recipient may begin transmitting. */ static void srpt_cm_rtu_recv(struct srpt_rdma_ch *ch) { … } /** * srpt_cm_handler - IB connection manager callback function * @cm_id: IB/CM connection identifier. * @event: IB/CM event. * * A non-zero return value will cause the caller destroy the CM ID. * * Note: srpt_cm_handler() must only return a non-zero value when transferring * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning * a non-zero value in any other case will trigger a race with the * ib_destroy_cm_id() call in srpt_release_channel(). */ static int srpt_cm_handler(struct ib_cm_id *cm_id, const struct ib_cm_event *event) { … } static int srpt_rdma_cm_handler(struct rdma_cm_id *cm_id, struct rdma_cm_event *event) { … } /* * srpt_write_pending - Start data transfer from initiator to target (write). */ static int srpt_write_pending(struct se_cmd *se_cmd) { … } static u8 tcm_to_srp_tsk_mgmt_status(const int tcm_mgmt_status) { … } /** * srpt_queue_response - transmit the response to a SCSI command * @cmd: SCSI target command. * * Callback function called by the TCM core. Must not block since it can be * invoked on the context of the IB completion handler. */ static void srpt_queue_response(struct se_cmd *cmd) { … } static int srpt_queue_data_in(struct se_cmd *cmd) { … } static void srpt_queue_tm_rsp(struct se_cmd *cmd) { … } /* * This function is called for aborted commands if no response is sent to the * initiator. Make sure that the credits freed by aborting a command are * returned to the initiator the next time a response is sent by incrementing * ch->req_lim_delta. */ static void srpt_aborted_task(struct se_cmd *cmd) { … } static int srpt_queue_status(struct se_cmd *cmd) { … } static void srpt_refresh_port_work(struct work_struct *work) { … } /** * srpt_release_sport - disable login and wait for associated channels * @sport: SRPT HCA port. */ static int srpt_release_sport(struct srpt_port *sport) { … } struct port_and_port_id { … }; static struct port_and_port_id __srpt_lookup_port(const char *name) { … } /** * srpt_lookup_port() - Look up an RDMA port by name * @name: ASCII port name * * Increments the RDMA port reference count if an RDMA port pointer is returned. * The caller must drop that reference count by calling srpt_port_put_ref(). */ static struct port_and_port_id srpt_lookup_port(const char *name) { … } static void srpt_free_srq(struct srpt_device *sdev) { … } static int srpt_alloc_srq(struct srpt_device *sdev) { … } static int srpt_use_srq(struct srpt_device *sdev, bool use_srq) { … } static void srpt_free_sdev(struct kref *refcnt) { … } static void srpt_sdev_put(struct srpt_device *sdev) { … } /** * srpt_add_one - InfiniBand device addition callback function * @device: Describes a HCA. */ static int srpt_add_one(struct ib_device *device) { … } /** * srpt_remove_one - InfiniBand device removal callback function * @device: Describes a HCA. * @client_data: The value passed as the third argument to ib_set_client_data(). */ static void srpt_remove_one(struct ib_device *device, void *client_data) { … } static struct ib_client srpt_client = …; static int srpt_check_true(struct se_portal_group *se_tpg) { … } static struct srpt_port *srpt_tpg_to_sport(struct se_portal_group *tpg) { … } static struct srpt_port_id *srpt_wwn_to_sport_id(struct se_wwn *wwn) { … } static char *srpt_get_fabric_wwn(struct se_portal_group *tpg) { … } static u16 srpt_get_tag(struct se_portal_group *tpg) { … } static void srpt_release_cmd(struct se_cmd *se_cmd) { … } /** * srpt_close_session - forcibly close a session * @se_sess: SCSI target session. * * Callback function invoked by the TCM core to clean up sessions associated * with a node ACL when the user invokes * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id */ static void srpt_close_session(struct se_session *se_sess) { … } /* Note: only used from inside debug printk's by the TCM core. */ static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd) { … } static int srpt_parse_guid(u64 *guid, const char *name) { … } /** * srpt_parse_i_port_id - parse an initiator port ID * @name: ASCII representation of a 128-bit initiator port ID. * @i_port_id: Binary 128-bit port ID. */ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name) { … } /* * configfs callback function invoked for mkdir * /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id * * i_port_id must be an initiator port GUID, GID or IP address. See also the * target_alloc_session() calls in this driver. Examples of valid initiator * port IDs: * 0x0000000000000000505400fffe4a0b7b * 0000000000000000505400fffe4a0b7b * 5054:00ff:fe4a:0b7b * 192.168.122.76 */ static int srpt_init_nodeacl(struct se_node_acl *se_nacl, const char *name) { … } static ssize_t srpt_tpg_attrib_srp_max_rdma_size_show(struct config_item *item, char *page) { … } static ssize_t srpt_tpg_attrib_srp_max_rdma_size_store(struct config_item *item, const char *page, size_t count) { … } static ssize_t srpt_tpg_attrib_srp_max_rsp_size_show(struct config_item *item, char *page) { … } static ssize_t srpt_tpg_attrib_srp_max_rsp_size_store(struct config_item *item, const char *page, size_t count) { … } static ssize_t srpt_tpg_attrib_srp_sq_size_show(struct config_item *item, char *page) { … } static ssize_t srpt_tpg_attrib_srp_sq_size_store(struct config_item *item, const char *page, size_t count) { … } static ssize_t srpt_tpg_attrib_use_srq_show(struct config_item *item, char *page) { … } static ssize_t srpt_tpg_attrib_use_srq_store(struct config_item *item, const char *page, size_t count) { … } CONFIGFS_ATTR(…); CONFIGFS_ATTR(…); CONFIGFS_ATTR(…); CONFIGFS_ATTR(…); static struct configfs_attribute *srpt_tpg_attrib_attrs[] = …; static struct rdma_cm_id *srpt_create_rdma_id(struct sockaddr *listen_addr) { … } static ssize_t srpt_rdma_cm_port_show(struct config_item *item, char *page) { … } static ssize_t srpt_rdma_cm_port_store(struct config_item *item, const char *page, size_t count) { … } CONFIGFS_ATTR(…); static struct configfs_attribute *srpt_da_attrs[] = …; static int srpt_enable_tpg(struct se_portal_group *se_tpg, bool enable) { … } /** * srpt_make_tpg - configfs callback invoked for mkdir /sys/kernel/config/target/$driver/$port/$tpg * @wwn: Corresponds to $driver/$port. * @name: $tpg. */ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn, const char *name) { … } /** * srpt_drop_tpg - configfs callback invoked for rmdir /sys/kernel/config/target/$driver/$port/$tpg * @tpg: Target portal group to deregister. */ static void srpt_drop_tpg(struct se_portal_group *tpg) { … } /** * srpt_make_tport - configfs callback invoked for mkdir /sys/kernel/config/target/$driver/$port * @tf: Not used. * @group: Not used. * @name: $port. */ static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf, struct config_group *group, const char *name) { … } /** * srpt_drop_tport - configfs callback invoked for rmdir /sys/kernel/config/target/$driver/$port * @wwn: $port. */ static void srpt_drop_tport(struct se_wwn *wwn) { … } static ssize_t srpt_wwn_version_show(struct config_item *item, char *buf) { … } CONFIGFS_ATTR_RO(…); static struct configfs_attribute *srpt_wwn_attrs[] = …; static const struct target_core_fabric_ops srpt_template = …; /** * srpt_init_module - kernel module initialization * * Note: Since ib_register_client() registers callback functions, and since at * least one of these callback functions (srpt_add_one()) calls target core * functions, this driver must be registered with the target core before * ib_register_client() is called. */ static int __init srpt_init_module(void) { … } static void __exit srpt_cleanup_module(void) { … } module_init(…) …; module_exit(srpt_cleanup_module);