···11+config INFINIBAND_SRPT22+ tristate "InfiniBand SCSI RDMA Protocol target support"33+ depends on INFINIBAND && TARGET_CORE44+ ---help---55+66+ Support for the SCSI RDMA Protocol (SRP) Target driver. The77+ SRP protocol is a protocol that allows an initiator to access88+ a block storage device on another host (target) over a network99+ that supports the RDMA protocol. Currently the RDMA protocol is1010+ supported by InfiniBand and by iWarp network hardware. More1111+ information about the SRP protocol can be found on the website1212+ of the INCITS T10 technical committee (http://www.t10.org/).
···11+/*22+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.33+ *44+ * This software is available to you under a choice of one of two55+ * licenses. You may choose to be licensed under the terms of the GNU66+ * General Public License (GPL) Version 2, available from the file77+ * COPYING in the main directory of this source tree, or the88+ * OpenIB.org BSD license below:99+ *1010+ * Redistribution and use in source and binary forms, with or1111+ * without modification, are permitted provided that the following1212+ * conditions are met:1313+ *1414+ * - Redistributions of source code must retain the above1515+ * copyright notice, this list of conditions and the following1616+ * disclaimer.1717+ *1818+ * - Redistributions in binary form must reproduce the above1919+ * copyright notice, this list of conditions and the following2020+ * disclaimer in the documentation and/or other materials2121+ * provided with the distribution.2222+ *2323+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2424+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2525+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND2626+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS2727+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN2828+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN2929+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3030+ * SOFTWARE.3131+ *3232+ */3333+3434+#ifndef IB_DM_MAD_H3535+#define IB_DM_MAD_H3636+3737+#include <linux/types.h>3838+3939+#include <rdma/ib_mad.h>4040+4141+enum {4242+ /*4343+ * See also section 13.4.7 Status Field, table 115 MAD Common Status4444+ * Field Bit Values and also section 16.3.1.1 Status Field in the4545+ * InfiniBand Architecture Specification.4646+ */4747+ DM_MAD_STATUS_UNSUP_METHOD = 0x0008,4848+ DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c,4949+ DM_MAD_STATUS_INVALID_FIELD = 0x001c,5050+ DM_MAD_STATUS_NO_IOC = 0x0100,5151+5252+ /*5353+ * See also the Device Management chapter, section 16.3.3 Attributes,5454+ * table 279 Device Management Attributes in the InfiniBand5555+ * Architecture Specification.5656+ */5757+ DM_ATTR_CLASS_PORT_INFO = 0x01,5858+ DM_ATTR_IOU_INFO = 0x10,5959+ DM_ATTR_IOC_PROFILE = 0x11,6060+ DM_ATTR_SVC_ENTRIES = 0x126161+};6262+6363+struct ib_dm_hdr {6464+ u8 reserved[28];6565+};6666+6767+/*6868+ * Structure of management datagram sent by the SRP target implementation.6969+ * Contains a management datagram header, reliable multi-packet transaction7070+ * protocol (RMPP) header and ib_dm_hdr. Notes:7171+ * - The SRP target implementation does not use RMPP or ib_dm_hdr when sending7272+ * management datagrams.7373+ * - The header size must be exactly 64 bytes (IB_MGMT_DEVICE_HDR), since this7474+ * is the header size that is passed to ib_create_send_mad() in ib_srpt.c.7575+ * - The maximum supported size for a management datagram when not using RMPP7676+ * is 256 bytes -- 64 bytes header and 192 (IB_MGMT_DEVICE_DATA) bytes data.7777+ */7878+struct ib_dm_mad {7979+ struct ib_mad_hdr mad_hdr;8080+ struct ib_rmpp_hdr rmpp_hdr;8181+ struct ib_dm_hdr dm_hdr;8282+ u8 data[IB_MGMT_DEVICE_DATA];8383+};8484+8585+/*8686+ * IOUnitInfo as defined in section 16.3.3.3 IOUnitInfo of the InfiniBand8787+ * Architecture Specification.8888+ */8989+struct ib_dm_iou_info {9090+ __be16 change_id;9191+ u8 max_controllers;9292+ u8 op_rom;9393+ u8 controller_list[128];9494+};9595+9696+/*9797+ * IOControllerprofile as defined in section 16.3.3.4 IOControllerProfile of9898+ * the InfiniBand Architecture Specification.9999+ */100100+struct ib_dm_ioc_profile {101101+ __be64 guid;102102+ __be32 vendor_id;103103+ __be32 device_id;104104+ __be16 device_version;105105+ __be16 reserved1;106106+ __be32 subsys_vendor_id;107107+ __be32 subsys_device_id;108108+ __be16 io_class;109109+ __be16 io_subclass;110110+ __be16 protocol;111111+ __be16 protocol_version;112112+ __be16 service_conn;113113+ __be16 initiators_supported;114114+ __be16 send_queue_depth;115115+ u8 reserved2;116116+ u8 rdma_read_depth;117117+ __be32 send_size;118118+ __be32 rdma_size;119119+ u8 op_cap_mask;120120+ u8 svc_cap_mask;121121+ u8 num_svc_entries;122122+ u8 reserved3[9];123123+ u8 id_string[64];124124+};125125+126126+struct ib_dm_svc_entry {127127+ u8 name[40];128128+ __be64 id;129129+};130130+131131+/*132132+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture133133+ * Specification. See also section B.7, table B.8 in the T10 SRP r16a document.134134+ */135135+struct ib_dm_svc_entries {136136+ struct ib_dm_svc_entry service_entries[4];137137+};138138+139139+#endif
+4073
drivers/infiniband/ulp/srpt/ib_srpt.c
···11+/*22+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.33+ * Copyright (C) 2008 - 2011 Bart Van Assche <bvanassche@acm.org>.44+ *55+ * This software is available to you under a choice of one of two66+ * licenses. You may choose to be licensed under the terms of the GNU77+ * General Public License (GPL) Version 2, available from the file88+ * COPYING in the main directory of this source tree, or the99+ * OpenIB.org BSD license below:1010+ *1111+ * Redistribution and use in source and binary forms, with or1212+ * without modification, are permitted provided that the following1313+ * conditions are met:1414+ *1515+ * - Redistributions of source code must retain the above1616+ * copyright notice, this list of conditions and the following1717+ * disclaimer.1818+ *1919+ * - Redistributions in binary form must reproduce the above2020+ * copyright notice, this list of conditions and the following2121+ * disclaimer in the documentation and/or other materials2222+ * provided with the distribution.2323+ *2424+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2525+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2626+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND2727+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS2828+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN2929+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN3030+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3131+ * SOFTWARE.3232+ *3333+ */3434+3535+#include <linux/module.h>3636+#include <linux/init.h>3737+#include <linux/slab.h>3838+#include <linux/err.h>3939+#include <linux/ctype.h>4040+#include <linux/kthread.h>4141+#include <linux/string.h>4242+#include <linux/delay.h>4343+#include <linux/atomic.h>4444+#include <scsi/scsi_tcq.h>4545+#include <target/configfs_macros.h>4646+#include <target/target_core_base.h>4747+#include <target/target_core_fabric_configfs.h>4848+#include <target/target_core_fabric.h>4949+#include <target/target_core_configfs.h>5050+#include "ib_srpt.h"5151+5252+/* Name of this kernel module. */5353+#define DRV_NAME "ib_srpt"5454+#define DRV_VERSION "2.0.0"5555+#define DRV_RELDATE "2011-02-14"5656+5757+#define SRPT_ID_STRING "Linux SRP target"5858+5959+#undef pr_fmt6060+#define pr_fmt(fmt) DRV_NAME " " fmt6161+6262+MODULE_AUTHOR("Vu Pham and Bart Van Assche");6363+MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target "6464+ "v" DRV_VERSION " (" DRV_RELDATE ")");6565+MODULE_LICENSE("Dual BSD/GPL");6666+6767+/*6868+ * Global Variables6969+ */7070+7171+static u64 srpt_service_guid;7272+static spinlock_t srpt_dev_lock; /* Protects srpt_dev_list. */7373+static struct list_head srpt_dev_list; /* List of srpt_device structures. */7474+7575+static unsigned srp_max_req_size = DEFAULT_MAX_REQ_SIZE;7676+module_param(srp_max_req_size, int, 0444);7777+MODULE_PARM_DESC(srp_max_req_size,7878+ "Maximum size of SRP request messages in bytes.");7979+8080+static int srpt_srq_size = DEFAULT_SRPT_SRQ_SIZE;8181+module_param(srpt_srq_size, int, 0444);8282+MODULE_PARM_DESC(srpt_srq_size,8383+ "Shared receive queue (SRQ) size.");8484+8585+static int srpt_get_u64_x(char *buffer, struct kernel_param *kp)8686+{8787+ return sprintf(buffer, "0x%016llx", *(u64 *)kp->arg);8888+}8989+module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,9090+ 0444);9191+MODULE_PARM_DESC(srpt_service_guid,9292+ "Using this value for ioc_guid, id_ext, and cm_listen_id"9393+ " instead of using the node_guid of the first HCA.");9494+9595+static struct ib_client srpt_client;9696+static struct target_fabric_configfs *srpt_target;9797+static void srpt_release_channel(struct srpt_rdma_ch *ch);9898+static int srpt_queue_status(struct se_cmd *cmd);9999+100100+/**101101+ * opposite_dma_dir() - Swap DMA_TO_DEVICE and DMA_FROM_DEVICE.102102+ */103103+static inline104104+enum dma_data_direction opposite_dma_dir(enum dma_data_direction dir)105105+{106106+ switch (dir) {107107+ case DMA_TO_DEVICE: return DMA_FROM_DEVICE;108108+ case DMA_FROM_DEVICE: return DMA_TO_DEVICE;109109+ default: return dir;110110+ }111111+}112112+113113+/**114114+ * srpt_sdev_name() - Return the name associated with the HCA.115115+ *116116+ * Examples are ib0, ib1, ...117117+ */118118+static inline const char *srpt_sdev_name(struct srpt_device *sdev)119119+{120120+ return sdev->device->name;121121+}122122+123123+static enum rdma_ch_state srpt_get_ch_state(struct srpt_rdma_ch *ch)124124+{125125+ unsigned long flags;126126+ enum rdma_ch_state state;127127+128128+ spin_lock_irqsave(&ch->spinlock, flags);129129+ state = ch->state;130130+ spin_unlock_irqrestore(&ch->spinlock, flags);131131+ return state;132132+}133133+134134+static enum rdma_ch_state135135+srpt_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state new_state)136136+{137137+ unsigned long flags;138138+ enum rdma_ch_state prev;139139+140140+ spin_lock_irqsave(&ch->spinlock, flags);141141+ prev = ch->state;142142+ ch->state = new_state;143143+ spin_unlock_irqrestore(&ch->spinlock, flags);144144+ return prev;145145+}146146+147147+/**148148+ * srpt_test_and_set_ch_state() - Test and set the channel state.149149+ *150150+ * Returns true if and only if the channel state has been set to the new state.151151+ */152152+static bool153153+srpt_test_and_set_ch_state(struct srpt_rdma_ch *ch, enum rdma_ch_state old,154154+ enum rdma_ch_state new)155155+{156156+ unsigned long flags;157157+ enum rdma_ch_state prev;158158+159159+ spin_lock_irqsave(&ch->spinlock, flags);160160+ prev = ch->state;161161+ if (prev == old)162162+ ch->state = new;163163+ spin_unlock_irqrestore(&ch->spinlock, flags);164164+ return prev == old;165165+}166166+167167+/**168168+ * srpt_event_handler() - Asynchronous IB event callback function.169169+ *170170+ * Callback function called by the InfiniBand core when an asynchronous IB171171+ * event occurs. This callback may occur in interrupt context. See also172172+ * section 11.5.2, Set Asynchronous Event Handler in the InfiniBand173173+ * Architecture Specification.174174+ */175175+static void srpt_event_handler(struct ib_event_handler *handler,176176+ struct ib_event *event)177177+{178178+ struct srpt_device *sdev;179179+ struct srpt_port *sport;180180+181181+ sdev = ib_get_client_data(event->device, &srpt_client);182182+ if (!sdev || sdev->device != event->device)183183+ return;184184+185185+ pr_debug("ASYNC event= %d on device= %s\n", event->event,186186+ srpt_sdev_name(sdev));187187+188188+ switch (event->event) {189189+ case IB_EVENT_PORT_ERR:190190+ if (event->element.port_num <= sdev->device->phys_port_cnt) {191191+ sport = &sdev->port[event->element.port_num - 1];192192+ sport->lid = 0;193193+ sport->sm_lid = 0;194194+ }195195+ break;196196+ case IB_EVENT_PORT_ACTIVE:197197+ case IB_EVENT_LID_CHANGE:198198+ case IB_EVENT_PKEY_CHANGE:199199+ case IB_EVENT_SM_CHANGE:200200+ case IB_EVENT_CLIENT_REREGISTER:201201+ /* Refresh port data asynchronously. */202202+ if (event->element.port_num <= sdev->device->phys_port_cnt) {203203+ sport = &sdev->port[event->element.port_num - 1];204204+ if (!sport->lid && !sport->sm_lid)205205+ schedule_work(&sport->work);206206+ }207207+ break;208208+ default:209209+ printk(KERN_ERR "received unrecognized IB event %d\n",210210+ event->event);211211+ break;212212+ }213213+}214214+215215+/**216216+ * srpt_srq_event() - SRQ event callback function.217217+ */218218+static void srpt_srq_event(struct ib_event *event, void *ctx)219219+{220220+ printk(KERN_INFO "SRQ event %d\n", event->event);221221+}222222+223223+/**224224+ * srpt_qp_event() - QP event callback function.225225+ */226226+static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)227227+{228228+ pr_debug("QP event %d on cm_id=%p sess_name=%s state=%d\n",229229+ event->event, ch->cm_id, ch->sess_name, srpt_get_ch_state(ch));230230+231231+ switch (event->event) {232232+ case IB_EVENT_COMM_EST:233233+ ib_cm_notify(ch->cm_id, event->event);234234+ break;235235+ case IB_EVENT_QP_LAST_WQE_REACHED:236236+ if (srpt_test_and_set_ch_state(ch, CH_DRAINING,237237+ CH_RELEASING))238238+ srpt_release_channel(ch);239239+ else240240+ pr_debug("%s: state %d - ignored LAST_WQE.\n",241241+ ch->sess_name, srpt_get_ch_state(ch));242242+ break;243243+ default:244244+ printk(KERN_ERR "received unrecognized IB QP event %d\n",245245+ event->event);246246+ break;247247+ }248248+}249249+250250+/**251251+ * srpt_set_ioc() - Helper function for initializing an IOUnitInfo structure.252252+ *253253+ * @slot: one-based slot number.254254+ * @value: four-bit value.255255+ *256256+ * Copies the lowest four bits of value in element slot of the array of four257257+ * bit elements called c_list (controller list). The index slot is one-based.258258+ */259259+static void srpt_set_ioc(u8 *c_list, u32 slot, u8 value)260260+{261261+ u16 id;262262+ u8 tmp;263263+264264+ id = (slot - 1) / 2;265265+ if (slot & 0x1) {266266+ tmp = c_list[id] & 0xf;267267+ c_list[id] = (value << 4) | tmp;268268+ } else {269269+ tmp = c_list[id] & 0xf0;270270+ c_list[id] = (value & 0xf) | tmp;271271+ }272272+}273273+274274+/**275275+ * srpt_get_class_port_info() - Copy ClassPortInfo to a management datagram.276276+ *277277+ * See also section 16.3.3.1 ClassPortInfo in the InfiniBand Architecture278278+ * Specification.279279+ */280280+static void srpt_get_class_port_info(struct ib_dm_mad *mad)281281+{282282+ struct ib_class_port_info *cif;283283+284284+ cif = (struct ib_class_port_info *)mad->data;285285+ memset(cif, 0, sizeof *cif);286286+ cif->base_version = 1;287287+ cif->class_version = 1;288288+ cif->resp_time_value = 20;289289+290290+ mad->mad_hdr.status = 0;291291+}292292+293293+/**294294+ * srpt_get_iou() - Write IOUnitInfo to a management datagram.295295+ *296296+ * See also section 16.3.3.3 IOUnitInfo in the InfiniBand Architecture297297+ * Specification. See also section B.7, table B.6 in the SRP r16a document.298298+ */299299+static void srpt_get_iou(struct ib_dm_mad *mad)300300+{301301+ struct ib_dm_iou_info *ioui;302302+ u8 slot;303303+ int i;304304+305305+ ioui = (struct ib_dm_iou_info *)mad->data;306306+ ioui->change_id = __constant_cpu_to_be16(1);307307+ ioui->max_controllers = 16;308308+309309+ /* set present for slot 1 and empty for the rest */310310+ srpt_set_ioc(ioui->controller_list, 1, 1);311311+ for (i = 1, slot = 2; i < 16; i++, slot++)312312+ srpt_set_ioc(ioui->controller_list, slot, 0);313313+314314+ mad->mad_hdr.status = 0;315315+}316316+317317+/**318318+ * srpt_get_ioc() - Write IOControllerprofile to a management datagram.319319+ *320320+ * See also section 16.3.3.4 IOControllerProfile in the InfiniBand321321+ * Architecture Specification. See also section B.7, table B.7 in the SRP322322+ * r16a document.323323+ */324324+static void srpt_get_ioc(struct srpt_port *sport, u32 slot,325325+ struct ib_dm_mad *mad)326326+{327327+ struct srpt_device *sdev = sport->sdev;328328+ struct ib_dm_ioc_profile *iocp;329329+330330+ iocp = (struct ib_dm_ioc_profile *)mad->data;331331+332332+ if (!slot || slot > 16) {333333+ mad->mad_hdr.status334334+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);335335+ return;336336+ }337337+338338+ if (slot > 2) {339339+ mad->mad_hdr.status340340+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);341341+ return;342342+ }343343+344344+ memset(iocp, 0, sizeof *iocp);345345+ strcpy(iocp->id_string, SRPT_ID_STRING);346346+ iocp->guid = cpu_to_be64(srpt_service_guid);347347+ iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);348348+ iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id);349349+ iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver);350350+ iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id);351351+ iocp->subsys_device_id = 0x0;352352+ iocp->io_class = __constant_cpu_to_be16(SRP_REV16A_IB_IO_CLASS);353353+ iocp->io_subclass = __constant_cpu_to_be16(SRP_IO_SUBCLASS);354354+ iocp->protocol = __constant_cpu_to_be16(SRP_PROTOCOL);355355+ iocp->protocol_version = __constant_cpu_to_be16(SRP_PROTOCOL_VERSION);356356+ iocp->send_queue_depth = cpu_to_be16(sdev->srq_size);357357+ iocp->rdma_read_depth = 4;358358+ iocp->send_size = cpu_to_be32(srp_max_req_size);359359+ iocp->rdma_size = cpu_to_be32(min(sport->port_attrib.srp_max_rdma_size,360360+ 1U << 24));361361+ iocp->num_svc_entries = 1;362362+ iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC |363363+ SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC;364364+365365+ mad->mad_hdr.status = 0;366366+}367367+368368+/**369369+ * srpt_get_svc_entries() - Write ServiceEntries to a management datagram.370370+ *371371+ * See also section 16.3.3.5 ServiceEntries in the InfiniBand Architecture372372+ * Specification. See also section B.7, table B.8 in the SRP r16a document.373373+ */374374+static void srpt_get_svc_entries(u64 ioc_guid,375375+ u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad)376376+{377377+ struct ib_dm_svc_entries *svc_entries;378378+379379+ WARN_ON(!ioc_guid);380380+381381+ if (!slot || slot > 16) {382382+ mad->mad_hdr.status383383+ = __constant_cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD);384384+ return;385385+ }386386+387387+ if (slot > 2 || lo > hi || hi > 1) {388388+ mad->mad_hdr.status389389+ = __constant_cpu_to_be16(DM_MAD_STATUS_NO_IOC);390390+ return;391391+ }392392+393393+ svc_entries = (struct ib_dm_svc_entries *)mad->data;394394+ memset(svc_entries, 0, sizeof *svc_entries);395395+ svc_entries->service_entries[0].id = cpu_to_be64(ioc_guid);396396+ snprintf(svc_entries->service_entries[0].name,397397+ sizeof(svc_entries->service_entries[0].name),398398+ "%s%016llx",399399+ SRP_SERVICE_NAME_PREFIX,400400+ ioc_guid);401401+402402+ mad->mad_hdr.status = 0;403403+}404404+405405+/**406406+ * srpt_mgmt_method_get() - Process a received management datagram.407407+ * @sp: source port through which the MAD has been received.408408+ * @rq_mad: received MAD.409409+ * @rsp_mad: response MAD.410410+ */411411+static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad,412412+ struct ib_dm_mad *rsp_mad)413413+{414414+ u16 attr_id;415415+ u32 slot;416416+ u8 hi, lo;417417+418418+ attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id);419419+ switch (attr_id) {420420+ case DM_ATTR_CLASS_PORT_INFO:421421+ srpt_get_class_port_info(rsp_mad);422422+ break;423423+ case DM_ATTR_IOU_INFO:424424+ srpt_get_iou(rsp_mad);425425+ break;426426+ case DM_ATTR_IOC_PROFILE:427427+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);428428+ srpt_get_ioc(sp, slot, rsp_mad);429429+ break;430430+ case DM_ATTR_SVC_ENTRIES:431431+ slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod);432432+ hi = (u8) ((slot >> 8) & 0xff);433433+ lo = (u8) (slot & 0xff);434434+ slot = (u16) ((slot >> 16) & 0xffff);435435+ srpt_get_svc_entries(srpt_service_guid,436436+ slot, hi, lo, rsp_mad);437437+ break;438438+ default:439439+ rsp_mad->mad_hdr.status =440440+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);441441+ break;442442+ }443443+}444444+445445+/**446446+ * srpt_mad_send_handler() - Post MAD-send callback function.447447+ */448448+static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent,449449+ struct ib_mad_send_wc *mad_wc)450450+{451451+ ib_destroy_ah(mad_wc->send_buf->ah);452452+ ib_free_send_mad(mad_wc->send_buf);453453+}454454+455455+/**456456+ * srpt_mad_recv_handler() - MAD reception callback function.457457+ */458458+static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent,459459+ struct ib_mad_recv_wc *mad_wc)460460+{461461+ struct srpt_port *sport = (struct srpt_port *)mad_agent->context;462462+ struct ib_ah *ah;463463+ struct ib_mad_send_buf *rsp;464464+ struct ib_dm_mad *dm_mad;465465+466466+ if (!mad_wc || !mad_wc->recv_buf.mad)467467+ return;468468+469469+ ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc,470470+ mad_wc->recv_buf.grh, mad_agent->port_num);471471+ if (IS_ERR(ah))472472+ goto err;473473+474474+ BUILD_BUG_ON(offsetof(struct ib_dm_mad, data) != IB_MGMT_DEVICE_HDR);475475+476476+ rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp,477477+ mad_wc->wc->pkey_index, 0,478478+ IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA,479479+ GFP_KERNEL);480480+ if (IS_ERR(rsp))481481+ goto err_rsp;482482+483483+ rsp->ah = ah;484484+485485+ dm_mad = rsp->mad;486486+ memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad);487487+ dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;488488+ dm_mad->mad_hdr.status = 0;489489+490490+ switch (mad_wc->recv_buf.mad->mad_hdr.method) {491491+ case IB_MGMT_METHOD_GET:492492+ srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad);493493+ break;494494+ case IB_MGMT_METHOD_SET:495495+ dm_mad->mad_hdr.status =496496+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR);497497+ break;498498+ default:499499+ dm_mad->mad_hdr.status =500500+ __constant_cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD);501501+ break;502502+ }503503+504504+ if (!ib_post_send_mad(rsp, NULL)) {505505+ ib_free_recv_mad(mad_wc);506506+ /* will destroy_ah & free_send_mad in send completion */507507+ return;508508+ }509509+510510+ ib_free_send_mad(rsp);511511+512512+err_rsp:513513+ ib_destroy_ah(ah);514514+err:515515+ ib_free_recv_mad(mad_wc);516516+}517517+518518+/**519519+ * srpt_refresh_port() - Configure a HCA port.520520+ *521521+ * Enable InfiniBand management datagram processing, update the cached sm_lid,522522+ * lid and gid values, and register a callback function for processing MADs523523+ * on the specified port.524524+ *525525+ * Note: It is safe to call this function more than once for the same port.526526+ */527527+static int srpt_refresh_port(struct srpt_port *sport)528528+{529529+ struct ib_mad_reg_req reg_req;530530+ struct ib_port_modify port_modify;531531+ struct ib_port_attr port_attr;532532+ int ret;533533+534534+ memset(&port_modify, 0, sizeof port_modify);535535+ port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;536536+ port_modify.clr_port_cap_mask = 0;537537+538538+ ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);539539+ if (ret)540540+ goto err_mod_port;541541+542542+ ret = ib_query_port(sport->sdev->device, sport->port, &port_attr);543543+ if (ret)544544+ goto err_query_port;545545+546546+ sport->sm_lid = port_attr.sm_lid;547547+ sport->lid = port_attr.lid;548548+549549+ ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid);550550+ if (ret)551551+ goto err_query_port;552552+553553+ if (!sport->mad_agent) {554554+ memset(®_req, 0, sizeof reg_req);555555+ reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT;556556+ reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION;557557+ set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask);558558+ set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask);559559+560560+ sport->mad_agent = ib_register_mad_agent(sport->sdev->device,561561+ sport->port,562562+ IB_QPT_GSI,563563+ ®_req, 0,564564+ srpt_mad_send_handler,565565+ srpt_mad_recv_handler,566566+ sport);567567+ if (IS_ERR(sport->mad_agent)) {568568+ ret = PTR_ERR(sport->mad_agent);569569+ sport->mad_agent = NULL;570570+ goto err_query_port;571571+ }572572+ }573573+574574+ return 0;575575+576576+err_query_port:577577+578578+ port_modify.set_port_cap_mask = 0;579579+ port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP;580580+ ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify);581581+582582+err_mod_port:583583+584584+ return ret;585585+}586586+587587+/**588588+ * srpt_unregister_mad_agent() - Unregister MAD callback functions.589589+ *590590+ * Note: It is safe to call this function more than once for the same device.591591+ */592592+static void srpt_unregister_mad_agent(struct srpt_device *sdev)593593+{594594+ struct ib_port_modify port_modify = {595595+ .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP,596596+ };597597+ struct srpt_port *sport;598598+ int i;599599+600600+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {601601+ sport = &sdev->port[i - 1];602602+ WARN_ON(sport->port != i);603603+ if (ib_modify_port(sdev->device, i, 0, &port_modify) < 0)604604+ printk(KERN_ERR "disabling MAD processing failed.\n");605605+ if (sport->mad_agent) {606606+ ib_unregister_mad_agent(sport->mad_agent);607607+ sport->mad_agent = NULL;608608+ }609609+ }610610+}611611+612612+/**613613+ * srpt_alloc_ioctx() - Allocate an SRPT I/O context structure.614614+ */615615+static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev,616616+ int ioctx_size, int dma_size,617617+ enum dma_data_direction dir)618618+{619619+ struct srpt_ioctx *ioctx;620620+621621+ ioctx = kmalloc(ioctx_size, GFP_KERNEL);622622+ if (!ioctx)623623+ goto err;624624+625625+ ioctx->buf = kmalloc(dma_size, GFP_KERNEL);626626+ if (!ioctx->buf)627627+ goto err_free_ioctx;628628+629629+ ioctx->dma = ib_dma_map_single(sdev->device, ioctx->buf, dma_size, dir);630630+ if (ib_dma_mapping_error(sdev->device, ioctx->dma))631631+ goto err_free_buf;632632+633633+ return ioctx;634634+635635+err_free_buf:636636+ kfree(ioctx->buf);637637+err_free_ioctx:638638+ kfree(ioctx);639639+err:640640+ return NULL;641641+}642642+643643+/**644644+ * srpt_free_ioctx() - Free an SRPT I/O context structure.645645+ */646646+static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx,647647+ int dma_size, enum dma_data_direction dir)648648+{649649+ if (!ioctx)650650+ return;651651+652652+ ib_dma_unmap_single(sdev->device, ioctx->dma, dma_size, dir);653653+ kfree(ioctx->buf);654654+ kfree(ioctx);655655+}656656+657657+/**658658+ * srpt_alloc_ioctx_ring() - Allocate a ring of SRPT I/O context structures.659659+ * @sdev: Device to allocate the I/O context ring for.660660+ * @ring_size: Number of elements in the I/O context ring.661661+ * @ioctx_size: I/O context size.662662+ * @dma_size: DMA buffer size.663663+ * @dir: DMA data direction.664664+ */665665+static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,666666+ int ring_size, int ioctx_size,667667+ int dma_size, enum dma_data_direction dir)668668+{669669+ struct srpt_ioctx **ring;670670+ int i;671671+672672+ WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)673673+ && ioctx_size != sizeof(struct srpt_send_ioctx));674674+675675+ ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);676676+ if (!ring)677677+ goto out;678678+ for (i = 0; i < ring_size; ++i) {679679+ ring[i] = srpt_alloc_ioctx(sdev, ioctx_size, dma_size, dir);680680+ if (!ring[i])681681+ goto err;682682+ ring[i]->index = i;683683+ }684684+ goto out;685685+686686+err:687687+ while (--i >= 0)688688+ srpt_free_ioctx(sdev, ring[i], dma_size, dir);689689+ kfree(ring);690690+out:691691+ return ring;692692+}693693+694694+/**695695+ * srpt_free_ioctx_ring() - Free the ring of SRPT I/O context structures.696696+ */697697+static void srpt_free_ioctx_ring(struct srpt_ioctx **ioctx_ring,698698+ struct srpt_device *sdev, int ring_size,699699+ int dma_size, enum dma_data_direction dir)700700+{701701+ int i;702702+703703+ for (i = 0; i < ring_size; ++i)704704+ srpt_free_ioctx(sdev, ioctx_ring[i], dma_size, dir);705705+ kfree(ioctx_ring);706706+}707707+708708+/**709709+ * srpt_get_cmd_state() - Get the state of a SCSI command.710710+ */711711+static enum srpt_command_state srpt_get_cmd_state(struct srpt_send_ioctx *ioctx)712712+{713713+ enum srpt_command_state state;714714+ unsigned long flags;715715+716716+ BUG_ON(!ioctx);717717+718718+ spin_lock_irqsave(&ioctx->spinlock, flags);719719+ state = ioctx->state;720720+ spin_unlock_irqrestore(&ioctx->spinlock, flags);721721+ return state;722722+}723723+724724+/**725725+ * srpt_set_cmd_state() - Set the state of a SCSI command.726726+ *727727+ * Does not modify the state of aborted commands. Returns the previous command728728+ * state.729729+ */730730+static enum srpt_command_state srpt_set_cmd_state(struct srpt_send_ioctx *ioctx,731731+ enum srpt_command_state new)732732+{733733+ enum srpt_command_state previous;734734+ unsigned long flags;735735+736736+ BUG_ON(!ioctx);737737+738738+ spin_lock_irqsave(&ioctx->spinlock, flags);739739+ previous = ioctx->state;740740+ if (previous != SRPT_STATE_DONE)741741+ ioctx->state = new;742742+ spin_unlock_irqrestore(&ioctx->spinlock, flags);743743+744744+ return previous;745745+}746746+747747+/**748748+ * srpt_test_and_set_cmd_state() - Test and set the state of a command.749749+ *750750+ * Returns true if and only if the previous command state was equal to 'old'.751751+ */752752+static bool srpt_test_and_set_cmd_state(struct srpt_send_ioctx *ioctx,753753+ enum srpt_command_state old,754754+ enum srpt_command_state new)755755+{756756+ enum srpt_command_state previous;757757+ unsigned long flags;758758+759759+ WARN_ON(!ioctx);760760+ WARN_ON(old == SRPT_STATE_DONE);761761+ WARN_ON(new == SRPT_STATE_NEW);762762+763763+ spin_lock_irqsave(&ioctx->spinlock, flags);764764+ previous = ioctx->state;765765+ if (previous == old)766766+ ioctx->state = new;767767+ spin_unlock_irqrestore(&ioctx->spinlock, flags);768768+ return previous == old;769769+}770770+771771+/**772772+ * srpt_post_recv() - Post an IB receive request.773773+ */774774+static int srpt_post_recv(struct srpt_device *sdev,775775+ struct srpt_recv_ioctx *ioctx)776776+{777777+ struct ib_sge list;778778+ struct ib_recv_wr wr, *bad_wr;779779+780780+ BUG_ON(!sdev);781781+ wr.wr_id = encode_wr_id(SRPT_RECV, ioctx->ioctx.index);782782+783783+ list.addr = ioctx->ioctx.dma;784784+ list.length = srp_max_req_size;785785+ list.lkey = sdev->mr->lkey;786786+787787+ wr.next = NULL;788788+ wr.sg_list = &list;789789+ wr.num_sge = 1;790790+791791+ return ib_post_srq_recv(sdev->srq, &wr, &bad_wr);792792+}793793+794794+/**795795+ * srpt_post_send() - Post an IB send request.796796+ *797797+ * Returns zero upon success and a non-zero value upon failure.798798+ */799799+static int srpt_post_send(struct srpt_rdma_ch *ch,800800+ struct srpt_send_ioctx *ioctx, int len)801801+{802802+ struct ib_sge list;803803+ struct ib_send_wr wr, *bad_wr;804804+ struct srpt_device *sdev = ch->sport->sdev;805805+ int ret;806806+807807+ atomic_inc(&ch->req_lim);808808+809809+ ret = -ENOMEM;810810+ if (unlikely(atomic_dec_return(&ch->sq_wr_avail) < 0)) {811811+ printk(KERN_WARNING "IB send queue full (needed 1)\n");812812+ goto out;813813+ }814814+815815+ ib_dma_sync_single_for_device(sdev->device, ioctx->ioctx.dma, len,816816+ DMA_TO_DEVICE);817817+818818+ list.addr = ioctx->ioctx.dma;819819+ list.length = len;820820+ list.lkey = sdev->mr->lkey;821821+822822+ wr.next = NULL;823823+ wr.wr_id = encode_wr_id(SRPT_SEND, ioctx->ioctx.index);824824+ wr.sg_list = &list;825825+ wr.num_sge = 1;826826+ wr.opcode = IB_WR_SEND;827827+ wr.send_flags = IB_SEND_SIGNALED;828828+829829+ ret = ib_post_send(ch->qp, &wr, &bad_wr);830830+831831+out:832832+ if (ret < 0) {833833+ atomic_inc(&ch->sq_wr_avail);834834+ atomic_dec(&ch->req_lim);835835+ }836836+ return ret;837837+}838838+839839+/**840840+ * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request.841841+ * @ioctx: Pointer to the I/O context associated with the request.842842+ * @srp_cmd: Pointer to the SRP_CMD request data.843843+ * @dir: Pointer to the variable to which the transfer direction will be844844+ * written.845845+ * @data_len: Pointer to the variable to which the total data length of all846846+ * descriptors in the SRP_CMD request will be written.847847+ *848848+ * This function initializes ioctx->nrbuf and ioctx->r_bufs.849849+ *850850+ * Returns -EINVAL when the SRP_CMD request contains inconsistent descriptors;851851+ * -ENOMEM when memory allocation fails and zero upon success.852852+ */853853+static int srpt_get_desc_tbl(struct srpt_send_ioctx *ioctx,854854+ struct srp_cmd *srp_cmd,855855+ enum dma_data_direction *dir, u64 *data_len)856856+{857857+ struct srp_indirect_buf *idb;858858+ struct srp_direct_buf *db;859859+ unsigned add_cdb_offset;860860+ int ret;861861+862862+ /*863863+ * The pointer computations below will only be compiled correctly864864+ * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check865865+ * whether srp_cmd::add_data has been declared as a byte pointer.866866+ */867867+ BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)868868+ && !__same_type(srp_cmd->add_data[0], (u8)0));869869+870870+ BUG_ON(!dir);871871+ BUG_ON(!data_len);872872+873873+ ret = 0;874874+ *data_len = 0;875875+876876+ /*877877+ * The lower four bits of the buffer format field contain the DATA-IN878878+ * buffer descriptor format, and the highest four bits contain the879879+ * DATA-OUT buffer descriptor format.880880+ */881881+ *dir = DMA_NONE;882882+ if (srp_cmd->buf_fmt & 0xf)883883+ /* DATA-IN: transfer data from target to initiator (read). */884884+ *dir = DMA_FROM_DEVICE;885885+ else if (srp_cmd->buf_fmt >> 4)886886+ /* DATA-OUT: transfer data from initiator to target (write). */887887+ *dir = DMA_TO_DEVICE;888888+889889+ /*890890+ * According to the SRP spec, the lower two bits of the 'ADDITIONAL891891+ * CDB LENGTH' field are reserved and the size in bytes of this field892892+ * is four times the value specified in bits 3..7. Hence the "& ~3".893893+ */894894+ add_cdb_offset = srp_cmd->add_cdb_len & ~3;895895+ if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||896896+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {897897+ ioctx->n_rbuf = 1;898898+ ioctx->rbufs = &ioctx->single_rbuf;899899+900900+ db = (struct srp_direct_buf *)(srp_cmd->add_data901901+ + add_cdb_offset);902902+ memcpy(ioctx->rbufs, db, sizeof *db);903903+ *data_len = be32_to_cpu(db->len);904904+ } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||905905+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {906906+ idb = (struct srp_indirect_buf *)(srp_cmd->add_data907907+ + add_cdb_offset);908908+909909+ ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db;910910+911911+ if (ioctx->n_rbuf >912912+ (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) {913913+ printk(KERN_ERR "received unsupported SRP_CMD request"914914+ " type (%u out + %u in != %u / %zu)\n",915915+ srp_cmd->data_out_desc_cnt,916916+ srp_cmd->data_in_desc_cnt,917917+ be32_to_cpu(idb->table_desc.len),918918+ sizeof(*db));919919+ ioctx->n_rbuf = 0;920920+ ret = -EINVAL;921921+ goto out;922922+ }923923+924924+ if (ioctx->n_rbuf == 1)925925+ ioctx->rbufs = &ioctx->single_rbuf;926926+ else {927927+ ioctx->rbufs =928928+ kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC);929929+ if (!ioctx->rbufs) {930930+ ioctx->n_rbuf = 0;931931+ ret = -ENOMEM;932932+ goto out;933933+ }934934+ }935935+936936+ db = idb->desc_list;937937+ memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db);938938+ *data_len = be32_to_cpu(idb->len);939939+ }940940+out:941941+ return ret;942942+}943943+944944+/**945945+ * srpt_init_ch_qp() - Initialize queue pair attributes.946946+ *947947+ * Initialized the attributes of queue pair 'qp' by allowing local write,948948+ * remote read and remote write. Also transitions 'qp' to state IB_QPS_INIT.949949+ */950950+static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp)951951+{952952+ struct ib_qp_attr *attr;953953+ int ret;954954+955955+ attr = kzalloc(sizeof *attr, GFP_KERNEL);956956+ if (!attr)957957+ return -ENOMEM;958958+959959+ attr->qp_state = IB_QPS_INIT;960960+ attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ |961961+ IB_ACCESS_REMOTE_WRITE;962962+ attr->port_num = ch->sport->port;963963+ attr->pkey_index = 0;964964+965965+ ret = ib_modify_qp(qp, attr,966966+ IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT |967967+ IB_QP_PKEY_INDEX);968968+969969+ kfree(attr);970970+ return ret;971971+}972972+973973+/**974974+ * srpt_ch_qp_rtr() - Change the state of a channel to 'ready to receive' (RTR).975975+ * @ch: channel of the queue pair.976976+ * @qp: queue pair to change the state of.977977+ *978978+ * Returns zero upon success and a negative value upon failure.979979+ *980980+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.981981+ * If this structure ever becomes larger, it might be necessary to allocate982982+ * it dynamically instead of on the stack.983983+ */984984+static int srpt_ch_qp_rtr(struct srpt_rdma_ch *ch, struct ib_qp *qp)985985+{986986+ struct ib_qp_attr qp_attr;987987+ int attr_mask;988988+ int ret;989989+990990+ qp_attr.qp_state = IB_QPS_RTR;991991+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);992992+ if (ret)993993+ goto out;994994+995995+ qp_attr.max_dest_rd_atomic = 4;996996+997997+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);998998+999999+out:10001000+ return ret;10011001+}10021002+10031003+/**10041004+ * srpt_ch_qp_rts() - Change the state of a channel to 'ready to send' (RTS).10051005+ * @ch: channel of the queue pair.10061006+ * @qp: queue pair to change the state of.10071007+ *10081008+ * Returns zero upon success and a negative value upon failure.10091009+ *10101010+ * Note: currently a struct ib_qp_attr takes 136 bytes on a 64-bit system.10111011+ * If this structure ever becomes larger, it might be necessary to allocate10121012+ * it dynamically instead of on the stack.10131013+ */10141014+static int srpt_ch_qp_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp)10151015+{10161016+ struct ib_qp_attr qp_attr;10171017+ int attr_mask;10181018+ int ret;10191019+10201020+ qp_attr.qp_state = IB_QPS_RTS;10211021+ ret = ib_cm_init_qp_attr(ch->cm_id, &qp_attr, &attr_mask);10221022+ if (ret)10231023+ goto out;10241024+10251025+ qp_attr.max_rd_atomic = 4;10261026+10271027+ ret = ib_modify_qp(qp, &qp_attr, attr_mask);10281028+10291029+out:10301030+ return ret;10311031+}10321032+10331033+/**10341034+ * srpt_ch_qp_err() - Set the channel queue pair state to 'error'.10351035+ */10361036+static int srpt_ch_qp_err(struct srpt_rdma_ch *ch)10371037+{10381038+ struct ib_qp_attr qp_attr;10391039+10401040+ qp_attr.qp_state = IB_QPS_ERR;10411041+ return ib_modify_qp(ch->qp, &qp_attr, IB_QP_STATE);10421042+}10431043+10441044+/**10451045+ * srpt_unmap_sg_to_ib_sge() - Unmap an IB SGE list.10461046+ */10471047+static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch,10481048+ struct srpt_send_ioctx *ioctx)10491049+{10501050+ struct scatterlist *sg;10511051+ enum dma_data_direction dir;10521052+10531053+ BUG_ON(!ch);10541054+ BUG_ON(!ioctx);10551055+ BUG_ON(ioctx->n_rdma && !ioctx->rdma_ius);10561056+10571057+ while (ioctx->n_rdma)10581058+ kfree(ioctx->rdma_ius[--ioctx->n_rdma].sge);10591059+10601060+ kfree(ioctx->rdma_ius);10611061+ ioctx->rdma_ius = NULL;10621062+10631063+ if (ioctx->mapped_sg_count) {10641064+ sg = ioctx->sg;10651065+ WARN_ON(!sg);10661066+ dir = ioctx->cmd.data_direction;10671067+ BUG_ON(dir == DMA_NONE);10681068+ ib_dma_unmap_sg(ch->sport->sdev->device, sg, ioctx->sg_cnt,10691069+ opposite_dma_dir(dir));10701070+ ioctx->mapped_sg_count = 0;10711071+ }10721072+}10731073+10741074+/**10751075+ * srpt_map_sg_to_ib_sge() - Map an SG list to an IB SGE list.10761076+ */10771077+static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch,10781078+ struct srpt_send_ioctx *ioctx)10791079+{10801080+ struct se_cmd *cmd;10811081+ struct scatterlist *sg, *sg_orig;10821082+ int sg_cnt;10831083+ enum dma_data_direction dir;10841084+ struct rdma_iu *riu;10851085+ struct srp_direct_buf *db;10861086+ dma_addr_t dma_addr;10871087+ struct ib_sge *sge;10881088+ u64 raddr;10891089+ u32 rsize;10901090+ u32 tsize;10911091+ u32 dma_len;10921092+ int count, nrdma;10931093+ int i, j, k;10941094+10951095+ BUG_ON(!ch);10961096+ BUG_ON(!ioctx);10971097+ cmd = &ioctx->cmd;10981098+ dir = cmd->data_direction;10991099+ BUG_ON(dir == DMA_NONE);11001100+11011101+ transport_do_task_sg_chain(cmd);11021102+ ioctx->sg = sg = sg_orig = cmd->t_tasks_sg_chained;11031103+ ioctx->sg_cnt = sg_cnt = cmd->t_tasks_sg_chained_no;11041104+11051105+ count = ib_dma_map_sg(ch->sport->sdev->device, sg, sg_cnt,11061106+ opposite_dma_dir(dir));11071107+ if (unlikely(!count))11081108+ return -EAGAIN;11091109+11101110+ ioctx->mapped_sg_count = count;11111111+11121112+ if (ioctx->rdma_ius && ioctx->n_rdma_ius)11131113+ nrdma = ioctx->n_rdma_ius;11141114+ else {11151115+ nrdma = (count + SRPT_DEF_SG_PER_WQE - 1) / SRPT_DEF_SG_PER_WQE11161116+ + ioctx->n_rbuf;11171117+11181118+ ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu, GFP_KERNEL);11191119+ if (!ioctx->rdma_ius)11201120+ goto free_mem;11211121+11221122+ ioctx->n_rdma_ius = nrdma;11231123+ }11241124+11251125+ db = ioctx->rbufs;11261126+ tsize = cmd->data_length;11271127+ dma_len = sg_dma_len(&sg[0]);11281128+ riu = ioctx->rdma_ius;11291129+11301130+ /*11311131+ * For each remote desc - calculate the #ib_sge.11321132+ * If #ib_sge < SRPT_DEF_SG_PER_WQE per rdma operation then11331133+ * each remote desc rdma_iu is required a rdma wr;11341134+ * else11351135+ * we need to allocate extra rdma_iu to carry extra #ib_sge in11361136+ * another rdma wr11371137+ */11381138+ for (i = 0, j = 0;11391139+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {11401140+ rsize = be32_to_cpu(db->len);11411141+ raddr = be64_to_cpu(db->va);11421142+ riu->raddr = raddr;11431143+ riu->rkey = be32_to_cpu(db->key);11441144+ riu->sge_cnt = 0;11451145+11461146+ /* calculate how many sge required for this remote_buf */11471147+ while (rsize > 0 && tsize > 0) {11481148+11491149+ if (rsize >= dma_len) {11501150+ tsize -= dma_len;11511151+ rsize -= dma_len;11521152+ raddr += dma_len;11531153+11541154+ if (tsize > 0) {11551155+ ++j;11561156+ if (j < count) {11571157+ sg = sg_next(sg);11581158+ dma_len = sg_dma_len(sg);11591159+ }11601160+ }11611161+ } else {11621162+ tsize -= rsize;11631163+ dma_len -= rsize;11641164+ rsize = 0;11651165+ }11661166+11671167+ ++riu->sge_cnt;11681168+11691169+ if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_PER_WQE) {11701170+ ++ioctx->n_rdma;11711171+ riu->sge =11721172+ kmalloc(riu->sge_cnt * sizeof *riu->sge,11731173+ GFP_KERNEL);11741174+ if (!riu->sge)11751175+ goto free_mem;11761176+11771177+ ++riu;11781178+ riu->sge_cnt = 0;11791179+ riu->raddr = raddr;11801180+ riu->rkey = be32_to_cpu(db->key);11811181+ }11821182+ }11831183+11841184+ ++ioctx->n_rdma;11851185+ riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge,11861186+ GFP_KERNEL);11871187+ if (!riu->sge)11881188+ goto free_mem;11891189+ }11901190+11911191+ db = ioctx->rbufs;11921192+ tsize = cmd->data_length;11931193+ riu = ioctx->rdma_ius;11941194+ sg = sg_orig;11951195+ dma_len = sg_dma_len(&sg[0]);11961196+ dma_addr = sg_dma_address(&sg[0]);11971197+11981198+ /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */11991199+ for (i = 0, j = 0;12001200+ j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) {12011201+ rsize = be32_to_cpu(db->len);12021202+ sge = riu->sge;12031203+ k = 0;12041204+12051205+ while (rsize > 0 && tsize > 0) {12061206+ sge->addr = dma_addr;12071207+ sge->lkey = ch->sport->sdev->mr->lkey;12081208+12091209+ if (rsize >= dma_len) {12101210+ sge->length =12111211+ (tsize < dma_len) ? tsize : dma_len;12121212+ tsize -= dma_len;12131213+ rsize -= dma_len;12141214+12151215+ if (tsize > 0) {12161216+ ++j;12171217+ if (j < count) {12181218+ sg = sg_next(sg);12191219+ dma_len = sg_dma_len(sg);12201220+ dma_addr = sg_dma_address(sg);12211221+ }12221222+ }12231223+ } else {12241224+ sge->length = (tsize < rsize) ? tsize : rsize;12251225+ tsize -= rsize;12261226+ dma_len -= rsize;12271227+ dma_addr += rsize;12281228+ rsize = 0;12291229+ }12301230+12311231+ ++k;12321232+ if (k == riu->sge_cnt && rsize > 0 && tsize > 0) {12331233+ ++riu;12341234+ sge = riu->sge;12351235+ k = 0;12361236+ } else if (rsize > 0 && tsize > 0)12371237+ ++sge;12381238+ }12391239+ }12401240+12411241+ return 0;12421242+12431243+free_mem:12441244+ srpt_unmap_sg_to_ib_sge(ch, ioctx);12451245+12461246+ return -ENOMEM;12471247+}12481248+12491249+/**12501250+ * srpt_get_send_ioctx() - Obtain an I/O context for sending to the initiator.12511251+ */12521252+static struct srpt_send_ioctx *srpt_get_send_ioctx(struct srpt_rdma_ch *ch)12531253+{12541254+ struct srpt_send_ioctx *ioctx;12551255+ unsigned long flags;12561256+12571257+ BUG_ON(!ch);12581258+12591259+ ioctx = NULL;12601260+ spin_lock_irqsave(&ch->spinlock, flags);12611261+ if (!list_empty(&ch->free_list)) {12621262+ ioctx = list_first_entry(&ch->free_list,12631263+ struct srpt_send_ioctx, free_list);12641264+ list_del(&ioctx->free_list);12651265+ }12661266+ spin_unlock_irqrestore(&ch->spinlock, flags);12671267+12681268+ if (!ioctx)12691269+ return ioctx;12701270+12711271+ BUG_ON(ioctx->ch != ch);12721272+ kref_init(&ioctx->kref);12731273+ spin_lock_init(&ioctx->spinlock);12741274+ ioctx->state = SRPT_STATE_NEW;12751275+ ioctx->n_rbuf = 0;12761276+ ioctx->rbufs = NULL;12771277+ ioctx->n_rdma = 0;12781278+ ioctx->n_rdma_ius = 0;12791279+ ioctx->rdma_ius = NULL;12801280+ ioctx->mapped_sg_count = 0;12811281+ init_completion(&ioctx->tx_done);12821282+ ioctx->queue_status_only = false;12831283+ /*12841284+ * transport_init_se_cmd() does not initialize all fields, so do it12851285+ * here.12861286+ */12871287+ memset(&ioctx->cmd, 0, sizeof(ioctx->cmd));12881288+ memset(&ioctx->sense_data, 0, sizeof(ioctx->sense_data));12891289+12901290+ return ioctx;12911291+}12921292+12931293+/**12941294+ * srpt_put_send_ioctx() - Free up resources.12951295+ */12961296+static void srpt_put_send_ioctx(struct srpt_send_ioctx *ioctx)12971297+{12981298+ struct srpt_rdma_ch *ch;12991299+ unsigned long flags;13001300+13011301+ BUG_ON(!ioctx);13021302+ ch = ioctx->ch;13031303+ BUG_ON(!ch);13041304+13051305+ WARN_ON(srpt_get_cmd_state(ioctx) != SRPT_STATE_DONE);13061306+13071307+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);13081308+ transport_generic_free_cmd(&ioctx->cmd, 0);13091309+13101310+ if (ioctx->n_rbuf > 1) {13111311+ kfree(ioctx->rbufs);13121312+ ioctx->rbufs = NULL;13131313+ ioctx->n_rbuf = 0;13141314+ }13151315+13161316+ spin_lock_irqsave(&ch->spinlock, flags);13171317+ list_add(&ioctx->free_list, &ch->free_list);13181318+ spin_unlock_irqrestore(&ch->spinlock, flags);13191319+}13201320+13211321+static void srpt_put_send_ioctx_kref(struct kref *kref)13221322+{13231323+ srpt_put_send_ioctx(container_of(kref, struct srpt_send_ioctx, kref));13241324+}13251325+13261326+/**13271327+ * srpt_abort_cmd() - Abort a SCSI command.13281328+ * @ioctx: I/O context associated with the SCSI command.13291329+ * @context: Preferred execution context.13301330+ */13311331+static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)13321332+{13331333+ enum srpt_command_state state;13341334+ unsigned long flags;13351335+13361336+ BUG_ON(!ioctx);13371337+13381338+ /*13391339+ * If the command is in a state where the target core is waiting for13401340+ * the ib_srpt driver, change the state to the next state. Changing13411341+ * the state of the command from SRPT_STATE_NEED_DATA to13421342+ * SRPT_STATE_DATA_IN ensures that srpt_xmit_response() will call this13431343+ * function a second time.13441344+ */13451345+13461346+ spin_lock_irqsave(&ioctx->spinlock, flags);13471347+ state = ioctx->state;13481348+ switch (state) {13491349+ case SRPT_STATE_NEED_DATA:13501350+ ioctx->state = SRPT_STATE_DATA_IN;13511351+ break;13521352+ case SRPT_STATE_DATA_IN:13531353+ case SRPT_STATE_CMD_RSP_SENT:13541354+ case SRPT_STATE_MGMT_RSP_SENT:13551355+ ioctx->state = SRPT_STATE_DONE;13561356+ break;13571357+ default:13581358+ break;13591359+ }13601360+ spin_unlock_irqrestore(&ioctx->spinlock, flags);13611361+13621362+ if (state == SRPT_STATE_DONE)13631363+ goto out;13641364+13651365+ pr_debug("Aborting cmd with state %d and tag %lld\n", state,13661366+ ioctx->tag);13671367+13681368+ switch (state) {13691369+ case SRPT_STATE_NEW:13701370+ case SRPT_STATE_DATA_IN:13711371+ case SRPT_STATE_MGMT:13721372+ /*13731373+ * Do nothing - defer abort processing until13741374+ * srpt_queue_response() is invoked.13751375+ */13761376+ WARN_ON(!transport_check_aborted_status(&ioctx->cmd, false));13771377+ break;13781378+ case SRPT_STATE_NEED_DATA:13791379+ /* DMA_TO_DEVICE (write) - RDMA read error. */13801380+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);13811381+ transport_generic_handle_data(&ioctx->cmd);13821382+ break;13831383+ case SRPT_STATE_CMD_RSP_SENT:13841384+ /*13851385+ * SRP_RSP sending failed or the SRP_RSP send completion has13861386+ * not been received in time.13871387+ */13881388+ srpt_unmap_sg_to_ib_sge(ioctx->ch, ioctx);13891389+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);13901390+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);13911391+ break;13921392+ case SRPT_STATE_MGMT_RSP_SENT:13931393+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);13941394+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);13951395+ break;13961396+ default:13971397+ WARN_ON("ERROR: unexpected command state");13981398+ break;13991399+ }14001400+14011401+out:14021402+ return state;14031403+}14041404+14051405+/**14061406+ * srpt_handle_send_err_comp() - Process an IB_WC_SEND error completion.14071407+ */14081408+static void srpt_handle_send_err_comp(struct srpt_rdma_ch *ch, u64 wr_id)14091409+{14101410+ struct srpt_send_ioctx *ioctx;14111411+ enum srpt_command_state state;14121412+ struct se_cmd *cmd;14131413+ u32 index;14141414+14151415+ atomic_inc(&ch->sq_wr_avail);14161416+14171417+ index = idx_from_wr_id(wr_id);14181418+ ioctx = ch->ioctx_ring[index];14191419+ state = srpt_get_cmd_state(ioctx);14201420+ cmd = &ioctx->cmd;14211421+14221422+ WARN_ON(state != SRPT_STATE_CMD_RSP_SENT14231423+ && state != SRPT_STATE_MGMT_RSP_SENT14241424+ && state != SRPT_STATE_NEED_DATA14251425+ && state != SRPT_STATE_DONE);14261426+14271427+ /* If SRP_RSP sending failed, undo the ch->req_lim change. */14281428+ if (state == SRPT_STATE_CMD_RSP_SENT14291429+ || state == SRPT_STATE_MGMT_RSP_SENT)14301430+ atomic_dec(&ch->req_lim);14311431+14321432+ srpt_abort_cmd(ioctx);14331433+}14341434+14351435+/**14361436+ * srpt_handle_send_comp() - Process an IB send completion notification.14371437+ */14381438+static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,14391439+ struct srpt_send_ioctx *ioctx)14401440+{14411441+ enum srpt_command_state state;14421442+14431443+ atomic_inc(&ch->sq_wr_avail);14441444+14451445+ state = srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);14461446+14471447+ if (WARN_ON(state != SRPT_STATE_CMD_RSP_SENT14481448+ && state != SRPT_STATE_MGMT_RSP_SENT14491449+ && state != SRPT_STATE_DONE))14501450+ pr_debug("state = %d\n", state);14511451+14521452+ if (state != SRPT_STATE_DONE)14531453+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);14541454+ else14551455+ printk(KERN_ERR "IB completion has been received too late for"14561456+ " wr_id = %u.\n", ioctx->ioctx.index);14571457+}14581458+14591459+/**14601460+ * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.14611461+ *14621462+ * Note: transport_generic_handle_data() is asynchronous so unmapping the14631463+ * data that has been transferred via IB RDMA must be postponed until the14641464+ * check_stop_free() callback.14651465+ */14661466+static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,14671467+ struct srpt_send_ioctx *ioctx,14681468+ enum srpt_opcode opcode)14691469+{14701470+ WARN_ON(ioctx->n_rdma <= 0);14711471+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);14721472+14731473+ if (opcode == SRPT_RDMA_READ_LAST) {14741474+ if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,14751475+ SRPT_STATE_DATA_IN))14761476+ transport_generic_handle_data(&ioctx->cmd);14771477+ else14781478+ printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,14791479+ __LINE__, srpt_get_cmd_state(ioctx));14801480+ } else if (opcode == SRPT_RDMA_ABORT) {14811481+ ioctx->rdma_aborted = true;14821482+ } else {14831483+ WARN(true, "unexpected opcode %d\n", opcode);14841484+ }14851485+}14861486+14871487+/**14881488+ * srpt_handle_rdma_err_comp() - Process an IB RDMA error completion.14891489+ */14901490+static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,14911491+ struct srpt_send_ioctx *ioctx,14921492+ enum srpt_opcode opcode)14931493+{14941494+ struct se_cmd *cmd;14951495+ enum srpt_command_state state;14961496+14971497+ cmd = &ioctx->cmd;14981498+ state = srpt_get_cmd_state(ioctx);14991499+ switch (opcode) {15001500+ case SRPT_RDMA_READ_LAST:15011501+ if (ioctx->n_rdma <= 0) {15021502+ printk(KERN_ERR "Received invalid RDMA read"15031503+ " error completion with idx %d\n",15041504+ ioctx->ioctx.index);15051505+ break;15061506+ }15071507+ atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);15081508+ if (state == SRPT_STATE_NEED_DATA)15091509+ srpt_abort_cmd(ioctx);15101510+ else15111511+ printk(KERN_ERR "%s[%d]: wrong state = %d\n",15121512+ __func__, __LINE__, state);15131513+ break;15141514+ case SRPT_RDMA_WRITE_LAST:15151515+ atomic_set(&ioctx->cmd.transport_lun_stop, 1);15161516+ break;15171517+ default:15181518+ printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__,15191519+ __LINE__, opcode);15201520+ break;15211521+ }15221522+}15231523+15241524+/**15251525+ * srpt_build_cmd_rsp() - Build an SRP_RSP response.15261526+ * @ch: RDMA channel through which the request has been received.15271527+ * @ioctx: I/O context associated with the SRP_CMD request. The response will15281528+ * be built in the buffer ioctx->buf points at and hence this function will15291529+ * overwrite the request data.15301530+ * @tag: tag of the request for which this response is being generated.15311531+ * @status: value for the STATUS field of the SRP_RSP information unit.15321532+ *15331533+ * Returns the size in bytes of the SRP_RSP response.15341534+ *15351535+ * An SRP_RSP response contains a SCSI status or service response. See also15361536+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP15371537+ * response. See also SPC-2 for more information about sense data.15381538+ */15391539+static int srpt_build_cmd_rsp(struct srpt_rdma_ch *ch,15401540+ struct srpt_send_ioctx *ioctx, u64 tag,15411541+ int status)15421542+{15431543+ struct srp_rsp *srp_rsp;15441544+ const u8 *sense_data;15451545+ int sense_data_len, max_sense_len;15461546+15471547+ /*15481548+ * The lowest bit of all SAM-3 status codes is zero (see also15491549+ * paragraph 5.3 in SAM-3).15501550+ */15511551+ WARN_ON(status & 1);15521552+15531553+ srp_rsp = ioctx->ioctx.buf;15541554+ BUG_ON(!srp_rsp);15551555+15561556+ sense_data = ioctx->sense_data;15571557+ sense_data_len = ioctx->cmd.scsi_sense_length;15581558+ WARN_ON(sense_data_len > sizeof(ioctx->sense_data));15591559+15601560+ memset(srp_rsp, 0, sizeof *srp_rsp);15611561+ srp_rsp->opcode = SRP_RSP;15621562+ srp_rsp->req_lim_delta =15631563+ __constant_cpu_to_be32(1 + atomic_xchg(&ch->req_lim_delta, 0));15641564+ srp_rsp->tag = tag;15651565+ srp_rsp->status = status;15661566+15671567+ if (sense_data_len) {15681568+ BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));15691569+ max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);15701570+ if (sense_data_len > max_sense_len) {15711571+ printk(KERN_WARNING "truncated sense data from %d to %d"15721572+ " bytes\n", sense_data_len, max_sense_len);15731573+ sense_data_len = max_sense_len;15741574+ }15751575+15761576+ srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID;15771577+ srp_rsp->sense_data_len = cpu_to_be32(sense_data_len);15781578+ memcpy(srp_rsp + 1, sense_data, sense_data_len);15791579+ }15801580+15811581+ return sizeof(*srp_rsp) + sense_data_len;15821582+}15831583+15841584+/**15851585+ * srpt_build_tskmgmt_rsp() - Build a task management response.15861586+ * @ch: RDMA channel through which the request has been received.15871587+ * @ioctx: I/O context in which the SRP_RSP response will be built.15881588+ * @rsp_code: RSP_CODE that will be stored in the response.15891589+ * @tag: Tag of the request for which this response is being generated.15901590+ *15911591+ * Returns the size in bytes of the SRP_RSP response.15921592+ *15931593+ * An SRP_RSP response contains a SCSI status or service response. See also15941594+ * section 6.9 in the SRP r16a document for the format of an SRP_RSP15951595+ * response.15961596+ */15971597+static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,15981598+ struct srpt_send_ioctx *ioctx,15991599+ u8 rsp_code, u64 tag)16001600+{16011601+ struct srp_rsp *srp_rsp;16021602+ int resp_data_len;16031603+ int resp_len;16041604+16051605+ resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;16061606+ resp_len = sizeof(*srp_rsp) + resp_data_len;16071607+16081608+ srp_rsp = ioctx->ioctx.buf;16091609+ BUG_ON(!srp_rsp);16101610+ memset(srp_rsp, 0, sizeof *srp_rsp);16111611+16121612+ srp_rsp->opcode = SRP_RSP;16131613+ srp_rsp->req_lim_delta = __constant_cpu_to_be32(116141614+ + atomic_xchg(&ch->req_lim_delta, 0));16151615+ srp_rsp->tag = tag;16161616+16171617+ if (rsp_code != SRP_TSK_MGMT_SUCCESS) {16181618+ srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;16191619+ srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);16201620+ srp_rsp->data[3] = rsp_code;16211621+ }16221622+16231623+ return resp_len;16241624+}16251625+16261626+#define NO_SUCH_LUN ((uint64_t)-1LL)16271627+16281628+/*16291629+ * SCSI LUN addressing method. See also SAM-2 and the section about16301630+ * eight byte LUNs.16311631+ */16321632+enum scsi_lun_addr_method {16331633+ SCSI_LUN_ADDR_METHOD_PERIPHERAL = 0,16341634+ SCSI_LUN_ADDR_METHOD_FLAT = 1,16351635+ SCSI_LUN_ADDR_METHOD_LUN = 2,16361636+ SCSI_LUN_ADDR_METHOD_EXTENDED_LUN = 3,16371637+};16381638+16391639+/*16401640+ * srpt_unpack_lun() - Convert from network LUN to linear LUN.16411641+ *16421642+ * Convert an 2-byte, 4-byte, 6-byte or 8-byte LUN structure in network byte16431643+ * order (big endian) to a linear LUN. Supports three LUN addressing methods:16441644+ * peripheral, flat and logical unit. See also SAM-2, section 4.9.4 (page 40).16451645+ */16461646+static uint64_t srpt_unpack_lun(const uint8_t *lun, int len)16471647+{16481648+ uint64_t res = NO_SUCH_LUN;16491649+ int addressing_method;16501650+16511651+ if (unlikely(len < 2)) {16521652+ printk(KERN_ERR "Illegal LUN length %d, expected 2 bytes or "16531653+ "more", len);16541654+ goto out;16551655+ }16561656+16571657+ switch (len) {16581658+ case 8:16591659+ if ((*((__be64 *)lun) &16601660+ __constant_cpu_to_be64(0x0000FFFFFFFFFFFFLL)) != 0)16611661+ goto out_err;16621662+ break;16631663+ case 4:16641664+ if (*((__be16 *)&lun[2]) != 0)16651665+ goto out_err;16661666+ break;16671667+ case 6:16681668+ if (*((__be32 *)&lun[2]) != 0)16691669+ goto out_err;16701670+ break;16711671+ case 2:16721672+ break;16731673+ default:16741674+ goto out_err;16751675+ }16761676+16771677+ addressing_method = (*lun) >> 6; /* highest two bits of byte 0 */16781678+ switch (addressing_method) {16791679+ case SCSI_LUN_ADDR_METHOD_PERIPHERAL:16801680+ case SCSI_LUN_ADDR_METHOD_FLAT:16811681+ case SCSI_LUN_ADDR_METHOD_LUN:16821682+ res = *(lun + 1) | (((*lun) & 0x3f) << 8);16831683+ break;16841684+16851685+ case SCSI_LUN_ADDR_METHOD_EXTENDED_LUN:16861686+ default:16871687+ printk(KERN_ERR "Unimplemented LUN addressing method %u",16881688+ addressing_method);16891689+ break;16901690+ }16911691+16921692+out:16931693+ return res;16941694+16951695+out_err:16961696+ printk(KERN_ERR "Support for multi-level LUNs has not yet been"16971697+ " implemented");16981698+ goto out;16991699+}17001700+17011701+static int srpt_check_stop_free(struct se_cmd *cmd)17021702+{17031703+ struct srpt_send_ioctx *ioctx;17041704+17051705+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);17061706+ return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);17071707+}17081708+17091709+/**17101710+ * srpt_handle_cmd() - Process SRP_CMD.17111711+ */17121712+static int srpt_handle_cmd(struct srpt_rdma_ch *ch,17131713+ struct srpt_recv_ioctx *recv_ioctx,17141714+ struct srpt_send_ioctx *send_ioctx)17151715+{17161716+ struct se_cmd *cmd;17171717+ struct srp_cmd *srp_cmd;17181718+ uint64_t unpacked_lun;17191719+ u64 data_len;17201720+ enum dma_data_direction dir;17211721+ int ret;17221722+17231723+ BUG_ON(!send_ioctx);17241724+17251725+ srp_cmd = recv_ioctx->ioctx.buf;17261726+ kref_get(&send_ioctx->kref);17271727+ cmd = &send_ioctx->cmd;17281728+ send_ioctx->tag = srp_cmd->tag;17291729+17301730+ switch (srp_cmd->task_attr) {17311731+ case SRP_CMD_SIMPLE_Q:17321732+ cmd->sam_task_attr = MSG_SIMPLE_TAG;17331733+ break;17341734+ case SRP_CMD_ORDERED_Q:17351735+ default:17361736+ cmd->sam_task_attr = MSG_ORDERED_TAG;17371737+ break;17381738+ case SRP_CMD_HEAD_OF_Q:17391739+ cmd->sam_task_attr = MSG_HEAD_TAG;17401740+ break;17411741+ case SRP_CMD_ACA:17421742+ cmd->sam_task_attr = MSG_ACA_TAG;17431743+ break;17441744+ }17451745+17461746+ ret = srpt_get_desc_tbl(send_ioctx, srp_cmd, &dir, &data_len);17471747+ if (ret) {17481748+ printk(KERN_ERR "0x%llx: parsing SRP descriptor table failed.\n",17491749+ srp_cmd->tag);17501750+ cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;17511751+ cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;17521752+ goto send_sense;17531753+ }17541754+17551755+ cmd->data_length = data_len;17561756+ cmd->data_direction = dir;17571757+ unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun,17581758+ sizeof(srp_cmd->lun));17591759+ if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0)17601760+ goto send_sense;17611761+ ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb);17621762+ if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)17631763+ srpt_queue_status(cmd);17641764+ else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION)17651765+ goto send_sense;17661766+ else17671767+ WARN_ON_ONCE(ret);17681768+17691769+ transport_handle_cdb_direct(cmd);17701770+ return 0;17711771+17721772+send_sense:17731773+ transport_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason,17741774+ 0);17751775+ return -1;17761776+}17771777+17781778+/**17791779+ * srpt_rx_mgmt_fn_tag() - Process a task management function by tag.17801780+ * @ch: RDMA channel of the task management request.17811781+ * @fn: Task management function to perform.17821782+ * @req_tag: Tag of the SRP task management request.17831783+ * @mgmt_ioctx: I/O context of the task management request.17841784+ *17851785+ * Returns zero if the target core will process the task management17861786+ * request asynchronously.17871787+ *17881788+ * Note: It is assumed that the initiator serializes tag-based task management17891789+ * requests.17901790+ */17911791+static int srpt_rx_mgmt_fn_tag(struct srpt_send_ioctx *ioctx, u64 tag)17921792+{17931793+ struct srpt_device *sdev;17941794+ struct srpt_rdma_ch *ch;17951795+ struct srpt_send_ioctx *target;17961796+ int ret, i;17971797+17981798+ ret = -EINVAL;17991799+ ch = ioctx->ch;18001800+ BUG_ON(!ch);18011801+ BUG_ON(!ch->sport);18021802+ sdev = ch->sport->sdev;18031803+ BUG_ON(!sdev);18041804+ spin_lock_irq(&sdev->spinlock);18051805+ for (i = 0; i < ch->rq_size; ++i) {18061806+ target = ch->ioctx_ring[i];18071807+ if (target->cmd.se_lun == ioctx->cmd.se_lun &&18081808+ target->tag == tag &&18091809+ srpt_get_cmd_state(target) != SRPT_STATE_DONE) {18101810+ ret = 0;18111811+ /* now let the target core abort &target->cmd; */18121812+ break;18131813+ }18141814+ }18151815+ spin_unlock_irq(&sdev->spinlock);18161816+ return ret;18171817+}18181818+18191819+static int srp_tmr_to_tcm(int fn)18201820+{18211821+ switch (fn) {18221822+ case SRP_TSK_ABORT_TASK:18231823+ return TMR_ABORT_TASK;18241824+ case SRP_TSK_ABORT_TASK_SET:18251825+ return TMR_ABORT_TASK_SET;18261826+ case SRP_TSK_CLEAR_TASK_SET:18271827+ return TMR_CLEAR_TASK_SET;18281828+ case SRP_TSK_LUN_RESET:18291829+ return TMR_LUN_RESET;18301830+ case SRP_TSK_CLEAR_ACA:18311831+ return TMR_CLEAR_ACA;18321832+ default:18331833+ return -1;18341834+ }18351835+}18361836+18371837+/**18381838+ * srpt_handle_tsk_mgmt() - Process an SRP_TSK_MGMT information unit.18391839+ *18401840+ * Returns 0 if and only if the request will be processed by the target core.18411841+ *18421842+ * For more information about SRP_TSK_MGMT information units, see also section18431843+ * 6.7 in the SRP r16a document.18441844+ */18451845+static void srpt_handle_tsk_mgmt(struct srpt_rdma_ch *ch,18461846+ struct srpt_recv_ioctx *recv_ioctx,18471847+ struct srpt_send_ioctx *send_ioctx)18481848+{18491849+ struct srp_tsk_mgmt *srp_tsk;18501850+ struct se_cmd *cmd;18511851+ uint64_t unpacked_lun;18521852+ int tcm_tmr;18531853+ int res;18541854+18551855+ BUG_ON(!send_ioctx);18561856+18571857+ srp_tsk = recv_ioctx->ioctx.buf;18581858+ cmd = &send_ioctx->cmd;18591859+18601860+ pr_debug("recv tsk_mgmt fn %d for task_tag %lld and cmd tag %lld"18611861+ " cm_id %p sess %p\n", srp_tsk->tsk_mgmt_func,18621862+ srp_tsk->task_tag, srp_tsk->tag, ch->cm_id, ch->sess);18631863+18641864+ srpt_set_cmd_state(send_ioctx, SRPT_STATE_MGMT);18651865+ send_ioctx->tag = srp_tsk->tag;18661866+ tcm_tmr = srp_tmr_to_tcm(srp_tsk->tsk_mgmt_func);18671867+ if (tcm_tmr < 0) {18681868+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;18691869+ send_ioctx->cmd.se_tmr_req->response =18701870+ TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;18711871+ goto process_tmr;18721872+ }18731873+ cmd->se_tmr_req = core_tmr_alloc_req(cmd, NULL, tcm_tmr, GFP_KERNEL);18741874+ if (!cmd->se_tmr_req) {18751875+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;18761876+ send_ioctx->cmd.se_tmr_req->response = TMR_FUNCTION_REJECTED;18771877+ goto process_tmr;18781878+ }18791879+18801880+ unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_tsk->lun,18811881+ sizeof(srp_tsk->lun));18821882+ res = transport_lookup_tmr_lun(&send_ioctx->cmd, unpacked_lun);18831883+ if (res) {18841884+ pr_debug("rejecting TMR for LUN %lld\n", unpacked_lun);18851885+ send_ioctx->cmd.se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;18861886+ send_ioctx->cmd.se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;18871887+ goto process_tmr;18881888+ }18891889+18901890+ if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK)18911891+ srpt_rx_mgmt_fn_tag(send_ioctx, srp_tsk->task_tag);18921892+18931893+process_tmr:18941894+ kref_get(&send_ioctx->kref);18951895+ if (!(send_ioctx->cmd.se_cmd_flags & SCF_SCSI_CDB_EXCEPTION))18961896+ transport_generic_handle_tmr(&send_ioctx->cmd);18971897+ else18981898+ transport_send_check_condition_and_sense(cmd,18991899+ cmd->scsi_sense_reason, 0);19001900+19011901+}19021902+19031903+/**19041904+ * srpt_handle_new_iu() - Process a newly received information unit.19051905+ * @ch: RDMA channel through which the information unit has been received.19061906+ * @ioctx: SRPT I/O context associated with the information unit.19071907+ */19081908+static void srpt_handle_new_iu(struct srpt_rdma_ch *ch,19091909+ struct srpt_recv_ioctx *recv_ioctx,19101910+ struct srpt_send_ioctx *send_ioctx)19111911+{19121912+ struct srp_cmd *srp_cmd;19131913+ enum rdma_ch_state ch_state;19141914+19151915+ BUG_ON(!ch);19161916+ BUG_ON(!recv_ioctx);19171917+19181918+ ib_dma_sync_single_for_cpu(ch->sport->sdev->device,19191919+ recv_ioctx->ioctx.dma, srp_max_req_size,19201920+ DMA_FROM_DEVICE);19211921+19221922+ ch_state = srpt_get_ch_state(ch);19231923+ if (unlikely(ch_state == CH_CONNECTING)) {19241924+ list_add_tail(&recv_ioctx->wait_list, &ch->cmd_wait_list);19251925+ goto out;19261926+ }19271927+19281928+ if (unlikely(ch_state != CH_LIVE))19291929+ goto out;19301930+19311931+ srp_cmd = recv_ioctx->ioctx.buf;19321932+ if (srp_cmd->opcode == SRP_CMD || srp_cmd->opcode == SRP_TSK_MGMT) {19331933+ if (!send_ioctx)19341934+ send_ioctx = srpt_get_send_ioctx(ch);19351935+ if (unlikely(!send_ioctx)) {19361936+ list_add_tail(&recv_ioctx->wait_list,19371937+ &ch->cmd_wait_list);19381938+ goto out;19391939+ }19401940+ }19411941+19421942+ transport_init_se_cmd(&send_ioctx->cmd, &srpt_target->tf_ops, ch->sess,19431943+ 0, DMA_NONE, MSG_SIMPLE_TAG,19441944+ send_ioctx->sense_data);19451945+19461946+ switch (srp_cmd->opcode) {19471947+ case SRP_CMD:19481948+ srpt_handle_cmd(ch, recv_ioctx, send_ioctx);19491949+ break;19501950+ case SRP_TSK_MGMT:19511951+ srpt_handle_tsk_mgmt(ch, recv_ioctx, send_ioctx);19521952+ break;19531953+ case SRP_I_LOGOUT:19541954+ printk(KERN_ERR "Not yet implemented: SRP_I_LOGOUT\n");19551955+ break;19561956+ case SRP_CRED_RSP:19571957+ pr_debug("received SRP_CRED_RSP\n");19581958+ break;19591959+ case SRP_AER_RSP:19601960+ pr_debug("received SRP_AER_RSP\n");19611961+ break;19621962+ case SRP_RSP:19631963+ printk(KERN_ERR "Received SRP_RSP\n");19641964+ break;19651965+ default:19661966+ printk(KERN_ERR "received IU with unknown opcode 0x%x\n",19671967+ srp_cmd->opcode);19681968+ break;19691969+ }19701970+19711971+ srpt_post_recv(ch->sport->sdev, recv_ioctx);19721972+out:19731973+ return;19741974+}19751975+19761976+static void srpt_process_rcv_completion(struct ib_cq *cq,19771977+ struct srpt_rdma_ch *ch,19781978+ struct ib_wc *wc)19791979+{19801980+ struct srpt_device *sdev = ch->sport->sdev;19811981+ struct srpt_recv_ioctx *ioctx;19821982+ u32 index;19831983+19841984+ index = idx_from_wr_id(wc->wr_id);19851985+ if (wc->status == IB_WC_SUCCESS) {19861986+ int req_lim;19871987+19881988+ req_lim = atomic_dec_return(&ch->req_lim);19891989+ if (unlikely(req_lim < 0))19901990+ printk(KERN_ERR "req_lim = %d < 0\n", req_lim);19911991+ ioctx = sdev->ioctx_ring[index];19921992+ srpt_handle_new_iu(ch, ioctx, NULL);19931993+ } else {19941994+ printk(KERN_INFO "receiving failed for idx %u with status %d\n",19951995+ index, wc->status);19961996+ }19971997+}19981998+19991999+/**20002000+ * srpt_process_send_completion() - Process an IB send completion.20012001+ *20022002+ * Note: Although this has not yet been observed during tests, at least in20032003+ * theory it is possible that the srpt_get_send_ioctx() call invoked by20042004+ * srpt_handle_new_iu() fails. This is possible because the req_lim_delta20052005+ * value in each response is set to one, and it is possible that this response20062006+ * makes the initiator send a new request before the send completion for that20072007+ * response has been processed. This could e.g. happen if the call to20082008+ * srpt_put_send_iotcx() is delayed because of a higher priority interrupt or20092009+ * if IB retransmission causes generation of the send completion to be20102010+ * delayed. Incoming information units for which srpt_get_send_ioctx() fails20112011+ * are queued on cmd_wait_list. The code below processes these delayed20122012+ * requests one at a time.20132013+ */20142014+static void srpt_process_send_completion(struct ib_cq *cq,20152015+ struct srpt_rdma_ch *ch,20162016+ struct ib_wc *wc)20172017+{20182018+ struct srpt_send_ioctx *send_ioctx;20192019+ uint32_t index;20202020+ enum srpt_opcode opcode;20212021+20222022+ index = idx_from_wr_id(wc->wr_id);20232023+ opcode = opcode_from_wr_id(wc->wr_id);20242024+ send_ioctx = ch->ioctx_ring[index];20252025+ if (wc->status == IB_WC_SUCCESS) {20262026+ if (opcode == SRPT_SEND)20272027+ srpt_handle_send_comp(ch, send_ioctx);20282028+ else {20292029+ WARN_ON(opcode != SRPT_RDMA_ABORT &&20302030+ wc->opcode != IB_WC_RDMA_READ);20312031+ srpt_handle_rdma_comp(ch, send_ioctx, opcode);20322032+ }20332033+ } else {20342034+ if (opcode == SRPT_SEND) {20352035+ printk(KERN_INFO "sending response for idx %u failed"20362036+ " with status %d\n", index, wc->status);20372037+ srpt_handle_send_err_comp(ch, wc->wr_id);20382038+ } else if (opcode != SRPT_RDMA_MID) {20392039+ printk(KERN_INFO "RDMA t %d for idx %u failed with"20402040+ " status %d", opcode, index, wc->status);20412041+ srpt_handle_rdma_err_comp(ch, send_ioctx, opcode);20422042+ }20432043+ }20442044+20452045+ while (unlikely(opcode == SRPT_SEND20462046+ && !list_empty(&ch->cmd_wait_list)20472047+ && srpt_get_ch_state(ch) == CH_LIVE20482048+ && (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {20492049+ struct srpt_recv_ioctx *recv_ioctx;20502050+20512051+ recv_ioctx = list_first_entry(&ch->cmd_wait_list,20522052+ struct srpt_recv_ioctx,20532053+ wait_list);20542054+ list_del(&recv_ioctx->wait_list);20552055+ srpt_handle_new_iu(ch, recv_ioctx, send_ioctx);20562056+ }20572057+}20582058+20592059+static void srpt_process_completion(struct ib_cq *cq, struct srpt_rdma_ch *ch)20602060+{20612061+ struct ib_wc *const wc = ch->wc;20622062+ int i, n;20632063+20642064+ WARN_ON(cq != ch->cq);20652065+20662066+ ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);20672067+ while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {20682068+ for (i = 0; i < n; i++) {20692069+ if (opcode_from_wr_id(wc[i].wr_id) == SRPT_RECV)20702070+ srpt_process_rcv_completion(cq, ch, &wc[i]);20712071+ else20722072+ srpt_process_send_completion(cq, ch, &wc[i]);20732073+ }20742074+ }20752075+}20762076+20772077+/**20782078+ * srpt_completion() - IB completion queue callback function.20792079+ *20802080+ * Notes:20812081+ * - It is guaranteed that a completion handler will never be invoked20822082+ * concurrently on two different CPUs for the same completion queue. See also20832083+ * Documentation/infiniband/core_locking.txt and the implementation of20842084+ * handle_edge_irq() in kernel/irq/chip.c.20852085+ * - When threaded IRQs are enabled, completion handlers are invoked in thread20862086+ * context instead of interrupt context.20872087+ */20882088+static void srpt_completion(struct ib_cq *cq, void *ctx)20892089+{20902090+ struct srpt_rdma_ch *ch = ctx;20912091+20922092+ wake_up_interruptible(&ch->wait_queue);20932093+}20942094+20952095+static int srpt_compl_thread(void *arg)20962096+{20972097+ struct srpt_rdma_ch *ch;20982098+20992099+ /* Hibernation / freezing of the SRPT kernel thread is not supported. */21002100+ current->flags |= PF_NOFREEZE;21012101+21022102+ ch = arg;21032103+ BUG_ON(!ch);21042104+ printk(KERN_INFO "Session %s: kernel thread %s (PID %d) started\n",21052105+ ch->sess_name, ch->thread->comm, current->pid);21062106+ while (!kthread_should_stop()) {21072107+ wait_event_interruptible(ch->wait_queue,21082108+ (srpt_process_completion(ch->cq, ch),21092109+ kthread_should_stop()));21102110+ }21112111+ printk(KERN_INFO "Session %s: kernel thread %s (PID %d) stopped\n",21122112+ ch->sess_name, ch->thread->comm, current->pid);21132113+ return 0;21142114+}21152115+21162116+/**21172117+ * srpt_create_ch_ib() - Create receive and send completion queues.21182118+ */21192119+static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)21202120+{21212121+ struct ib_qp_init_attr *qp_init;21222122+ struct srpt_port *sport = ch->sport;21232123+ struct srpt_device *sdev = sport->sdev;21242124+ u32 srp_sq_size = sport->port_attrib.srp_sq_size;21252125+ int ret;21262126+21272127+ WARN_ON(ch->rq_size < 1);21282128+21292129+ ret = -ENOMEM;21302130+ qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL);21312131+ if (!qp_init)21322132+ goto out;21332133+21342134+ ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,21352135+ ch->rq_size + srp_sq_size, 0);21362136+ if (IS_ERR(ch->cq)) {21372137+ ret = PTR_ERR(ch->cq);21382138+ printk(KERN_ERR "failed to create CQ cqe= %d ret= %d\n",21392139+ ch->rq_size + srp_sq_size, ret);21402140+ goto out;21412141+ }21422142+21432143+ qp_init->qp_context = (void *)ch;21442144+ qp_init->event_handler21452145+ = (void(*)(struct ib_event *, void*))srpt_qp_event;21462146+ qp_init->send_cq = ch->cq;21472147+ qp_init->recv_cq = ch->cq;21482148+ qp_init->srq = sdev->srq;21492149+ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;21502150+ qp_init->qp_type = IB_QPT_RC;21512151+ qp_init->cap.max_send_wr = srp_sq_size;21522152+ qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;21532153+21542154+ ch->qp = ib_create_qp(sdev->pd, qp_init);21552155+ if (IS_ERR(ch->qp)) {21562156+ ret = PTR_ERR(ch->qp);21572157+ printk(KERN_ERR "failed to create_qp ret= %d\n", ret);21582158+ goto err_destroy_cq;21592159+ }21602160+21612161+ atomic_set(&ch->sq_wr_avail, qp_init->cap.max_send_wr);21622162+21632163+ pr_debug("%s: max_cqe= %d max_sge= %d sq_size = %d cm_id= %p\n",21642164+ __func__, ch->cq->cqe, qp_init->cap.max_send_sge,21652165+ qp_init->cap.max_send_wr, ch->cm_id);21662166+21672167+ ret = srpt_init_ch_qp(ch, ch->qp);21682168+ if (ret)21692169+ goto err_destroy_qp;21702170+21712171+ init_waitqueue_head(&ch->wait_queue);21722172+21732173+ pr_debug("creating thread for session %s\n", ch->sess_name);21742174+21752175+ ch->thread = kthread_run(srpt_compl_thread, ch, "ib_srpt_compl");21762176+ if (IS_ERR(ch->thread)) {21772177+ printk(KERN_ERR "failed to create kernel thread %ld\n",21782178+ PTR_ERR(ch->thread));21792179+ ch->thread = NULL;21802180+ goto err_destroy_qp;21812181+ }21822182+21832183+out:21842184+ kfree(qp_init);21852185+ return ret;21862186+21872187+err_destroy_qp:21882188+ ib_destroy_qp(ch->qp);21892189+err_destroy_cq:21902190+ ib_destroy_cq(ch->cq);21912191+ goto out;21922192+}21932193+21942194+static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch)21952195+{21962196+ if (ch->thread)21972197+ kthread_stop(ch->thread);21982198+21992199+ ib_destroy_qp(ch->qp);22002200+ ib_destroy_cq(ch->cq);22012201+}22022202+22032203+/**22042204+ * __srpt_close_ch() - Close an RDMA channel by setting the QP error state.22052205+ *22062206+ * Reset the QP and make sure all resources associated with the channel will22072207+ * be deallocated at an appropriate time.22082208+ *22092209+ * Note: The caller must hold ch->sport->sdev->spinlock.22102210+ */22112211+static void __srpt_close_ch(struct srpt_rdma_ch *ch)22122212+{22132213+ struct srpt_device *sdev;22142214+ enum rdma_ch_state prev_state;22152215+ unsigned long flags;22162216+22172217+ sdev = ch->sport->sdev;22182218+22192219+ spin_lock_irqsave(&ch->spinlock, flags);22202220+ prev_state = ch->state;22212221+ switch (prev_state) {22222222+ case CH_CONNECTING:22232223+ case CH_LIVE:22242224+ ch->state = CH_DISCONNECTING;22252225+ break;22262226+ default:22272227+ break;22282228+ }22292229+ spin_unlock_irqrestore(&ch->spinlock, flags);22302230+22312231+ switch (prev_state) {22322232+ case CH_CONNECTING:22332233+ ib_send_cm_rej(ch->cm_id, IB_CM_REJ_NO_RESOURCES, NULL, 0,22342234+ NULL, 0);22352235+ /* fall through */22362236+ case CH_LIVE:22372237+ if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0)22382238+ printk(KERN_ERR "sending CM DREQ failed.\n");22392239+ break;22402240+ case CH_DISCONNECTING:22412241+ break;22422242+ case CH_DRAINING:22432243+ case CH_RELEASING:22442244+ break;22452245+ }22462246+}22472247+22482248+/**22492249+ * srpt_close_ch() - Close an RDMA channel.22502250+ */22512251+static void srpt_close_ch(struct srpt_rdma_ch *ch)22522252+{22532253+ struct srpt_device *sdev;22542254+22552255+ sdev = ch->sport->sdev;22562256+ spin_lock_irq(&sdev->spinlock);22572257+ __srpt_close_ch(ch);22582258+ spin_unlock_irq(&sdev->spinlock);22592259+}22602260+22612261+/**22622262+ * srpt_drain_channel() - Drain a channel by resetting the IB queue pair.22632263+ * @cm_id: Pointer to the CM ID of the channel to be drained.22642264+ *22652265+ * Note: Must be called from inside srpt_cm_handler to avoid a race between22662266+ * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one()22672267+ * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one()22682268+ * waits until all target sessions for the associated IB device have been22692269+ * unregistered and target session registration involves a call to22702270+ * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until22712271+ * this function has finished).22722272+ */22732273+static void srpt_drain_channel(struct ib_cm_id *cm_id)22742274+{22752275+ struct srpt_device *sdev;22762276+ struct srpt_rdma_ch *ch;22772277+ int ret;22782278+ bool do_reset = false;22792279+22802280+ WARN_ON_ONCE(irqs_disabled());22812281+22822282+ sdev = cm_id->context;22832283+ BUG_ON(!sdev);22842284+ spin_lock_irq(&sdev->spinlock);22852285+ list_for_each_entry(ch, &sdev->rch_list, list) {22862286+ if (ch->cm_id == cm_id) {22872287+ do_reset = srpt_test_and_set_ch_state(ch,22882288+ CH_CONNECTING, CH_DRAINING) ||22892289+ srpt_test_and_set_ch_state(ch,22902290+ CH_LIVE, CH_DRAINING) ||22912291+ srpt_test_and_set_ch_state(ch,22922292+ CH_DISCONNECTING, CH_DRAINING);22932293+ break;22942294+ }22952295+ }22962296+ spin_unlock_irq(&sdev->spinlock);22972297+22982298+ if (do_reset) {22992299+ ret = srpt_ch_qp_err(ch);23002300+ if (ret < 0)23012301+ printk(KERN_ERR "Setting queue pair in error state"23022302+ " failed: %d\n", ret);23032303+ }23042304+}23052305+23062306+/**23072307+ * srpt_find_channel() - Look up an RDMA channel.23082308+ * @cm_id: Pointer to the CM ID of the channel to be looked up.23092309+ *23102310+ * Return NULL if no matching RDMA channel has been found.23112311+ */23122312+static struct srpt_rdma_ch *srpt_find_channel(struct srpt_device *sdev,23132313+ struct ib_cm_id *cm_id)23142314+{23152315+ struct srpt_rdma_ch *ch;23162316+ bool found;23172317+23182318+ WARN_ON_ONCE(irqs_disabled());23192319+ BUG_ON(!sdev);23202320+23212321+ found = false;23222322+ spin_lock_irq(&sdev->spinlock);23232323+ list_for_each_entry(ch, &sdev->rch_list, list) {23242324+ if (ch->cm_id == cm_id) {23252325+ found = true;23262326+ break;23272327+ }23282328+ }23292329+ spin_unlock_irq(&sdev->spinlock);23302330+23312331+ return found ? ch : NULL;23322332+}23332333+23342334+/**23352335+ * srpt_release_channel() - Release channel resources.23362336+ *23372337+ * Schedules the actual release because:23382338+ * - Calling the ib_destroy_cm_id() call from inside an IB CM callback would23392339+ * trigger a deadlock.23402340+ * - It is not safe to call TCM transport_* functions from interrupt context.23412341+ */23422342+static void srpt_release_channel(struct srpt_rdma_ch *ch)23432343+{23442344+ schedule_work(&ch->release_work);23452345+}23462346+23472347+static void srpt_release_channel_work(struct work_struct *w)23482348+{23492349+ struct srpt_rdma_ch *ch;23502350+ struct srpt_device *sdev;23512351+23522352+ ch = container_of(w, struct srpt_rdma_ch, release_work);23532353+ pr_debug("ch = %p; ch->sess = %p; release_done = %p\n", ch, ch->sess,23542354+ ch->release_done);23552355+23562356+ sdev = ch->sport->sdev;23572357+ BUG_ON(!sdev);23582358+23592359+ transport_deregister_session_configfs(ch->sess);23602360+ transport_deregister_session(ch->sess);23612361+ ch->sess = NULL;23622362+23632363+ srpt_destroy_ch_ib(ch);23642364+23652365+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,23662366+ ch->sport->sdev, ch->rq_size,23672367+ ch->rsp_size, DMA_TO_DEVICE);23682368+23692369+ spin_lock_irq(&sdev->spinlock);23702370+ list_del(&ch->list);23712371+ spin_unlock_irq(&sdev->spinlock);23722372+23732373+ ib_destroy_cm_id(ch->cm_id);23742374+23752375+ if (ch->release_done)23762376+ complete(ch->release_done);23772377+23782378+ wake_up(&sdev->ch_releaseQ);23792379+23802380+ kfree(ch);23812381+}23822382+23832383+static struct srpt_node_acl *__srpt_lookup_acl(struct srpt_port *sport,23842384+ u8 i_port_id[16])23852385+{23862386+ struct srpt_node_acl *nacl;23872387+23882388+ list_for_each_entry(nacl, &sport->port_acl_list, list)23892389+ if (memcmp(nacl->i_port_id, i_port_id,23902390+ sizeof(nacl->i_port_id)) == 0)23912391+ return nacl;23922392+23932393+ return NULL;23942394+}23952395+23962396+static struct srpt_node_acl *srpt_lookup_acl(struct srpt_port *sport,23972397+ u8 i_port_id[16])23982398+{23992399+ struct srpt_node_acl *nacl;24002400+24012401+ spin_lock_irq(&sport->port_acl_lock);24022402+ nacl = __srpt_lookup_acl(sport, i_port_id);24032403+ spin_unlock_irq(&sport->port_acl_lock);24042404+24052405+ return nacl;24062406+}24072407+24082408+/**24092409+ * srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.24102410+ *24112411+ * Ownership of the cm_id is transferred to the target session if this24122412+ * functions returns zero. Otherwise the caller remains the owner of cm_id.24132413+ */24142414+static int srpt_cm_req_recv(struct ib_cm_id *cm_id,24152415+ struct ib_cm_req_event_param *param,24162416+ void *private_data)24172417+{24182418+ struct srpt_device *sdev = cm_id->context;24192419+ struct srpt_port *sport = &sdev->port[param->port - 1];24202420+ struct srp_login_req *req;24212421+ struct srp_login_rsp *rsp;24222422+ struct srp_login_rej *rej;24232423+ struct ib_cm_rep_param *rep_param;24242424+ struct srpt_rdma_ch *ch, *tmp_ch;24252425+ struct srpt_node_acl *nacl;24262426+ u32 it_iu_len;24272427+ int i;24282428+ int ret = 0;24292429+24302430+ WARN_ON_ONCE(irqs_disabled());24312431+24322432+ if (WARN_ON(!sdev || !private_data))24332433+ return -EINVAL;24342434+24352435+ req = (struct srp_login_req *)private_data;24362436+24372437+ it_iu_len = be32_to_cpu(req->req_it_iu_len);24382438+24392439+ printk(KERN_INFO "Received SRP_LOGIN_REQ with i_port_id 0x%llx:0x%llx,"24402440+ " t_port_id 0x%llx:0x%llx and it_iu_len %d on port %d"24412441+ " (guid=0x%llx:0x%llx)\n",24422442+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[0]),24432443+ be64_to_cpu(*(__be64 *)&req->initiator_port_id[8]),24442444+ be64_to_cpu(*(__be64 *)&req->target_port_id[0]),24452445+ be64_to_cpu(*(__be64 *)&req->target_port_id[8]),24462446+ it_iu_len,24472447+ param->port,24482448+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[0]),24492449+ be64_to_cpu(*(__be64 *)&sdev->port[param->port - 1].gid.raw[8]));24502450+24512451+ rsp = kzalloc(sizeof *rsp, GFP_KERNEL);24522452+ rej = kzalloc(sizeof *rej, GFP_KERNEL);24532453+ rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL);24542454+24552455+ if (!rsp || !rej || !rep_param) {24562456+ ret = -ENOMEM;24572457+ goto out;24582458+ }24592459+24602460+ if (it_iu_len > srp_max_req_size || it_iu_len < 64) {24612461+ rej->reason = __constant_cpu_to_be32(24622462+ SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE);24632463+ ret = -EINVAL;24642464+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because its"24652465+ " length (%d bytes) is out of range (%d .. %d)\n",24662466+ it_iu_len, 64, srp_max_req_size);24672467+ goto reject;24682468+ }24692469+24702470+ if (!sport->enabled) {24712471+ rej->reason = __constant_cpu_to_be32(24722472+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);24732473+ ret = -EINVAL;24742474+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because the target port"24752475+ " has not yet been enabled\n");24762476+ goto reject;24772477+ }24782478+24792479+ if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {24802480+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;24812481+24822482+ spin_lock_irq(&sdev->spinlock);24832483+24842484+ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {24852485+ if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)24862486+ && !memcmp(ch->t_port_id, req->target_port_id, 16)24872487+ && param->port == ch->sport->port24882488+ && param->listen_id == ch->sport->sdev->cm_id24892489+ && ch->cm_id) {24902490+ enum rdma_ch_state ch_state;24912491+24922492+ ch_state = srpt_get_ch_state(ch);24932493+ if (ch_state != CH_CONNECTING24942494+ && ch_state != CH_LIVE)24952495+ continue;24962496+24972497+ /* found an existing channel */24982498+ pr_debug("Found existing channel %s"24992499+ " cm_id= %p state= %d\n",25002500+ ch->sess_name, ch->cm_id, ch_state);25012501+25022502+ __srpt_close_ch(ch);25032503+25042504+ rsp->rsp_flags =25052505+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED;25062506+ }25072507+ }25082508+25092509+ spin_unlock_irq(&sdev->spinlock);25102510+25112511+ } else25122512+ rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;25132513+25142514+ if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)25152515+ || *(__be64 *)(req->target_port_id + 8) !=25162516+ cpu_to_be64(srpt_service_guid)) {25172517+ rej->reason = __constant_cpu_to_be32(25182518+ SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL);25192519+ ret = -ENOMEM;25202520+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because it"25212521+ " has an invalid target port identifier.\n");25222522+ goto reject;25232523+ }25242524+25252525+ ch = kzalloc(sizeof *ch, GFP_KERNEL);25262526+ if (!ch) {25272527+ rej->reason = __constant_cpu_to_be32(25282528+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);25292529+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because no memory.\n");25302530+ ret = -ENOMEM;25312531+ goto reject;25322532+ }25332533+25342534+ INIT_WORK(&ch->release_work, srpt_release_channel_work);25352535+ memcpy(ch->i_port_id, req->initiator_port_id, 16);25362536+ memcpy(ch->t_port_id, req->target_port_id, 16);25372537+ ch->sport = &sdev->port[param->port - 1];25382538+ ch->cm_id = cm_id;25392539+ /*25402540+ * Avoid QUEUE_FULL conditions by limiting the number of buffers used25412541+ * for the SRP protocol to the command queue size.25422542+ */25432543+ ch->rq_size = SRPT_RQ_SIZE;25442544+ spin_lock_init(&ch->spinlock);25452545+ ch->state = CH_CONNECTING;25462546+ INIT_LIST_HEAD(&ch->cmd_wait_list);25472547+ ch->rsp_size = ch->sport->port_attrib.srp_max_rsp_size;25482548+25492549+ ch->ioctx_ring = (struct srpt_send_ioctx **)25502550+ srpt_alloc_ioctx_ring(ch->sport->sdev, ch->rq_size,25512551+ sizeof(*ch->ioctx_ring[0]),25522552+ ch->rsp_size, DMA_TO_DEVICE);25532553+ if (!ch->ioctx_ring)25542554+ goto free_ch;25552555+25562556+ INIT_LIST_HEAD(&ch->free_list);25572557+ for (i = 0; i < ch->rq_size; i++) {25582558+ ch->ioctx_ring[i]->ch = ch;25592559+ list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);25602560+ }25612561+25622562+ ret = srpt_create_ch_ib(ch);25632563+ if (ret) {25642564+ rej->reason = __constant_cpu_to_be32(25652565+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);25662566+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because creating"25672567+ " a new RDMA channel failed.\n");25682568+ goto free_ring;25692569+ }25702570+25712571+ ret = srpt_ch_qp_rtr(ch, ch->qp);25722572+ if (ret) {25732573+ rej->reason = __constant_cpu_to_be32(25742574+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);25752575+ printk(KERN_ERR "rejected SRP_LOGIN_REQ because enabling"25762576+ " RTR failed (error code = %d)\n", ret);25772577+ goto destroy_ib;25782578+ }25792579+ /*25802580+ * Use the initator port identifier as the session name.25812581+ */25822582+ snprintf(ch->sess_name, sizeof(ch->sess_name), "0x%016llx%016llx",25832583+ be64_to_cpu(*(__be64 *)ch->i_port_id),25842584+ be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));25852585+25862586+ pr_debug("registering session %s\n", ch->sess_name);25872587+25882588+ nacl = srpt_lookup_acl(sport, ch->i_port_id);25892589+ if (!nacl) {25902590+ printk(KERN_INFO "Rejected login because no ACL has been"25912591+ " configured yet for initiator %s.\n", ch->sess_name);25922592+ rej->reason = __constant_cpu_to_be32(25932593+ SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);25942594+ goto destroy_ib;25952595+ }25962596+25972597+ ch->sess = transport_init_session();25982598+ if (!ch->sess) {25992599+ rej->reason = __constant_cpu_to_be32(26002600+ SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);26012601+ pr_debug("Failed to create session\n");26022602+ goto deregister_session;26032603+ }26042604+ ch->sess->se_node_acl = &nacl->nacl;26052605+ transport_register_session(&sport->port_tpg_1, &nacl->nacl, ch->sess, ch);26062606+26072607+ pr_debug("Establish connection sess=%p name=%s cm_id=%p\n", ch->sess,26082608+ ch->sess_name, ch->cm_id);26092609+26102610+ /* create srp_login_response */26112611+ rsp->opcode = SRP_LOGIN_RSP;26122612+ rsp->tag = req->tag;26132613+ rsp->max_it_iu_len = req->req_it_iu_len;26142614+ rsp->max_ti_iu_len = req->req_it_iu_len;26152615+ ch->max_ti_iu_len = it_iu_len;26162616+ rsp->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT26172617+ | SRP_BUF_FORMAT_INDIRECT);26182618+ rsp->req_lim_delta = cpu_to_be32(ch->rq_size);26192619+ atomic_set(&ch->req_lim, ch->rq_size);26202620+ atomic_set(&ch->req_lim_delta, 0);26212621+26222622+ /* create cm reply */26232623+ rep_param->qp_num = ch->qp->qp_num;26242624+ rep_param->private_data = (void *)rsp;26252625+ rep_param->private_data_len = sizeof *rsp;26262626+ rep_param->rnr_retry_count = 7;26272627+ rep_param->flow_control = 1;26282628+ rep_param->failover_accepted = 0;26292629+ rep_param->srq = 1;26302630+ rep_param->responder_resources = 4;26312631+ rep_param->initiator_depth = 4;26322632+26332633+ ret = ib_send_cm_rep(cm_id, rep_param);26342634+ if (ret) {26352635+ printk(KERN_ERR "sending SRP_LOGIN_REQ response failed"26362636+ " (error code = %d)\n", ret);26372637+ goto release_channel;26382638+ }26392639+26402640+ spin_lock_irq(&sdev->spinlock);26412641+ list_add_tail(&ch->list, &sdev->rch_list);26422642+ spin_unlock_irq(&sdev->spinlock);26432643+26442644+ goto out;26452645+26462646+release_channel:26472647+ srpt_set_ch_state(ch, CH_RELEASING);26482648+ transport_deregister_session_configfs(ch->sess);26492649+26502650+deregister_session:26512651+ transport_deregister_session(ch->sess);26522652+ ch->sess = NULL;26532653+26542654+destroy_ib:26552655+ srpt_destroy_ch_ib(ch);26562656+26572657+free_ring:26582658+ srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,26592659+ ch->sport->sdev, ch->rq_size,26602660+ ch->rsp_size, DMA_TO_DEVICE);26612661+free_ch:26622662+ kfree(ch);26632663+26642664+reject:26652665+ rej->opcode = SRP_LOGIN_REJ;26662666+ rej->tag = req->tag;26672667+ rej->buf_fmt = __constant_cpu_to_be16(SRP_BUF_FORMAT_DIRECT26682668+ | SRP_BUF_FORMAT_INDIRECT);26692669+26702670+ ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,26712671+ (void *)rej, sizeof *rej);26722672+26732673+out:26742674+ kfree(rep_param);26752675+ kfree(rsp);26762676+ kfree(rej);26772677+26782678+ return ret;26792679+}26802680+26812681+static void srpt_cm_rej_recv(struct ib_cm_id *cm_id)26822682+{26832683+ printk(KERN_INFO "Received IB REJ for cm_id %p.\n", cm_id);26842684+ srpt_drain_channel(cm_id);26852685+}26862686+26872687+/**26882688+ * srpt_cm_rtu_recv() - Process an IB_CM_RTU_RECEIVED or USER_ESTABLISHED event.26892689+ *26902690+ * An IB_CM_RTU_RECEIVED message indicates that the connection is established26912691+ * and that the recipient may begin transmitting (RTU = ready to use).26922692+ */26932693+static void srpt_cm_rtu_recv(struct ib_cm_id *cm_id)26942694+{26952695+ struct srpt_rdma_ch *ch;26962696+ int ret;26972697+26982698+ ch = srpt_find_channel(cm_id->context, cm_id);26992699+ BUG_ON(!ch);27002700+27012701+ if (srpt_test_and_set_ch_state(ch, CH_CONNECTING, CH_LIVE)) {27022702+ struct srpt_recv_ioctx *ioctx, *ioctx_tmp;27032703+27042704+ ret = srpt_ch_qp_rts(ch, ch->qp);27052705+27062706+ list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list,27072707+ wait_list) {27082708+ list_del(&ioctx->wait_list);27092709+ srpt_handle_new_iu(ch, ioctx, NULL);27102710+ }27112711+ if (ret)27122712+ srpt_close_ch(ch);27132713+ }27142714+}27152715+27162716+static void srpt_cm_timewait_exit(struct ib_cm_id *cm_id)27172717+{27182718+ printk(KERN_INFO "Received IB TimeWait exit for cm_id %p.\n", cm_id);27192719+ srpt_drain_channel(cm_id);27202720+}27212721+27222722+static void srpt_cm_rep_error(struct ib_cm_id *cm_id)27232723+{27242724+ printk(KERN_INFO "Received IB REP error for cm_id %p.\n", cm_id);27252725+ srpt_drain_channel(cm_id);27262726+}27272727+27282728+/**27292729+ * srpt_cm_dreq_recv() - Process reception of a DREQ message.27302730+ */27312731+static void srpt_cm_dreq_recv(struct ib_cm_id *cm_id)27322732+{27332733+ struct srpt_rdma_ch *ch;27342734+ unsigned long flags;27352735+ bool send_drep = false;27362736+27372737+ ch = srpt_find_channel(cm_id->context, cm_id);27382738+ BUG_ON(!ch);27392739+27402740+ pr_debug("cm_id= %p ch->state= %d\n", cm_id, srpt_get_ch_state(ch));27412741+27422742+ spin_lock_irqsave(&ch->spinlock, flags);27432743+ switch (ch->state) {27442744+ case CH_CONNECTING:27452745+ case CH_LIVE:27462746+ send_drep = true;27472747+ ch->state = CH_DISCONNECTING;27482748+ break;27492749+ case CH_DISCONNECTING:27502750+ case CH_DRAINING:27512751+ case CH_RELEASING:27522752+ WARN(true, "unexpected channel state %d\n", ch->state);27532753+ break;27542754+ }27552755+ spin_unlock_irqrestore(&ch->spinlock, flags);27562756+27572757+ if (send_drep) {27582758+ if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0)27592759+ printk(KERN_ERR "Sending IB DREP failed.\n");27602760+ printk(KERN_INFO "Received DREQ and sent DREP for session %s.\n",27612761+ ch->sess_name);27622762+ }27632763+}27642764+27652765+/**27662766+ * srpt_cm_drep_recv() - Process reception of a DREP message.27672767+ */27682768+static void srpt_cm_drep_recv(struct ib_cm_id *cm_id)27692769+{27702770+ printk(KERN_INFO "Received InfiniBand DREP message for cm_id %p.\n",27712771+ cm_id);27722772+ srpt_drain_channel(cm_id);27732773+}27742774+27752775+/**27762776+ * srpt_cm_handler() - IB connection manager callback function.27772777+ *27782778+ * A non-zero return value will cause the caller destroy the CM ID.27792779+ *27802780+ * Note: srpt_cm_handler() must only return a non-zero value when transferring27812781+ * ownership of the cm_id to a channel by srpt_cm_req_recv() failed. Returning27822782+ * a non-zero value in any other case will trigger a race with the27832783+ * ib_destroy_cm_id() call in srpt_release_channel().27842784+ */27852785+static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)27862786+{27872787+ int ret;27882788+27892789+ ret = 0;27902790+ switch (event->event) {27912791+ case IB_CM_REQ_RECEIVED:27922792+ ret = srpt_cm_req_recv(cm_id, &event->param.req_rcvd,27932793+ event->private_data);27942794+ break;27952795+ case IB_CM_REJ_RECEIVED:27962796+ srpt_cm_rej_recv(cm_id);27972797+ break;27982798+ case IB_CM_RTU_RECEIVED:27992799+ case IB_CM_USER_ESTABLISHED:28002800+ srpt_cm_rtu_recv(cm_id);28012801+ break;28022802+ case IB_CM_DREQ_RECEIVED:28032803+ srpt_cm_dreq_recv(cm_id);28042804+ break;28052805+ case IB_CM_DREP_RECEIVED:28062806+ srpt_cm_drep_recv(cm_id);28072807+ break;28082808+ case IB_CM_TIMEWAIT_EXIT:28092809+ srpt_cm_timewait_exit(cm_id);28102810+ break;28112811+ case IB_CM_REP_ERROR:28122812+ srpt_cm_rep_error(cm_id);28132813+ break;28142814+ case IB_CM_DREQ_ERROR:28152815+ printk(KERN_INFO "Received IB DREQ ERROR event.\n");28162816+ break;28172817+ case IB_CM_MRA_RECEIVED:28182818+ printk(KERN_INFO "Received IB MRA event\n");28192819+ break;28202820+ default:28212821+ printk(KERN_ERR "received unrecognized IB CM event %d\n",28222822+ event->event);28232823+ break;28242824+ }28252825+28262826+ return ret;28272827+}28282828+28292829+/**28302830+ * srpt_perform_rdmas() - Perform IB RDMA.28312831+ *28322832+ * Returns zero upon success or a negative number upon failure.28332833+ */28342834+static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,28352835+ struct srpt_send_ioctx *ioctx)28362836+{28372837+ struct ib_send_wr wr;28382838+ struct ib_send_wr *bad_wr;28392839+ struct rdma_iu *riu;28402840+ int i;28412841+ int ret;28422842+ int sq_wr_avail;28432843+ enum dma_data_direction dir;28442844+ const int n_rdma = ioctx->n_rdma;28452845+28462846+ dir = ioctx->cmd.data_direction;28472847+ if (dir == DMA_TO_DEVICE) {28482848+ /* write */28492849+ ret = -ENOMEM;28502850+ sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail);28512851+ if (sq_wr_avail < 0) {28522852+ printk(KERN_WARNING "IB send queue full (needed %d)\n",28532853+ n_rdma);28542854+ goto out;28552855+ }28562856+ }28572857+28582858+ ioctx->rdma_aborted = false;28592859+ ret = 0;28602860+ riu = ioctx->rdma_ius;28612861+ memset(&wr, 0, sizeof wr);28622862+28632863+ for (i = 0; i < n_rdma; ++i, ++riu) {28642864+ if (dir == DMA_FROM_DEVICE) {28652865+ wr.opcode = IB_WR_RDMA_WRITE;28662866+ wr.wr_id = encode_wr_id(i == n_rdma - 1 ?28672867+ SRPT_RDMA_WRITE_LAST :28682868+ SRPT_RDMA_MID,28692869+ ioctx->ioctx.index);28702870+ } else {28712871+ wr.opcode = IB_WR_RDMA_READ;28722872+ wr.wr_id = encode_wr_id(i == n_rdma - 1 ?28732873+ SRPT_RDMA_READ_LAST :28742874+ SRPT_RDMA_MID,28752875+ ioctx->ioctx.index);28762876+ }28772877+ wr.next = NULL;28782878+ wr.wr.rdma.remote_addr = riu->raddr;28792879+ wr.wr.rdma.rkey = riu->rkey;28802880+ wr.num_sge = riu->sge_cnt;28812881+ wr.sg_list = riu->sge;28822882+28832883+ /* only get completion event for the last rdma write */28842884+ if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)28852885+ wr.send_flags = IB_SEND_SIGNALED;28862886+28872887+ ret = ib_post_send(ch->qp, &wr, &bad_wr);28882888+ if (ret)28892889+ break;28902890+ }28912891+28922892+ if (ret)28932893+ printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d",28942894+ __func__, __LINE__, ret, i, n_rdma);28952895+ if (ret && i > 0) {28962896+ wr.num_sge = 0;28972897+ wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);28982898+ wr.send_flags = IB_SEND_SIGNALED;28992899+ while (ch->state == CH_LIVE &&29002900+ ib_post_send(ch->qp, &wr, &bad_wr) != 0) {29012901+ printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]",29022902+ ioctx->ioctx.index);29032903+ msleep(1000);29042904+ }29052905+ while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) {29062906+ printk(KERN_INFO "Waiting until RDMA abort finished [%d]",29072907+ ioctx->ioctx.index);29082908+ msleep(1000);29092909+ }29102910+ }29112911+out:29122912+ if (unlikely(dir == DMA_TO_DEVICE && ret < 0))29132913+ atomic_add(n_rdma, &ch->sq_wr_avail);29142914+ return ret;29152915+}29162916+29172917+/**29182918+ * srpt_xfer_data() - Start data transfer from initiator to target.29192919+ */29202920+static int srpt_xfer_data(struct srpt_rdma_ch *ch,29212921+ struct srpt_send_ioctx *ioctx)29222922+{29232923+ int ret;29242924+29252925+ ret = srpt_map_sg_to_ib_sge(ch, ioctx);29262926+ if (ret) {29272927+ printk(KERN_ERR "%s[%d] ret=%d\n", __func__, __LINE__, ret);29282928+ goto out;29292929+ }29302930+29312931+ ret = srpt_perform_rdmas(ch, ioctx);29322932+ if (ret) {29332933+ if (ret == -EAGAIN || ret == -ENOMEM)29342934+ printk(KERN_INFO "%s[%d] queue full -- ret=%d\n",29352935+ __func__, __LINE__, ret);29362936+ else29372937+ printk(KERN_ERR "%s[%d] fatal error -- ret=%d\n",29382938+ __func__, __LINE__, ret);29392939+ goto out_unmap;29402940+ }29412941+29422942+out:29432943+ return ret;29442944+out_unmap:29452945+ srpt_unmap_sg_to_ib_sge(ch, ioctx);29462946+ goto out;29472947+}29482948+29492949+static int srpt_write_pending_status(struct se_cmd *se_cmd)29502950+{29512951+ struct srpt_send_ioctx *ioctx;29522952+29532953+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);29542954+ return srpt_get_cmd_state(ioctx) == SRPT_STATE_NEED_DATA;29552955+}29562956+29572957+/*29582958+ * srpt_write_pending() - Start data transfer from initiator to target (write).29592959+ */29602960+static int srpt_write_pending(struct se_cmd *se_cmd)29612961+{29622962+ struct srpt_rdma_ch *ch;29632963+ struct srpt_send_ioctx *ioctx;29642964+ enum srpt_command_state new_state;29652965+ enum rdma_ch_state ch_state;29662966+ int ret;29672967+29682968+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);29692969+29702970+ new_state = srpt_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA);29712971+ WARN_ON(new_state == SRPT_STATE_DONE);29722972+29732973+ ch = ioctx->ch;29742974+ BUG_ON(!ch);29752975+29762976+ ch_state = srpt_get_ch_state(ch);29772977+ switch (ch_state) {29782978+ case CH_CONNECTING:29792979+ WARN(true, "unexpected channel state %d\n", ch_state);29802980+ ret = -EINVAL;29812981+ goto out;29822982+ case CH_LIVE:29832983+ break;29842984+ case CH_DISCONNECTING:29852985+ case CH_DRAINING:29862986+ case CH_RELEASING:29872987+ pr_debug("cmd with tag %lld: channel disconnecting\n",29882988+ ioctx->tag);29892989+ srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN);29902990+ ret = -EINVAL;29912991+ goto out;29922992+ }29932993+ ret = srpt_xfer_data(ch, ioctx);29942994+29952995+out:29962996+ return ret;29972997+}29982998+29992999+static u8 tcm_to_srp_tsk_mgmt_status(const int tcm_mgmt_status)30003000+{30013001+ switch (tcm_mgmt_status) {30023002+ case TMR_FUNCTION_COMPLETE:30033003+ return SRP_TSK_MGMT_SUCCESS;30043004+ case TMR_FUNCTION_REJECTED:30053005+ return SRP_TSK_MGMT_FUNC_NOT_SUPP;30063006+ }30073007+ return SRP_TSK_MGMT_FAILED;30083008+}30093009+30103010+/**30113011+ * srpt_queue_response() - Transmits the response to a SCSI command.30123012+ *30133013+ * Callback function called by the TCM core. Must not block since it can be30143014+ * invoked on the context of the IB completion handler.30153015+ */30163016+static int srpt_queue_response(struct se_cmd *cmd)30173017+{30183018+ struct srpt_rdma_ch *ch;30193019+ struct srpt_send_ioctx *ioctx;30203020+ enum srpt_command_state state;30213021+ unsigned long flags;30223022+ int ret;30233023+ enum dma_data_direction dir;30243024+ int resp_len;30253025+ u8 srp_tm_status;30263026+30273027+ ret = 0;30283028+30293029+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);30303030+ ch = ioctx->ch;30313031+ BUG_ON(!ch);30323032+30333033+ spin_lock_irqsave(&ioctx->spinlock, flags);30343034+ state = ioctx->state;30353035+ switch (state) {30363036+ case SRPT_STATE_NEW:30373037+ case SRPT_STATE_DATA_IN:30383038+ ioctx->state = SRPT_STATE_CMD_RSP_SENT;30393039+ break;30403040+ case SRPT_STATE_MGMT:30413041+ ioctx->state = SRPT_STATE_MGMT_RSP_SENT;30423042+ break;30433043+ default:30443044+ WARN(true, "ch %p; cmd %d: unexpected command state %d\n",30453045+ ch, ioctx->ioctx.index, ioctx->state);30463046+ break;30473047+ }30483048+ spin_unlock_irqrestore(&ioctx->spinlock, flags);30493049+30503050+ if (unlikely(transport_check_aborted_status(&ioctx->cmd, false)30513051+ || WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) {30523052+ atomic_inc(&ch->req_lim_delta);30533053+ srpt_abort_cmd(ioctx);30543054+ goto out;30553055+ }30563056+30573057+ dir = ioctx->cmd.data_direction;30583058+30593059+ /* For read commands, transfer the data to the initiator. */30603060+ if (dir == DMA_FROM_DEVICE && ioctx->cmd.data_length &&30613061+ !ioctx->queue_status_only) {30623062+ ret = srpt_xfer_data(ch, ioctx);30633063+ if (ret) {30643064+ printk(KERN_ERR "xfer_data failed for tag %llu\n",30653065+ ioctx->tag);30663066+ goto out;30673067+ }30683068+ }30693069+30703070+ if (state != SRPT_STATE_MGMT)30713071+ resp_len = srpt_build_cmd_rsp(ch, ioctx, ioctx->tag,30723072+ cmd->scsi_status);30733073+ else {30743074+ srp_tm_status30753075+ = tcm_to_srp_tsk_mgmt_status(cmd->se_tmr_req->response);30763076+ resp_len = srpt_build_tskmgmt_rsp(ch, ioctx, srp_tm_status,30773077+ ioctx->tag);30783078+ }30793079+ ret = srpt_post_send(ch, ioctx, resp_len);30803080+ if (ret) {30813081+ printk(KERN_ERR "sending cmd response failed for tag %llu\n",30823082+ ioctx->tag);30833083+ srpt_unmap_sg_to_ib_sge(ch, ioctx);30843084+ srpt_set_cmd_state(ioctx, SRPT_STATE_DONE);30853085+ kref_put(&ioctx->kref, srpt_put_send_ioctx_kref);30863086+ }30873087+30883088+out:30893089+ return ret;30903090+}30913091+30923092+static int srpt_queue_status(struct se_cmd *cmd)30933093+{30943094+ struct srpt_send_ioctx *ioctx;30953095+30963096+ ioctx = container_of(cmd, struct srpt_send_ioctx, cmd);30973097+ BUG_ON(ioctx->sense_data != cmd->sense_buffer);30983098+ if (cmd->se_cmd_flags &30993099+ (SCF_TRANSPORT_TASK_SENSE | SCF_EMULATED_TASK_SENSE))31003100+ WARN_ON(cmd->scsi_status != SAM_STAT_CHECK_CONDITION);31013101+ ioctx->queue_status_only = true;31023102+ return srpt_queue_response(cmd);31033103+}31043104+31053105+static void srpt_refresh_port_work(struct work_struct *work)31063106+{31073107+ struct srpt_port *sport = container_of(work, struct srpt_port, work);31083108+31093109+ srpt_refresh_port(sport);31103110+}31113111+31123112+static int srpt_ch_list_empty(struct srpt_device *sdev)31133113+{31143114+ int res;31153115+31163116+ spin_lock_irq(&sdev->spinlock);31173117+ res = list_empty(&sdev->rch_list);31183118+ spin_unlock_irq(&sdev->spinlock);31193119+31203120+ return res;31213121+}31223122+31233123+/**31243124+ * srpt_release_sdev() - Free the channel resources associated with a target.31253125+ */31263126+static int srpt_release_sdev(struct srpt_device *sdev)31273127+{31283128+ struct srpt_rdma_ch *ch, *tmp_ch;31293129+ int res;31303130+31313131+ WARN_ON_ONCE(irqs_disabled());31323132+31333133+ BUG_ON(!sdev);31343134+31353135+ spin_lock_irq(&sdev->spinlock);31363136+ list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list)31373137+ __srpt_close_ch(ch);31383138+ spin_unlock_irq(&sdev->spinlock);31393139+31403140+ res = wait_event_interruptible(sdev->ch_releaseQ,31413141+ srpt_ch_list_empty(sdev));31423142+ if (res)31433143+ printk(KERN_ERR "%s: interrupted.\n", __func__);31443144+31453145+ return 0;31463146+}31473147+31483148+static struct srpt_port *__srpt_lookup_port(const char *name)31493149+{31503150+ struct ib_device *dev;31513151+ struct srpt_device *sdev;31523152+ struct srpt_port *sport;31533153+ int i;31543154+31553155+ list_for_each_entry(sdev, &srpt_dev_list, list) {31563156+ dev = sdev->device;31573157+ if (!dev)31583158+ continue;31593159+31603160+ for (i = 0; i < dev->phys_port_cnt; i++) {31613161+ sport = &sdev->port[i];31623162+31633163+ if (!strcmp(sport->port_guid, name))31643164+ return sport;31653165+ }31663166+ }31673167+31683168+ return NULL;31693169+}31703170+31713171+static struct srpt_port *srpt_lookup_port(const char *name)31723172+{31733173+ struct srpt_port *sport;31743174+31753175+ spin_lock(&srpt_dev_lock);31763176+ sport = __srpt_lookup_port(name);31773177+ spin_unlock(&srpt_dev_lock);31783178+31793179+ return sport;31803180+}31813181+31823182+/**31833183+ * srpt_add_one() - Infiniband device addition callback function.31843184+ */31853185+static void srpt_add_one(struct ib_device *device)31863186+{31873187+ struct srpt_device *sdev;31883188+ struct srpt_port *sport;31893189+ struct ib_srq_init_attr srq_attr;31903190+ int i;31913191+31923192+ pr_debug("device = %p, device->dma_ops = %p\n", device,31933193+ device->dma_ops);31943194+31953195+ sdev = kzalloc(sizeof *sdev, GFP_KERNEL);31963196+ if (!sdev)31973197+ goto err;31983198+31993199+ sdev->device = device;32003200+ INIT_LIST_HEAD(&sdev->rch_list);32013201+ init_waitqueue_head(&sdev->ch_releaseQ);32023202+ spin_lock_init(&sdev->spinlock);32033203+32043204+ if (ib_query_device(device, &sdev->dev_attr))32053205+ goto free_dev;32063206+32073207+ sdev->pd = ib_alloc_pd(device);32083208+ if (IS_ERR(sdev->pd))32093209+ goto free_dev;32103210+32113211+ sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE);32123212+ if (IS_ERR(sdev->mr))32133213+ goto err_pd;32143214+32153215+ sdev->srq_size = min(srpt_srq_size, sdev->dev_attr.max_srq_wr);32163216+32173217+ srq_attr.event_handler = srpt_srq_event;32183218+ srq_attr.srq_context = (void *)sdev;32193219+ srq_attr.attr.max_wr = sdev->srq_size;32203220+ srq_attr.attr.max_sge = 1;32213221+ srq_attr.attr.srq_limit = 0;32223222+32233223+ sdev->srq = ib_create_srq(sdev->pd, &srq_attr);32243224+ if (IS_ERR(sdev->srq))32253225+ goto err_mr;32263226+32273227+ pr_debug("%s: create SRQ #wr= %d max_allow=%d dev= %s\n",32283228+ __func__, sdev->srq_size, sdev->dev_attr.max_srq_wr,32293229+ device->name);32303230+32313231+ if (!srpt_service_guid)32323232+ srpt_service_guid = be64_to_cpu(device->node_guid);32333233+32343234+ sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev);32353235+ if (IS_ERR(sdev->cm_id))32363236+ goto err_srq;32373237+32383238+ /* print out target login information */32393239+ pr_debug("Target login info: id_ext=%016llx,ioc_guid=%016llx,"32403240+ "pkey=ffff,service_id=%016llx\n", srpt_service_guid,32413241+ srpt_service_guid, srpt_service_guid);32423242+32433243+ /*32443244+ * We do not have a consistent service_id (ie. also id_ext of target_id)32453245+ * to identify this target. We currently use the guid of the first HCA32463246+ * in the system as service_id; therefore, the target_id will change32473247+ * if this HCA is gone bad and replaced by different HCA32483248+ */32493249+ if (ib_cm_listen(sdev->cm_id, cpu_to_be64(srpt_service_guid), 0, NULL))32503250+ goto err_cm;32513251+32523252+ INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,32533253+ srpt_event_handler);32543254+ if (ib_register_event_handler(&sdev->event_handler))32553255+ goto err_cm;32563256+32573257+ sdev->ioctx_ring = (struct srpt_recv_ioctx **)32583258+ srpt_alloc_ioctx_ring(sdev, sdev->srq_size,32593259+ sizeof(*sdev->ioctx_ring[0]),32603260+ srp_max_req_size, DMA_FROM_DEVICE);32613261+ if (!sdev->ioctx_ring)32623262+ goto err_event;32633263+32643264+ for (i = 0; i < sdev->srq_size; ++i)32653265+ srpt_post_recv(sdev, sdev->ioctx_ring[i]);32663266+32673267+ WARN_ON(sdev->device->phys_port_cnt32683268+ > sizeof(sdev->port)/sizeof(sdev->port[0]));32693269+32703270+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {32713271+ sport = &sdev->port[i - 1];32723272+ sport->sdev = sdev;32733273+ sport->port = i;32743274+ sport->port_attrib.srp_max_rdma_size = DEFAULT_MAX_RDMA_SIZE;32753275+ sport->port_attrib.srp_max_rsp_size = DEFAULT_MAX_RSP_SIZE;32763276+ sport->port_attrib.srp_sq_size = DEF_SRPT_SQ_SIZE;32773277+ INIT_WORK(&sport->work, srpt_refresh_port_work);32783278+ INIT_LIST_HEAD(&sport->port_acl_list);32793279+ spin_lock_init(&sport->port_acl_lock);32803280+32813281+ if (srpt_refresh_port(sport)) {32823282+ printk(KERN_ERR "MAD registration failed for %s-%d.\n",32833283+ srpt_sdev_name(sdev), i);32843284+ goto err_ring;32853285+ }32863286+ snprintf(sport->port_guid, sizeof(sport->port_guid),32873287+ "0x%016llx%016llx",32883288+ be64_to_cpu(sport->gid.global.subnet_prefix),32893289+ be64_to_cpu(sport->gid.global.interface_id));32903290+ }32913291+32923292+ spin_lock(&srpt_dev_lock);32933293+ list_add_tail(&sdev->list, &srpt_dev_list);32943294+ spin_unlock(&srpt_dev_lock);32953295+32963296+out:32973297+ ib_set_client_data(device, &srpt_client, sdev);32983298+ pr_debug("added %s.\n", device->name);32993299+ return;33003300+33013301+err_ring:33023302+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,33033303+ sdev->srq_size, srp_max_req_size,33043304+ DMA_FROM_DEVICE);33053305+err_event:33063306+ ib_unregister_event_handler(&sdev->event_handler);33073307+err_cm:33083308+ ib_destroy_cm_id(sdev->cm_id);33093309+err_srq:33103310+ ib_destroy_srq(sdev->srq);33113311+err_mr:33123312+ ib_dereg_mr(sdev->mr);33133313+err_pd:33143314+ ib_dealloc_pd(sdev->pd);33153315+free_dev:33163316+ kfree(sdev);33173317+err:33183318+ sdev = NULL;33193319+ printk(KERN_INFO "%s(%s) failed.\n", __func__, device->name);33203320+ goto out;33213321+}33223322+33233323+/**33243324+ * srpt_remove_one() - InfiniBand device removal callback function.33253325+ */33263326+static void srpt_remove_one(struct ib_device *device)33273327+{33283328+ struct srpt_device *sdev;33293329+ int i;33303330+33313331+ sdev = ib_get_client_data(device, &srpt_client);33323332+ if (!sdev) {33333333+ printk(KERN_INFO "%s(%s): nothing to do.\n", __func__,33343334+ device->name);33353335+ return;33363336+ }33373337+33383338+ srpt_unregister_mad_agent(sdev);33393339+33403340+ ib_unregister_event_handler(&sdev->event_handler);33413341+33423342+ /* Cancel any work queued by the just unregistered IB event handler. */33433343+ for (i = 0; i < sdev->device->phys_port_cnt; i++)33443344+ cancel_work_sync(&sdev->port[i].work);33453345+33463346+ ib_destroy_cm_id(sdev->cm_id);33473347+33483348+ /*33493349+ * Unregistering a target must happen after destroying sdev->cm_id33503350+ * such that no new SRP_LOGIN_REQ information units can arrive while33513351+ * destroying the target.33523352+ */33533353+ spin_lock(&srpt_dev_lock);33543354+ list_del(&sdev->list);33553355+ spin_unlock(&srpt_dev_lock);33563356+ srpt_release_sdev(sdev);33573357+33583358+ ib_destroy_srq(sdev->srq);33593359+ ib_dereg_mr(sdev->mr);33603360+ ib_dealloc_pd(sdev->pd);33613361+33623362+ srpt_free_ioctx_ring((struct srpt_ioctx **)sdev->ioctx_ring, sdev,33633363+ sdev->srq_size, srp_max_req_size, DMA_FROM_DEVICE);33643364+ sdev->ioctx_ring = NULL;33653365+ kfree(sdev);33663366+}33673367+33683368+static struct ib_client srpt_client = {33693369+ .name = DRV_NAME,33703370+ .add = srpt_add_one,33713371+ .remove = srpt_remove_one33723372+};33733373+33743374+static int srpt_check_true(struct se_portal_group *se_tpg)33753375+{33763376+ return 1;33773377+}33783378+33793379+static int srpt_check_false(struct se_portal_group *se_tpg)33803380+{33813381+ return 0;33823382+}33833383+33843384+static char *srpt_get_fabric_name(void)33853385+{33863386+ return "srpt";33873387+}33883388+33893389+static u8 srpt_get_fabric_proto_ident(struct se_portal_group *se_tpg)33903390+{33913391+ return SCSI_TRANSPORTID_PROTOCOLID_SRP;33923392+}33933393+33943394+static char *srpt_get_fabric_wwn(struct se_portal_group *tpg)33953395+{33963396+ struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);33973397+33983398+ return sport->port_guid;33993399+}34003400+34013401+static u16 srpt_get_tag(struct se_portal_group *tpg)34023402+{34033403+ return 1;34043404+}34053405+34063406+static u32 srpt_get_default_depth(struct se_portal_group *se_tpg)34073407+{34083408+ return 1;34093409+}34103410+34113411+static u32 srpt_get_pr_transport_id(struct se_portal_group *se_tpg,34123412+ struct se_node_acl *se_nacl,34133413+ struct t10_pr_registration *pr_reg,34143414+ int *format_code, unsigned char *buf)34153415+{34163416+ struct srpt_node_acl *nacl;34173417+ struct spc_rdma_transport_id *tr_id;34183418+34193419+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);34203420+ tr_id = (void *)buf;34213421+ tr_id->protocol_identifier = SCSI_TRANSPORTID_PROTOCOLID_SRP;34223422+ memcpy(tr_id->i_port_id, nacl->i_port_id, sizeof(tr_id->i_port_id));34233423+ return sizeof(*tr_id);34243424+}34253425+34263426+static u32 srpt_get_pr_transport_id_len(struct se_portal_group *se_tpg,34273427+ struct se_node_acl *se_nacl,34283428+ struct t10_pr_registration *pr_reg,34293429+ int *format_code)34303430+{34313431+ *format_code = 0;34323432+ return sizeof(struct spc_rdma_transport_id);34333433+}34343434+34353435+static char *srpt_parse_pr_out_transport_id(struct se_portal_group *se_tpg,34363436+ const char *buf, u32 *out_tid_len,34373437+ char **port_nexus_ptr)34383438+{34393439+ struct spc_rdma_transport_id *tr_id;34403440+34413441+ *port_nexus_ptr = NULL;34423442+ *out_tid_len = sizeof(struct spc_rdma_transport_id);34433443+ tr_id = (void *)buf;34443444+ return (char *)tr_id->i_port_id;34453445+}34463446+34473447+static struct se_node_acl *srpt_alloc_fabric_acl(struct se_portal_group *se_tpg)34483448+{34493449+ struct srpt_node_acl *nacl;34503450+34513451+ nacl = kzalloc(sizeof(struct srpt_node_acl), GFP_KERNEL);34523452+ if (!nacl) {34533453+ printk(KERN_ERR "Unable to alocate struct srpt_node_acl\n");34543454+ return NULL;34553455+ }34563456+34573457+ return &nacl->nacl;34583458+}34593459+34603460+static void srpt_release_fabric_acl(struct se_portal_group *se_tpg,34613461+ struct se_node_acl *se_nacl)34623462+{34633463+ struct srpt_node_acl *nacl;34643464+34653465+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);34663466+ kfree(nacl);34673467+}34683468+34693469+static u32 srpt_tpg_get_inst_index(struct se_portal_group *se_tpg)34703470+{34713471+ return 1;34723472+}34733473+34743474+static void srpt_release_cmd(struct se_cmd *se_cmd)34753475+{34763476+}34773477+34783478+/**34793479+ * srpt_shutdown_session() - Whether or not a session may be shut down.34803480+ */34813481+static int srpt_shutdown_session(struct se_session *se_sess)34823482+{34833483+ return true;34843484+}34853485+34863486+/**34873487+ * srpt_close_session() - Forcibly close a session.34883488+ *34893489+ * Callback function invoked by the TCM core to clean up sessions associated34903490+ * with a node ACL when the user invokes34913491+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id34923492+ */34933493+static void srpt_close_session(struct se_session *se_sess)34943494+{34953495+ DECLARE_COMPLETION_ONSTACK(release_done);34963496+ struct srpt_rdma_ch *ch;34973497+ struct srpt_device *sdev;34983498+ int res;34993499+35003500+ ch = se_sess->fabric_sess_ptr;35013501+ WARN_ON(ch->sess != se_sess);35023502+35033503+ pr_debug("ch %p state %d\n", ch, srpt_get_ch_state(ch));35043504+35053505+ sdev = ch->sport->sdev;35063506+ spin_lock_irq(&sdev->spinlock);35073507+ BUG_ON(ch->release_done);35083508+ ch->release_done = &release_done;35093509+ __srpt_close_ch(ch);35103510+ spin_unlock_irq(&sdev->spinlock);35113511+35123512+ res = wait_for_completion_timeout(&release_done, 60 * HZ);35133513+ WARN_ON(res <= 0);35143514+}35153515+35163516+/**35173517+ * To do: Find out whether stop_session() has a meaning for transports35183518+ * other than iSCSI.35193519+ */35203520+static void srpt_stop_session(struct se_session *se_sess, int sess_sleep,35213521+ int conn_sleep)35223522+{35233523+}35243524+35253525+static void srpt_reset_nexus(struct se_session *sess)35263526+{35273527+ printk(KERN_ERR "This is the SRP protocol, not iSCSI\n");35283528+}35293529+35303530+static int srpt_sess_logged_in(struct se_session *se_sess)35313531+{35323532+ return true;35333533+}35343534+35353535+/**35363536+ * srpt_sess_get_index() - Return the value of scsiAttIntrPortIndex (SCSI-MIB).35373537+ *35383538+ * A quote from RFC 4455 (SCSI-MIB) about this MIB object:35393539+ * This object represents an arbitrary integer used to uniquely identify a35403540+ * particular attached remote initiator port to a particular SCSI target port35413541+ * within a particular SCSI target device within a particular SCSI instance.35423542+ */35433543+static u32 srpt_sess_get_index(struct se_session *se_sess)35443544+{35453545+ return 0;35463546+}35473547+35483548+static void srpt_set_default_node_attrs(struct se_node_acl *nacl)35493549+{35503550+}35513551+35523552+static u32 srpt_get_task_tag(struct se_cmd *se_cmd)35533553+{35543554+ struct srpt_send_ioctx *ioctx;35553555+35563556+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);35573557+ return ioctx->tag;35583558+}35593559+35603560+/* Note: only used from inside debug printk's by the TCM core. */35613561+static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)35623562+{35633563+ struct srpt_send_ioctx *ioctx;35643564+35653565+ ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);35663566+ return srpt_get_cmd_state(ioctx);35673567+}35683568+35693569+static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)35703570+{35713571+ return 0;35723572+}35733573+35743574+static u16 srpt_get_fabric_sense_len(void)35753575+{35763576+ return 0;35773577+}35783578+35793579+static int srpt_is_state_remove(struct se_cmd *se_cmd)35803580+{35813581+ return 0;35823582+}35833583+35843584+/**35853585+ * srpt_parse_i_port_id() - Parse an initiator port ID.35863586+ * @name: ASCII representation of a 128-bit initiator port ID.35873587+ * @i_port_id: Binary 128-bit port ID.35883588+ */35893589+static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)35903590+{35913591+ const char *p;35923592+ unsigned len, count, leading_zero_bytes;35933593+ int ret, rc;35943594+35953595+ p = name;35963596+ if (strnicmp(p, "0x", 2) == 0)35973597+ p += 2;35983598+ ret = -EINVAL;35993599+ len = strlen(p);36003600+ if (len % 2)36013601+ goto out;36023602+ count = min(len / 2, 16U);36033603+ leading_zero_bytes = 16 - count;36043604+ memset(i_port_id, 0, leading_zero_bytes);36053605+ rc = hex2bin(i_port_id + leading_zero_bytes, p, count);36063606+ if (rc < 0)36073607+ pr_debug("hex2bin failed for srpt_parse_i_port_id: %d\n", rc);36083608+ ret = 0;36093609+out:36103610+ return ret;36113611+}36123612+36133613+/*36143614+ * configfs callback function invoked for36153615+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id36163616+ */36173617+static struct se_node_acl *srpt_make_nodeacl(struct se_portal_group *tpg,36183618+ struct config_group *group,36193619+ const char *name)36203620+{36213621+ struct srpt_port *sport = container_of(tpg, struct srpt_port, port_tpg_1);36223622+ struct se_node_acl *se_nacl, *se_nacl_new;36233623+ struct srpt_node_acl *nacl;36243624+ int ret = 0;36253625+ u32 nexus_depth = 1;36263626+ u8 i_port_id[16];36273627+36283628+ if (srpt_parse_i_port_id(i_port_id, name) < 0) {36293629+ printk(KERN_ERR "invalid initiator port ID %s\n", name);36303630+ ret = -EINVAL;36313631+ goto err;36323632+ }36333633+36343634+ se_nacl_new = srpt_alloc_fabric_acl(tpg);36353635+ if (!se_nacl_new) {36363636+ ret = -ENOMEM;36373637+ goto err;36383638+ }36393639+ /*36403640+ * nacl_new may be released by core_tpg_add_initiator_node_acl()36413641+ * when converting a node ACL from demo mode to explict36423642+ */36433643+ se_nacl = core_tpg_add_initiator_node_acl(tpg, se_nacl_new, name,36443644+ nexus_depth);36453645+ if (IS_ERR(se_nacl)) {36463646+ ret = PTR_ERR(se_nacl);36473647+ goto err;36483648+ }36493649+ /* Locate our struct srpt_node_acl and set sdev and i_port_id. */36503650+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);36513651+ memcpy(&nacl->i_port_id[0], &i_port_id[0], 16);36523652+ nacl->sport = sport;36533653+36543654+ spin_lock_irq(&sport->port_acl_lock);36553655+ list_add_tail(&nacl->list, &sport->port_acl_list);36563656+ spin_unlock_irq(&sport->port_acl_lock);36573657+36583658+ return se_nacl;36593659+err:36603660+ return ERR_PTR(ret);36613661+}36623662+36633663+/*36643664+ * configfs callback function invoked for36653665+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg/acls/$i_port_id36663666+ */36673667+static void srpt_drop_nodeacl(struct se_node_acl *se_nacl)36683668+{36693669+ struct srpt_node_acl *nacl;36703670+ struct srpt_device *sdev;36713671+ struct srpt_port *sport;36723672+36733673+ nacl = container_of(se_nacl, struct srpt_node_acl, nacl);36743674+ sport = nacl->sport;36753675+ sdev = sport->sdev;36763676+ spin_lock_irq(&sport->port_acl_lock);36773677+ list_del(&nacl->list);36783678+ spin_unlock_irq(&sport->port_acl_lock);36793679+ core_tpg_del_initiator_node_acl(&sport->port_tpg_1, se_nacl, 1);36803680+ srpt_release_fabric_acl(NULL, se_nacl);36813681+}36823682+36833683+static ssize_t srpt_tpg_attrib_show_srp_max_rdma_size(36843684+ struct se_portal_group *se_tpg,36853685+ char *page)36863686+{36873687+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);36883688+36893689+ return sprintf(page, "%u\n", sport->port_attrib.srp_max_rdma_size);36903690+}36913691+36923692+static ssize_t srpt_tpg_attrib_store_srp_max_rdma_size(36933693+ struct se_portal_group *se_tpg,36943694+ const char *page,36953695+ size_t count)36963696+{36973697+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);36983698+ unsigned long val;36993699+ int ret;37003700+37013701+ ret = strict_strtoul(page, 0, &val);37023702+ if (ret < 0) {37033703+ pr_err("strict_strtoul() failed with ret: %d\n", ret);37043704+ return -EINVAL;37053705+ }37063706+ if (val > MAX_SRPT_RDMA_SIZE) {37073707+ pr_err("val: %lu exceeds MAX_SRPT_RDMA_SIZE: %d\n", val,37083708+ MAX_SRPT_RDMA_SIZE);37093709+ return -EINVAL;37103710+ }37113711+ if (val < DEFAULT_MAX_RDMA_SIZE) {37123712+ pr_err("val: %lu smaller than DEFAULT_MAX_RDMA_SIZE: %d\n",37133713+ val, DEFAULT_MAX_RDMA_SIZE);37143714+ return -EINVAL;37153715+ }37163716+ sport->port_attrib.srp_max_rdma_size = val;37173717+37183718+ return count;37193719+}37203720+37213721+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rdma_size, S_IRUGO | S_IWUSR);37223722+37233723+static ssize_t srpt_tpg_attrib_show_srp_max_rsp_size(37243724+ struct se_portal_group *se_tpg,37253725+ char *page)37263726+{37273727+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);37283728+37293729+ return sprintf(page, "%u\n", sport->port_attrib.srp_max_rsp_size);37303730+}37313731+37323732+static ssize_t srpt_tpg_attrib_store_srp_max_rsp_size(37333733+ struct se_portal_group *se_tpg,37343734+ const char *page,37353735+ size_t count)37363736+{37373737+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);37383738+ unsigned long val;37393739+ int ret;37403740+37413741+ ret = strict_strtoul(page, 0, &val);37423742+ if (ret < 0) {37433743+ pr_err("strict_strtoul() failed with ret: %d\n", ret);37443744+ return -EINVAL;37453745+ }37463746+ if (val > MAX_SRPT_RSP_SIZE) {37473747+ pr_err("val: %lu exceeds MAX_SRPT_RSP_SIZE: %d\n", val,37483748+ MAX_SRPT_RSP_SIZE);37493749+ return -EINVAL;37503750+ }37513751+ if (val < MIN_MAX_RSP_SIZE) {37523752+ pr_err("val: %lu smaller than MIN_MAX_RSP_SIZE: %d\n", val,37533753+ MIN_MAX_RSP_SIZE);37543754+ return -EINVAL;37553755+ }37563756+ sport->port_attrib.srp_max_rsp_size = val;37573757+37583758+ return count;37593759+}37603760+37613761+TF_TPG_ATTRIB_ATTR(srpt, srp_max_rsp_size, S_IRUGO | S_IWUSR);37623762+37633763+static ssize_t srpt_tpg_attrib_show_srp_sq_size(37643764+ struct se_portal_group *se_tpg,37653765+ char *page)37663766+{37673767+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);37683768+37693769+ return sprintf(page, "%u\n", sport->port_attrib.srp_sq_size);37703770+}37713771+37723772+static ssize_t srpt_tpg_attrib_store_srp_sq_size(37733773+ struct se_portal_group *se_tpg,37743774+ const char *page,37753775+ size_t count)37763776+{37773777+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);37783778+ unsigned long val;37793779+ int ret;37803780+37813781+ ret = strict_strtoul(page, 0, &val);37823782+ if (ret < 0) {37833783+ pr_err("strict_strtoul() failed with ret: %d\n", ret);37843784+ return -EINVAL;37853785+ }37863786+ if (val > MAX_SRPT_SRQ_SIZE) {37873787+ pr_err("val: %lu exceeds MAX_SRPT_SRQ_SIZE: %d\n", val,37883788+ MAX_SRPT_SRQ_SIZE);37893789+ return -EINVAL;37903790+ }37913791+ if (val < MIN_SRPT_SRQ_SIZE) {37923792+ pr_err("val: %lu smaller than MIN_SRPT_SRQ_SIZE: %d\n", val,37933793+ MIN_SRPT_SRQ_SIZE);37943794+ return -EINVAL;37953795+ }37963796+ sport->port_attrib.srp_sq_size = val;37973797+37983798+ return count;37993799+}38003800+38013801+TF_TPG_ATTRIB_ATTR(srpt, srp_sq_size, S_IRUGO | S_IWUSR);38023802+38033803+static struct configfs_attribute *srpt_tpg_attrib_attrs[] = {38043804+ &srpt_tpg_attrib_srp_max_rdma_size.attr,38053805+ &srpt_tpg_attrib_srp_max_rsp_size.attr,38063806+ &srpt_tpg_attrib_srp_sq_size.attr,38073807+ NULL,38083808+};38093809+38103810+static ssize_t srpt_tpg_show_enable(38113811+ struct se_portal_group *se_tpg,38123812+ char *page)38133813+{38143814+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);38153815+38163816+ return snprintf(page, PAGE_SIZE, "%d\n", (sport->enabled) ? 1: 0);38173817+}38183818+38193819+static ssize_t srpt_tpg_store_enable(38203820+ struct se_portal_group *se_tpg,38213821+ const char *page,38223822+ size_t count)38233823+{38243824+ struct srpt_port *sport = container_of(se_tpg, struct srpt_port, port_tpg_1);38253825+ unsigned long tmp;38263826+ int ret;38273827+38283828+ ret = strict_strtoul(page, 0, &tmp);38293829+ if (ret < 0) {38303830+ printk(KERN_ERR "Unable to extract srpt_tpg_store_enable\n");38313831+ return -EINVAL;38323832+ }38333833+38343834+ if ((tmp != 0) && (tmp != 1)) {38353835+ printk(KERN_ERR "Illegal value for srpt_tpg_store_enable: %lu\n", tmp);38363836+ return -EINVAL;38373837+ }38383838+ if (tmp == 1)38393839+ sport->enabled = true;38403840+ else38413841+ sport->enabled = false;38423842+38433843+ return count;38443844+}38453845+38463846+TF_TPG_BASE_ATTR(srpt, enable, S_IRUGO | S_IWUSR);38473847+38483848+static struct configfs_attribute *srpt_tpg_attrs[] = {38493849+ &srpt_tpg_enable.attr,38503850+ NULL,38513851+};38523852+38533853+/**38543854+ * configfs callback invoked for38553855+ * mkdir /sys/kernel/config/target/$driver/$port/$tpg38563856+ */38573857+static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,38583858+ struct config_group *group,38593859+ const char *name)38603860+{38613861+ struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);38623862+ int res;38633863+38643864+ /* Initialize sport->port_wwn and sport->port_tpg_1 */38653865+ res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,38663866+ &sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);38673867+ if (res)38683868+ return ERR_PTR(res);38693869+38703870+ return &sport->port_tpg_1;38713871+}38723872+38733873+/**38743874+ * configfs callback invoked for38753875+ * rmdir /sys/kernel/config/target/$driver/$port/$tpg38763876+ */38773877+static void srpt_drop_tpg(struct se_portal_group *tpg)38783878+{38793879+ struct srpt_port *sport = container_of(tpg,38803880+ struct srpt_port, port_tpg_1);38813881+38823882+ sport->enabled = false;38833883+ core_tpg_deregister(&sport->port_tpg_1);38843884+}38853885+38863886+/**38873887+ * configfs callback invoked for38883888+ * mkdir /sys/kernel/config/target/$driver/$port38893889+ */38903890+static struct se_wwn *srpt_make_tport(struct target_fabric_configfs *tf,38913891+ struct config_group *group,38923892+ const char *name)38933893+{38943894+ struct srpt_port *sport;38953895+ int ret;38963896+38973897+ sport = srpt_lookup_port(name);38983898+ pr_debug("make_tport(%s)\n", name);38993899+ ret = -EINVAL;39003900+ if (!sport)39013901+ goto err;39023902+39033903+ return &sport->port_wwn;39043904+39053905+err:39063906+ return ERR_PTR(ret);39073907+}39083908+39093909+/**39103910+ * configfs callback invoked for39113911+ * rmdir /sys/kernel/config/target/$driver/$port39123912+ */39133913+static void srpt_drop_tport(struct se_wwn *wwn)39143914+{39153915+ struct srpt_port *sport = container_of(wwn, struct srpt_port, port_wwn);39163916+39173917+ pr_debug("drop_tport(%s\n", config_item_name(&sport->port_wwn.wwn_group.cg_item));39183918+}39193919+39203920+static ssize_t srpt_wwn_show_attr_version(struct target_fabric_configfs *tf,39213921+ char *buf)39223922+{39233923+ return scnprintf(buf, PAGE_SIZE, "%s\n", DRV_VERSION);39243924+}39253925+39263926+TF_WWN_ATTR_RO(srpt, version);39273927+39283928+static struct configfs_attribute *srpt_wwn_attrs[] = {39293929+ &srpt_wwn_version.attr,39303930+ NULL,39313931+};39323932+39333933+static struct target_core_fabric_ops srpt_template = {39343934+ .get_fabric_name = srpt_get_fabric_name,39353935+ .get_fabric_proto_ident = srpt_get_fabric_proto_ident,39363936+ .tpg_get_wwn = srpt_get_fabric_wwn,39373937+ .tpg_get_tag = srpt_get_tag,39383938+ .tpg_get_default_depth = srpt_get_default_depth,39393939+ .tpg_get_pr_transport_id = srpt_get_pr_transport_id,39403940+ .tpg_get_pr_transport_id_len = srpt_get_pr_transport_id_len,39413941+ .tpg_parse_pr_out_transport_id = srpt_parse_pr_out_transport_id,39423942+ .tpg_check_demo_mode = srpt_check_false,39433943+ .tpg_check_demo_mode_cache = srpt_check_true,39443944+ .tpg_check_demo_mode_write_protect = srpt_check_true,39453945+ .tpg_check_prod_mode_write_protect = srpt_check_false,39463946+ .tpg_alloc_fabric_acl = srpt_alloc_fabric_acl,39473947+ .tpg_release_fabric_acl = srpt_release_fabric_acl,39483948+ .tpg_get_inst_index = srpt_tpg_get_inst_index,39493949+ .release_cmd = srpt_release_cmd,39503950+ .check_stop_free = srpt_check_stop_free,39513951+ .shutdown_session = srpt_shutdown_session,39523952+ .close_session = srpt_close_session,39533953+ .stop_session = srpt_stop_session,39543954+ .fall_back_to_erl0 = srpt_reset_nexus,39553955+ .sess_logged_in = srpt_sess_logged_in,39563956+ .sess_get_index = srpt_sess_get_index,39573957+ .sess_get_initiator_sid = NULL,39583958+ .write_pending = srpt_write_pending,39593959+ .write_pending_status = srpt_write_pending_status,39603960+ .set_default_node_attributes = srpt_set_default_node_attrs,39613961+ .get_task_tag = srpt_get_task_tag,39623962+ .get_cmd_state = srpt_get_tcm_cmd_state,39633963+ .queue_data_in = srpt_queue_response,39643964+ .queue_status = srpt_queue_status,39653965+ .queue_tm_rsp = srpt_queue_response,39663966+ .get_fabric_sense_len = srpt_get_fabric_sense_len,39673967+ .set_fabric_sense_len = srpt_set_fabric_sense_len,39683968+ .is_state_remove = srpt_is_state_remove,39693969+ /*39703970+ * Setup function pointers for generic logic in39713971+ * target_core_fabric_configfs.c39723972+ */39733973+ .fabric_make_wwn = srpt_make_tport,39743974+ .fabric_drop_wwn = srpt_drop_tport,39753975+ .fabric_make_tpg = srpt_make_tpg,39763976+ .fabric_drop_tpg = srpt_drop_tpg,39773977+ .fabric_post_link = NULL,39783978+ .fabric_pre_unlink = NULL,39793979+ .fabric_make_np = NULL,39803980+ .fabric_drop_np = NULL,39813981+ .fabric_make_nodeacl = srpt_make_nodeacl,39823982+ .fabric_drop_nodeacl = srpt_drop_nodeacl,39833983+};39843984+39853985+/**39863986+ * srpt_init_module() - Kernel module initialization.39873987+ *39883988+ * Note: Since ib_register_client() registers callback functions, and since at39893989+ * least one of these callback functions (srpt_add_one()) calls target core39903990+ * functions, this driver must be registered with the target core before39913991+ * ib_register_client() is called.39923992+ */39933993+static int __init srpt_init_module(void)39943994+{39953995+ int ret;39963996+39973997+ ret = -EINVAL;39983998+ if (srp_max_req_size < MIN_MAX_REQ_SIZE) {39993999+ printk(KERN_ERR "invalid value %d for kernel module parameter"40004000+ " srp_max_req_size -- must be at least %d.\n",40014001+ srp_max_req_size, MIN_MAX_REQ_SIZE);40024002+ goto out;40034003+ }40044004+40054005+ if (srpt_srq_size < MIN_SRPT_SRQ_SIZE40064006+ || srpt_srq_size > MAX_SRPT_SRQ_SIZE) {40074007+ printk(KERN_ERR "invalid value %d for kernel module parameter"40084008+ " srpt_srq_size -- must be in the range [%d..%d].\n",40094009+ srpt_srq_size, MIN_SRPT_SRQ_SIZE, MAX_SRPT_SRQ_SIZE);40104010+ goto out;40114011+ }40124012+40134013+ spin_lock_init(&srpt_dev_lock);40144014+ INIT_LIST_HEAD(&srpt_dev_list);40154015+40164016+ ret = -ENODEV;40174017+ srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");40184018+ if (!srpt_target) {40194019+ printk(KERN_ERR "couldn't register\n");40204020+ goto out;40214021+ }40224022+40234023+ srpt_target->tf_ops = srpt_template;40244024+40254025+ /* Enable SG chaining */40264026+ srpt_target->tf_ops.task_sg_chaining = true;40274027+40284028+ /*40294029+ * Set up default attribute lists.40304030+ */40314031+ srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;40324032+ srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;40334033+ srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;40344034+ srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;40354035+ srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;40364036+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;40374037+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;40384038+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;40394039+ srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;40404040+40414041+ ret = target_fabric_configfs_register(srpt_target);40424042+ if (ret < 0) {40434043+ printk(KERN_ERR "couldn't register\n");40444044+ goto out_free_target;40454045+ }40464046+40474047+ ret = ib_register_client(&srpt_client);40484048+ if (ret) {40494049+ printk(KERN_ERR "couldn't register IB client\n");40504050+ goto out_unregister_target;40514051+ }40524052+40534053+ return 0;40544054+40554055+out_unregister_target:40564056+ target_fabric_configfs_deregister(srpt_target);40574057+ srpt_target = NULL;40584058+out_free_target:40594059+ if (srpt_target)40604060+ target_fabric_configfs_free(srpt_target);40614061+out:40624062+ return ret;40634063+}40644064+40654065+static void __exit srpt_cleanup_module(void)40664066+{40674067+ ib_unregister_client(&srpt_client);40684068+ target_fabric_configfs_deregister(srpt_target);40694069+ srpt_target = NULL;40704070+}40714071+40724072+module_init(srpt_init_module);40734073+module_exit(srpt_cleanup_module);
+444
drivers/infiniband/ulp/srpt/ib_srpt.h
···11+/*22+ * Copyright (c) 2006 - 2009 Mellanox Technology Inc. All rights reserved.33+ * Copyright (C) 2009 - 2010 Bart Van Assche <bvanassche@acm.org>.44+ *55+ * This software is available to you under a choice of one of two66+ * licenses. You may choose to be licensed under the terms of the GNU77+ * General Public License (GPL) Version 2, available from the file88+ * COPYING in the main directory of this source tree, or the99+ * OpenIB.org BSD license below:1010+ *1111+ * Redistribution and use in source and binary forms, with or1212+ * without modification, are permitted provided that the following1313+ * conditions are met:1414+ *1515+ * - Redistributions of source code must retain the above1616+ * copyright notice, this list of conditions and the following1717+ * disclaimer.1818+ *1919+ * - Redistributions in binary form must reproduce the above2020+ * copyright notice, this list of conditions and the following2121+ * disclaimer in the documentation and/or other materials2222+ * provided with the distribution.2323+ *2424+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,2525+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF2626+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND2727+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS2828+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN2929+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN3030+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE3131+ * SOFTWARE.3232+ *3333+ */3434+3535+#ifndef IB_SRPT_H3636+#define IB_SRPT_H3737+3838+#include <linux/version.h>3939+#include <linux/types.h>4040+#include <linux/list.h>4141+#include <linux/wait.h>4242+4343+#include <rdma/ib_verbs.h>4444+#include <rdma/ib_sa.h>4545+#include <rdma/ib_cm.h>4646+4747+#include <scsi/srp.h>4848+4949+#include "ib_dm_mad.h"5050+5151+/*5252+ * The prefix the ServiceName field must start with in the device management5353+ * ServiceEntries attribute pair. See also the SRP specification.5454+ */5555+#define SRP_SERVICE_NAME_PREFIX "SRP.T10:"5656+5757+enum {5858+ /*5959+ * SRP IOControllerProfile attributes for SRP target ports that have6060+ * not been defined in <scsi/srp.h>. Source: section B.7, table B.76161+ * in the SRP specification.6262+ */6363+ SRP_PROTOCOL = 0x0108,6464+ SRP_PROTOCOL_VERSION = 0x0001,6565+ SRP_IO_SUBCLASS = 0x609e,6666+ SRP_SEND_TO_IOC = 0x01,6767+ SRP_SEND_FROM_IOC = 0x02,6868+ SRP_RDMA_READ_FROM_IOC = 0x08,6969+ SRP_RDMA_WRITE_FROM_IOC = 0x20,7070+7171+ /*7272+ * srp_login_cmd.req_flags bitmasks. See also table 9 in the SRP7373+ * specification.7474+ */7575+ SRP_MTCH_ACTION = 0x03, /* MULTI-CHANNEL ACTION */7676+ SRP_LOSOLNT = 0x10, /* logout solicited notification */7777+ SRP_CRSOLNT = 0x20, /* credit request solicited notification */7878+ SRP_AESOLNT = 0x40, /* asynchronous event solicited notification */7979+8080+ /*8181+ * srp_cmd.sol_nt / srp_tsk_mgmt.sol_not bitmasks. See also tables8282+ * 18 and 20 in the SRP specification.8383+ */8484+ SRP_SCSOLNT = 0x02, /* SCSOLNT = successful solicited notification */8585+ SRP_UCSOLNT = 0x04, /* UCSOLNT = unsuccessful solicited notification */8686+8787+ /*8888+ * srp_rsp.sol_not / srp_t_logout.sol_not bitmasks. See also tables8989+ * 16 and 22 in the SRP specification.9090+ */9191+ SRP_SOLNT = 0x01, /* SOLNT = solicited notification */9292+9393+ /* See also table 24 in the SRP specification. */9494+ SRP_TSK_MGMT_SUCCESS = 0x00,9595+ SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04,9696+ SRP_TSK_MGMT_FAILED = 0x05,9797+9898+ /* See also table 21 in the SRP specification. */9999+ SRP_CMD_SIMPLE_Q = 0x0,100100+ SRP_CMD_HEAD_OF_Q = 0x1,101101+ SRP_CMD_ORDERED_Q = 0x2,102102+ SRP_CMD_ACA = 0x4,103103+104104+ SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0,105105+ SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1,106106+ SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,107107+108108+ SRPT_DEF_SG_TABLESIZE = 128,109109+ SRPT_DEF_SG_PER_WQE = 16,110110+111111+ MIN_SRPT_SQ_SIZE = 16,112112+ DEF_SRPT_SQ_SIZE = 4096,113113+ SRPT_RQ_SIZE = 128,114114+ MIN_SRPT_SRQ_SIZE = 4,115115+ DEFAULT_SRPT_SRQ_SIZE = 4095,116116+ MAX_SRPT_SRQ_SIZE = 65535,117117+ MAX_SRPT_RDMA_SIZE = 1U << 24,118118+ MAX_SRPT_RSP_SIZE = 1024,119119+120120+ MIN_MAX_REQ_SIZE = 996,121121+ DEFAULT_MAX_REQ_SIZE122122+ = sizeof(struct srp_cmd)/*48*/123123+ + sizeof(struct srp_indirect_buf)/*20*/124124+ + 128 * sizeof(struct srp_direct_buf)/*16*/,125125+126126+ MIN_MAX_RSP_SIZE = sizeof(struct srp_rsp)/*36*/ + 4,127127+ DEFAULT_MAX_RSP_SIZE = 256, /* leaves 220 bytes for sense data */128128+129129+ DEFAULT_MAX_RDMA_SIZE = 65536,130130+};131131+132132+enum srpt_opcode {133133+ SRPT_RECV,134134+ SRPT_SEND,135135+ SRPT_RDMA_MID,136136+ SRPT_RDMA_ABORT,137137+ SRPT_RDMA_READ_LAST,138138+ SRPT_RDMA_WRITE_LAST,139139+};140140+141141+static inline u64 encode_wr_id(u8 opcode, u32 idx)142142+{143143+ return ((u64)opcode << 32) | idx;144144+}145145+static inline enum srpt_opcode opcode_from_wr_id(u64 wr_id)146146+{147147+ return wr_id >> 32;148148+}149149+static inline u32 idx_from_wr_id(u64 wr_id)150150+{151151+ return (u32)wr_id;152152+}153153+154154+struct rdma_iu {155155+ u64 raddr;156156+ u32 rkey;157157+ struct ib_sge *sge;158158+ u32 sge_cnt;159159+ int mem_id;160160+};161161+162162+/**163163+ * enum srpt_command_state - SCSI command state managed by SRPT.164164+ * @SRPT_STATE_NEW: New command arrived and is being processed.165165+ * @SRPT_STATE_NEED_DATA: Processing a write or bidir command and waiting166166+ * for data arrival.167167+ * @SRPT_STATE_DATA_IN: Data for the write or bidir command arrived and is168168+ * being processed.169169+ * @SRPT_STATE_CMD_RSP_SENT: SRP_RSP for SRP_CMD has been sent.170170+ * @SRPT_STATE_MGMT: Processing a SCSI task management command.171171+ * @SRPT_STATE_MGMT_RSP_SENT: SRP_RSP for SRP_TSK_MGMT has been sent.172172+ * @SRPT_STATE_DONE: Command processing finished successfully, command173173+ * processing has been aborted or command processing174174+ * failed.175175+ */176176+enum srpt_command_state {177177+ SRPT_STATE_NEW = 0,178178+ SRPT_STATE_NEED_DATA = 1,179179+ SRPT_STATE_DATA_IN = 2,180180+ SRPT_STATE_CMD_RSP_SENT = 3,181181+ SRPT_STATE_MGMT = 4,182182+ SRPT_STATE_MGMT_RSP_SENT = 5,183183+ SRPT_STATE_DONE = 6,184184+};185185+186186+/**187187+ * struct srpt_ioctx - Shared SRPT I/O context information.188188+ * @buf: Pointer to the buffer.189189+ * @dma: DMA address of the buffer.190190+ * @index: Index of the I/O context in its ioctx_ring array.191191+ */192192+struct srpt_ioctx {193193+ void *buf;194194+ dma_addr_t dma;195195+ uint32_t index;196196+};197197+198198+/**199199+ * struct srpt_recv_ioctx - SRPT receive I/O context.200200+ * @ioctx: See above.201201+ * @wait_list: Node for insertion in srpt_rdma_ch.cmd_wait_list.202202+ */203203+struct srpt_recv_ioctx {204204+ struct srpt_ioctx ioctx;205205+ struct list_head wait_list;206206+};207207+208208+/**209209+ * struct srpt_send_ioctx - SRPT send I/O context.210210+ * @ioctx: See above.211211+ * @ch: Channel pointer.212212+ * @free_list: Node in srpt_rdma_ch.free_list.213213+ * @n_rbuf: Number of data buffers in the received SRP command.214214+ * @rbufs: Pointer to SRP data buffer array.215215+ * @single_rbuf: SRP data buffer if the command has only a single buffer.216216+ * @sg: Pointer to sg-list associated with this I/O context.217217+ * @sg_cnt: SG-list size.218218+ * @mapped_sg_count: ib_dma_map_sg() return value.219219+ * @n_rdma_ius: Number of elements in the rdma_ius array.220220+ * @rdma_ius: Array with information about the RDMA mapping.221221+ * @tag: Tag of the received SRP information unit.222222+ * @spinlock: Protects 'state'.223223+ * @state: I/O context state.224224+ * @rdma_aborted: If initiating a multipart RDMA transfer failed, whether225225+ * the already initiated transfers have finished.226226+ * @cmd: Target core command data structure.227227+ * @sense_data: SCSI sense data.228228+ */229229+struct srpt_send_ioctx {230230+ struct srpt_ioctx ioctx;231231+ struct srpt_rdma_ch *ch;232232+ struct kref kref;233233+ struct rdma_iu *rdma_ius;234234+ struct srp_direct_buf *rbufs;235235+ struct srp_direct_buf single_rbuf;236236+ struct scatterlist *sg;237237+ struct list_head free_list;238238+ spinlock_t spinlock;239239+ enum srpt_command_state state;240240+ bool rdma_aborted;241241+ struct se_cmd cmd;242242+ struct completion tx_done;243243+ u64 tag;244244+ int sg_cnt;245245+ int mapped_sg_count;246246+ u16 n_rdma_ius;247247+ u8 n_rdma;248248+ u8 n_rbuf;249249+ bool queue_status_only;250250+ u8 sense_data[SCSI_SENSE_BUFFERSIZE];251251+};252252+253253+/**254254+ * enum rdma_ch_state - SRP channel state.255255+ * @CH_CONNECTING: QP is in RTR state; waiting for RTU.256256+ * @CH_LIVE: QP is in RTS state.257257+ * @CH_DISCONNECTING: DREQ has been received; waiting for DREP258258+ * or DREQ has been send and waiting for DREP259259+ * or .260260+ * @CH_DRAINING: QP is in ERR state; waiting for last WQE event.261261+ * @CH_RELEASING: Last WQE event has been received; releasing resources.262262+ */263263+enum rdma_ch_state {264264+ CH_CONNECTING,265265+ CH_LIVE,266266+ CH_DISCONNECTING,267267+ CH_DRAINING,268268+ CH_RELEASING269269+};270270+271271+/**272272+ * struct srpt_rdma_ch - RDMA channel.273273+ * @wait_queue: Allows the kernel thread to wait for more work.274274+ * @thread: Kernel thread that processes the IB queues associated with275275+ * the channel.276276+ * @cm_id: IB CM ID associated with the channel.277277+ * @qp: IB queue pair used for communicating over this channel.278278+ * @cq: IB completion queue for this channel.279279+ * @rq_size: IB receive queue size.280280+ * @rsp_size IB response message size in bytes.281281+ * @sq_wr_avail: number of work requests available in the send queue.282282+ * @sport: pointer to the information of the HCA port used by this283283+ * channel.284284+ * @i_port_id: 128-bit initiator port identifier copied from SRP_LOGIN_REQ.285285+ * @t_port_id: 128-bit target port identifier copied from SRP_LOGIN_REQ.286286+ * @max_ti_iu_len: maximum target-to-initiator information unit length.287287+ * @req_lim: request limit: maximum number of requests that may be sent288288+ * by the initiator without having received a response.289289+ * @req_lim_delta: Number of credits not yet sent back to the initiator.290290+ * @spinlock: Protects free_list and state.291291+ * @free_list: Head of list with free send I/O contexts.292292+ * @state: channel state. See also enum rdma_ch_state.293293+ * @ioctx_ring: Send ring.294294+ * @wc: IB work completion array for srpt_process_completion().295295+ * @list: Node for insertion in the srpt_device.rch_list list.296296+ * @cmd_wait_list: List of SCSI commands that arrived before the RTU event. This297297+ * list contains struct srpt_ioctx elements and is protected298298+ * against concurrent modification by the cm_id spinlock.299299+ * @sess: Session information associated with this SRP channel.300300+ * @sess_name: Session name.301301+ * @release_work: Allows scheduling of srpt_release_channel().302302+ * @release_done: Enables waiting for srpt_release_channel() completion.303303+ */304304+struct srpt_rdma_ch {305305+ wait_queue_head_t wait_queue;306306+ struct task_struct *thread;307307+ struct ib_cm_id *cm_id;308308+ struct ib_qp *qp;309309+ struct ib_cq *cq;310310+ int rq_size;311311+ u32 rsp_size;312312+ atomic_t sq_wr_avail;313313+ struct srpt_port *sport;314314+ u8 i_port_id[16];315315+ u8 t_port_id[16];316316+ int max_ti_iu_len;317317+ atomic_t req_lim;318318+ atomic_t req_lim_delta;319319+ spinlock_t spinlock;320320+ struct list_head free_list;321321+ enum rdma_ch_state state;322322+ struct srpt_send_ioctx **ioctx_ring;323323+ struct ib_wc wc[16];324324+ struct list_head list;325325+ struct list_head cmd_wait_list;326326+ struct se_session *sess;327327+ u8 sess_name[36];328328+ struct work_struct release_work;329329+ struct completion *release_done;330330+};331331+332332+/**333333+ * struct srpt_port_attib - Attributes for SRPT port334334+ * @srp_max_rdma_size: Maximum size of SRP RDMA transfers for new connections.335335+ * @srp_max_rsp_size: Maximum size of SRP response messages in bytes.336336+ * @srp_sq_size: Shared receive queue (SRQ) size.337337+ */338338+struct srpt_port_attrib {339339+ u32 srp_max_rdma_size;340340+ u32 srp_max_rsp_size;341341+ u32 srp_sq_size;342342+};343343+344344+/**345345+ * struct srpt_port - Information associated by SRPT with a single IB port.346346+ * @sdev: backpointer to the HCA information.347347+ * @mad_agent: per-port management datagram processing information.348348+ * @enabled: Whether or not this target port is enabled.349349+ * @port_guid: ASCII representation of Port GUID350350+ * @port: one-based port number.351351+ * @sm_lid: cached value of the port's sm_lid.352352+ * @lid: cached value of the port's lid.353353+ * @gid: cached value of the port's gid.354354+ * @port_acl_lock spinlock for port_acl_list:355355+ * @work: work structure for refreshing the aforementioned cached values.356356+ * @port_tpg_1 Target portal group = 1 data.357357+ * @port_wwn: Target core WWN data.358358+ * @port_acl_list: Head of the list with all node ACLs for this port.359359+ */360360+struct srpt_port {361361+ struct srpt_device *sdev;362362+ struct ib_mad_agent *mad_agent;363363+ bool enabled;364364+ u8 port_guid[64];365365+ u8 port;366366+ u16 sm_lid;367367+ u16 lid;368368+ union ib_gid gid;369369+ spinlock_t port_acl_lock;370370+ struct work_struct work;371371+ struct se_portal_group port_tpg_1;372372+ struct se_wwn port_wwn;373373+ struct list_head port_acl_list;374374+ struct srpt_port_attrib port_attrib;375375+};376376+377377+/**378378+ * struct srpt_device - Information associated by SRPT with a single HCA.379379+ * @device: Backpointer to the struct ib_device managed by the IB core.380380+ * @pd: IB protection domain.381381+ * @mr: L_Key (local key) with write access to all local memory.382382+ * @srq: Per-HCA SRQ (shared receive queue).383383+ * @cm_id: Connection identifier.384384+ * @dev_attr: Attributes of the InfiniBand device as obtained during the385385+ * ib_client.add() callback.386386+ * @srq_size: SRQ size.387387+ * @ioctx_ring: Per-HCA SRQ.388388+ * @rch_list: Per-device channel list -- see also srpt_rdma_ch.list.389389+ * @ch_releaseQ: Enables waiting for removal from rch_list.390390+ * @spinlock: Protects rch_list and tpg.391391+ * @port: Information about the ports owned by this HCA.392392+ * @event_handler: Per-HCA asynchronous IB event handler.393393+ * @list: Node in srpt_dev_list.394394+ */395395+struct srpt_device {396396+ struct ib_device *device;397397+ struct ib_pd *pd;398398+ struct ib_mr *mr;399399+ struct ib_srq *srq;400400+ struct ib_cm_id *cm_id;401401+ struct ib_device_attr dev_attr;402402+ int srq_size;403403+ struct srpt_recv_ioctx **ioctx_ring;404404+ struct list_head rch_list;405405+ wait_queue_head_t ch_releaseQ;406406+ spinlock_t spinlock;407407+ struct srpt_port port[2];408408+ struct ib_event_handler event_handler;409409+ struct list_head list;410410+};411411+412412+/**413413+ * struct srpt_node_acl - Per-initiator ACL data (managed via configfs).414414+ * @i_port_id: 128-bit SRP initiator port ID.415415+ * @sport: port information.416416+ * @nacl: Target core node ACL information.417417+ * @list: Element of the per-HCA ACL list.418418+ */419419+struct srpt_node_acl {420420+ u8 i_port_id[16];421421+ struct srpt_port *sport;422422+ struct se_node_acl nacl;423423+ struct list_head list;424424+};425425+426426+/*427427+ * SRP-releated SCSI persistent reservation definitions.428428+ *429429+ * See also SPC4r28, section 7.6.1 (Protocol specific parameters introduction).430430+ * See also SPC4r28, section 7.6.4.5 (TransportID for initiator ports using431431+ * SCSI over an RDMA interface).432432+ */433433+434434+enum {435435+ SCSI_TRANSPORTID_PROTOCOLID_SRP = 4,436436+};437437+438438+struct spc_rdma_transport_id {439439+ uint8_t protocol_identifier;440440+ uint8_t reserved[7];441441+ uint8_t i_port_id[16];442442+};443443+444444+#endif /* IB_SRPT_H */