From: Doug Ledford <dledford@redhat.com> Date: Mon, 24 Mar 2008 14:24:22 -0400 Subject: [openib] remove srpt and empty vnic driver files Message-id: 1206383072-7299-2-git-send-email-dledford@redhat.com O-Subject: [Patch RHEL5 01/10] Infiniband: Remove srpt driver and empty vnic driver files Bugzilla: 253023 The srpt driver depends on the scsi_target infrastructure, which doesn't exist in the rhel5 kernel, so remove the srpt driver. Also, when the vnic driver was renamed to qlgc_vnic, the empty files where left laying around in the vnic directory. This removes them from the git repo. Signed-off-by: Doug Ledford <dledford@redhat.com> diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig index 80d8103..f0ace3b 100644 --- a/drivers/infiniband/Kconfig +++ b/drivers/infiniband/Kconfig @@ -52,8 +52,6 @@ source "drivers/infiniband/ulp/ipoib/Kconfig" source "drivers/infiniband/ulp/srp/Kconfig" -source "drivers/infiniband/ulp/srpt/Kconfig" - source "drivers/infiniband/ulp/iser/Kconfig" source "drivers/infiniband/ulp/sdp/Kconfig" diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile index 7779ec3..09fd4c1 100644 --- a/drivers/infiniband/Makefile +++ b/drivers/infiniband/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_INFINIBAND_NES) += hw/nes/ obj-$(CONFIG_MLX4_INFINIBAND) += hw/mlx4/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ -obj-$(CONFIG_INFINIBAND_SRPT) += ulp/srpt/ obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/ obj-$(CONFIG_INFINIBAND_SDP) += ulp/sdp/ obj-$(CONFIG_INFINIBAND_QLGC_VNIC) += ulp/qlgc_vnic/ diff --git a/drivers/infiniband/ulp/srpt/Kconfig b/drivers/infiniband/ulp/srpt/Kconfig deleted file mode 100644 index a59e786..0000000 --- a/drivers/infiniband/ulp/srpt/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config INFINIBAND_SRPT - tristate "InfiniBand SCSI RDMA Protocol Target Mode" - depends on INFINIBAND - ---help--- - Support for the SCSI RDMA Protocol Target mode over InfiniBand. - This allows you to turn a standard Linux box to native Infiniband - storage using SRP protocol. - - You will also need the SCST middle level drivers from - http://scst.sf.net/ - The SRP protocol is defined by the INCITS T10 technical - committee. See <http://www.t10.org/>. diff --git a/drivers/infiniband/ulp/srpt/Makefile b/drivers/infiniband/ulp/srpt/Makefile deleted file mode 100644 index 88e733b..0000000 --- a/drivers/infiniband/ulp/srpt/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -EXTRA_CFLAGS += -I/usr/local/include/scst -EXTRA_CFLAGS += -Idrivers/infiniband/ulp/srpt - -obj-$(CONFIG_INFINIBAND_SRPT) += ib_srpt.o diff --git a/drivers/infiniband/ulp/srpt/ib_dm_mad.h b/drivers/infiniband/ulp/srpt/ib_dm_mad.h deleted file mode 100644 index 4c27b80..0000000 --- a/drivers/infiniband/ulp/srpt/ib_dm_mad.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2006 Mellanox Technology Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef IB_DM_MAD_H -#define IB_DM_MAD_H - -#include <linux/types.h> - -#include <rdma/ib_mad.h> - -enum { - DM_MAD_STATUS_UNSUP_METHOD = 0x0008, - DM_MAD_STATUS_UNSUP_METHOD_ATTR = 0x000c, - DM_MAD_STATUS_INVALID_FIELD = 0x001c, - DM_MAD_STATUS_NO_IOC = 0x0100, - - DM_ATTR_CLASS_PORT_INFO = 0x01, - DM_ATTR_IOU_INFO = 0x10, - DM_ATTR_IOC_PROFILE = 0x11, - DM_ATTR_SVC_ENTRIES = 0x12 -}; - -struct ib_dm_hdr { - u8 reserved[28]; -}; - -struct ib_dm_mad { - struct ib_mad_hdr mad_hdr; - struct ib_rmpp_hdr rmpp_hdr; - struct ib_dm_hdr dm_hdr; - u8 data[IB_MGMT_DEVICE_DATA]; -}; - -struct ib_dm_iou_info { - __be16 change_id; - u8 max_controllers; - u8 op_rom; - u8 controller_list[128]; -}; - -struct ib_dm_ioc_profile { - __be64 guid; - __be32 vendor_id; - __be32 device_id; - __be16 device_version; - __be16 reserved1; - __be32 subsys_vendor_id; - __be32 subsys_device_id; - __be16 io_class; - __be16 io_subclass; - __be16 protocol; - __be16 protocol_version; - __be16 service_conn; - __be16 initiators_supported; - __be16 send_queue_depth; - u8 reserved2; - u8 rdma_read_depth; - __be32 send_size; - __be32 rdma_size; - u8 op_cap_mask; - u8 svc_cap_mask; - u8 num_svc_entries; - u8 reserved3[9]; - u8 id_string[64]; -}; - -struct ib_dm_svc_entry { - u8 name[40]; - u64 id; -}; - -struct ib_dm_svc_entries { - struct ib_dm_svc_entry service_entries[4]; -}; - -#endif diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c deleted file mode 100644 index 1fb9d56..0000000 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ /dev/null @@ -1,2499 +0,0 @@ -/* - * Copyright (c) 2006 Mellanox Technology Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/string.h> -#include <linux/kthread.h> - -#include <asm/atomic.h> - -#include "ib_srpt.h" - -#define DRV_NAME "ib_srpt" -#define PFX DRV_NAME ": " -#define DRV_VERSION "0.1" -#define DRV_RELDATE "January 10, 2007" - -#define MELLANOX_SRPT_ID_STRING "Mellanox OFED SRP target" - -MODULE_AUTHOR("Vu Pham"); -MODULE_DESCRIPTION("InfiniBand SCSI RDMA Protocol target " - "v" DRV_VERSION " (" DRV_RELDATE ")"); -MODULE_LICENSE("Dual BSD/GPL"); - -struct mem_elem { - struct page *page; - u32 len; - atomic_t used; -}; - -struct srpt_thread { - spinlock_t thread_lock; - struct list_head thread_ioctx_list; - struct task_struct *thread; -}; - -static u64 mellanox_ioc_guid = 0; -static struct list_head srpt_devices; -static int mem_size = 32768; -static int mem_elements = 4096; -static atomic_t mem_avail; -static int cur_pos = 1; -static struct mem_elem *srpt_mempool = NULL; -static int thread = 1; -static struct srpt_thread srpt_thread; -DECLARE_WAIT_QUEUE_HEAD(ioctx_list_waitQ); - -module_param(mem_elements, int, 0444); -MODULE_PARM_DESC(mem_elements, - "Number of elements in mem pool. Default mem_elements = 4096"); - -module_param(mem_size, int, 0444); -MODULE_PARM_DESC(mem_size, - "Size in bytes for each mem element. Default mem_size = 32768"); - -module_param(thread, int, 0444); -MODULE_PARM_DESC(thread, - "Executing ioctx in thread context. Default thread = 1"); - -static void srpt_add_one(struct ib_device *device); -static void srpt_remove_one(struct ib_device *device); - -static struct ib_client srpt_client = { - .name = DRV_NAME, - .add = srpt_add_one, - .remove = srpt_remove_one -}; - -static struct mem_elem *srpt_get_mem_elem(int *index) -{ - int i, end_pos; - - *index = 0; - end_pos = mem_elements; - for (i = cur_pos; i <= end_pos; ++i) { - if (i == mem_elements) { - end_pos = cur_pos; - i = 1; - } - - if (atomic_read(&srpt_mempool[i].used) == 0) { - atomic_inc(&srpt_mempool[i].used); - smp_mb__after_atomic_inc(); - *index = i; - cur_pos = i + 1; - atomic_dec(&mem_avail); - return &srpt_mempool[i]; - } - } - return NULL; -} - -static int srpt_free_mem_elem(int index) -{ - if (!index || index >= mem_elements) - return -EINVAL; - - atomic_dec(&srpt_mempool[index].used); - smp_mb__after_atomic_dec(); - atomic_inc(&mem_avail); - return 0; -} - -static int srpt_mempool_create(void) -{ - int i, order; - - order = get_order(mem_elements * sizeof(struct mem_elem)); - srpt_mempool = (struct mem_elem *) __get_free_pages(GFP_KERNEL, order); - if (!srpt_mempool) - return -ENOMEM; - - for (i = 1; i < mem_elements; ++i) { - order = get_order(mem_size); - srpt_mempool[i].page = alloc_pages(GFP_KERNEL, order); - if (!srpt_mempool[i].page) { - printk(KERN_ERR PFX - "alloc= %d bytes for elem= %d failed\n", - mem_size, i); - goto free_mem; - } - atomic_set(&srpt_mempool[i].used, 0); - } - - atomic_set(&mem_avail, mem_elements); - return 0; - - free_mem: - while (i > 1) - __free_pages(srpt_mempool[--i].page, order); - - free_pages((unsigned long) srpt_mempool, - get_order(mem_elements * sizeof(struct mem_elem))); - - return -ENOMEM; -} - -static void srpt_mempool_destroy(void) -{ - int i, order; - - order = get_order(mem_size); - for (i = 1; i < mem_elements; ++i) - __free_pages(srpt_mempool[i].page, order); - - free_pages((unsigned long) srpt_mempool, - get_order(mem_elements * sizeof(struct mem_elem))); -} - -static void srpt_event_handler(struct ib_event_handler *handler, - struct ib_event *event) -{ - struct srpt_device *sdev = - ib_get_client_data(event->device, &srpt_client); - - if (!sdev || sdev->device != event->device) - return; - - printk(KERN_WARNING PFX "ASYNC event= %d on device= %s\n", - event->event, sdev->device->name); -} - -static void srpt_srq_event(struct ib_event *event, void *ctx) -{ - printk(KERN_WARNING PFX "SRQ event %d\n", event->event); -} - -static void srpt_qp_event(struct ib_event *event, void *ctx) -{ - struct srpt_rdma_ch *ch = ctx; - - printk(KERN_WARNING PFX "QP event %d on cm_id= %p sess_name= %s state= %d\n", - event->event, ch->cm_id, ch->sess_name, ch->state); - - switch (event->event) { - case IB_EVENT_COMM_EST: -#ifndef OFED11 - ib_cm_notify(ch->cm_id, event->event); -#endif - schedule_work(&ch->work); - break; - default: - break; - } -} - -static void srpt_set_ioc(u8 * c_list, u32 slot, u8 value) -{ - u16 id; - u8 tmp; - - id = (slot - 1) / 2; - if (slot & 0x1) { - tmp = c_list[id] & 0xf; - c_list[id] = (value << 4) | tmp; - } else { - tmp = c_list[id] & 0xf0; - c_list[id] = (value & 0xf) | tmp; - } -} - -static void srpt_get_class_port_info(struct ib_dm_mad *mad) -{ - struct ib_class_port_info *cif; - - cif = (struct ib_class_port_info *)mad->data; - memset(cif, 0, sizeof *cif); - cif->base_version = 1; - cif->class_version = 1; - cif->resp_time_value = 20; - - mad->mad_hdr.status = 0; -} - -static void srpt_get_iou(struct ib_dm_mad *mad) -{ - struct ib_dm_iou_info *ioui; - u8 slot; - int i; - - ioui = (struct ib_dm_iou_info *)mad->data; - ioui->change_id = 1; - ioui->max_controllers = 16; - - /* set present for slot 1 and empty for the rest */ - srpt_set_ioc(ioui->controller_list, 1, 1); - for (i = 1, slot = 2; i < 16; i++, slot++) - srpt_set_ioc(ioui->controller_list, slot, 0); - - mad->mad_hdr.status = 0; -} - -static void srpt_get_ioc(struct srpt_device *sdev, u32 slot, - struct ib_dm_mad *mad) -{ - struct ib_dm_ioc_profile *iocp; - - iocp = (struct ib_dm_ioc_profile *)mad->data; - - if (!slot || slot > 16) { - mad->mad_hdr.status = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); - return; - } - - if (slot > 2) { - mad->mad_hdr.status = cpu_to_be16(DM_MAD_STATUS_NO_IOC); - return; - } - - memset(iocp, 0, sizeof *iocp); - strcpy(iocp->id_string, MELLANOX_SRPT_ID_STRING); - iocp->guid = cpu_to_be64(mellanox_ioc_guid); - iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); - iocp->device_id = cpu_to_be32(sdev->dev_attr.vendor_part_id); - iocp->device_version = cpu_to_be16(sdev->dev_attr.hw_ver); - iocp->subsys_vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); - iocp->subsys_device_id = 0x0; - iocp->io_class = cpu_to_be16(SRP_REV16A_IB_IO_CLASS); - iocp->io_subclass = cpu_to_be16(SRP_IO_SUBCLASS); - iocp->protocol = cpu_to_be16(SRP_PROTOCOL); - iocp->protocol_version = cpu_to_be16(SRP_PROTOCOL_VERSION); - iocp->send_queue_depth = cpu_to_be16(SRPT_SRQ_SIZE); - iocp->rdma_read_depth = 4; - iocp->send_size = cpu_to_be32(MAX_MESSAGE_SIZE); - iocp->rdma_size = cpu_to_be32(MAX_RDMA_SIZE); - iocp->num_svc_entries = 1; - iocp->op_cap_mask = SRP_SEND_TO_IOC | SRP_SEND_FROM_IOC | - SRP_RDMA_READ_FROM_IOC | SRP_RDMA_WRITE_FROM_IOC; - - mad->mad_hdr.status = 0; -} - -static void srpt_get_svc_entries(u16 slot, u8 hi, u8 lo, struct ib_dm_mad *mad) -{ - struct ib_dm_svc_entries *svc_entries; - - if (!slot || slot > 16) { - mad->mad_hdr.status = cpu_to_be16(DM_MAD_STATUS_INVALID_FIELD); - return; - } - - if (slot > 2 || lo > hi || hi > 1) { - mad->mad_hdr.status = cpu_to_be16(DM_MAD_STATUS_NO_IOC); - return; - } - - svc_entries = (struct ib_dm_svc_entries *)mad->data; - memset(svc_entries, 0, sizeof *svc_entries); - svc_entries->service_entries[0].id = cpu_to_be64(mellanox_ioc_guid); - sprintf(svc_entries->service_entries[0].name, "%s%016llx", - SRP_SERVICE_NAME_PREFIX, (unsigned long long)mellanox_ioc_guid); - - mad->mad_hdr.status = 0; -} - -static void srpt_mgmt_method_get(struct srpt_port *sp, struct ib_mad *rq_mad, - struct ib_dm_mad *rsp_mad) -{ - u16 attr_id; - u32 slot; - u8 hi, lo; - - attr_id = be16_to_cpu(rq_mad->mad_hdr.attr_id); - switch (attr_id) { - case DM_ATTR_CLASS_PORT_INFO: - srpt_get_class_port_info(rsp_mad); - break; - case DM_ATTR_IOU_INFO: - srpt_get_iou(rsp_mad); - break; - case DM_ATTR_IOC_PROFILE: - slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod); - srpt_get_ioc(sp->sdev, slot, rsp_mad); - break; - case DM_ATTR_SVC_ENTRIES: - slot = be32_to_cpu(rq_mad->mad_hdr.attr_mod); - hi = (u8) ((slot >> 8) & 0xff); - lo = (u8) (slot & 0xff); - slot = (u16) ((slot >> 16) & 0xffff); - srpt_get_svc_entries(slot, hi, lo, rsp_mad); - break; - default: - rsp_mad->mad_hdr.status = - cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); - break; - } -} - -static void srpt_mad_send_handler(struct ib_mad_agent *mad_agent, - struct ib_mad_send_wc *mad_wc) -{ - ib_destroy_ah(mad_wc->send_buf->ah); - ib_free_send_mad(mad_wc->send_buf); -} - -static void srpt_mad_recv_handler(struct ib_mad_agent *mad_agent, - struct ib_mad_recv_wc *mad_wc) -{ - struct srpt_port *sport = (struct srpt_port *)mad_agent->context; - struct ib_ah *ah; - struct ib_mad_send_buf *rsp; - struct ib_dm_mad *dm_mad; - - if (!mad_wc || !mad_wc->recv_buf.mad) - return; - - ah = ib_create_ah_from_wc(mad_agent->qp->pd, mad_wc->wc, - mad_wc->recv_buf.grh, mad_agent->port_num); - if (IS_ERR(ah)) - goto err; - - rsp = ib_create_send_mad(mad_agent, mad_wc->wc->src_qp, - mad_wc->wc->pkey_index, 0, - IB_MGMT_DEVICE_HDR, IB_MGMT_DEVICE_DATA, - GFP_KERNEL); - if (IS_ERR(rsp)) - goto err_rsp; - - rsp->ah = ah; - - dm_mad = rsp->mad; - memcpy(dm_mad, mad_wc->recv_buf.mad, sizeof *dm_mad); - dm_mad->mad_hdr.method = IB_MGMT_METHOD_GET_RESP; - dm_mad->mad_hdr.status = 0; - - switch (mad_wc->recv_buf.mad->mad_hdr.method) { - case IB_MGMT_METHOD_GET: - srpt_mgmt_method_get(sport, mad_wc->recv_buf.mad, dm_mad); - break; - case IB_MGMT_METHOD_SET: - dm_mad->mad_hdr.status = - cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD_ATTR); - break; - default: - dm_mad->mad_hdr.status = - cpu_to_be16(DM_MAD_STATUS_UNSUP_METHOD); - break; - } - - if (!ib_post_send_mad(rsp, NULL)) { - ib_free_recv_mad(mad_wc); - /* will destroy_ah & free_send_mad in send completion */ - return; - } - - ib_free_send_mad(rsp); - - err_rsp: - ib_destroy_ah(ah); - err: - ib_free_recv_mad(mad_wc); -} - -static int srpt_refresh_port(struct srpt_port *sport) -{ - struct ib_mad_reg_req reg_req; - struct ib_port_modify port_modify; - struct ib_port_attr port_attr; - int ret; - - memset(&port_modify, 0, sizeof port_modify); - port_modify.set_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; - port_modify.clr_port_cap_mask = 0; - - ret = ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify); - if (ret) - goto err_mod_port; - - ret = ib_query_port(sport->sdev->device, sport->port, &port_attr); - if (ret) - goto err_query_port; - - sport->sm_lid = port_attr.sm_lid; - sport->lid = port_attr.lid; - - ret = ib_query_gid(sport->sdev->device, sport->port, 0, &sport->gid); - if (ret) - goto err_query_port; - - if (!sport->mad_agent) { - reg_req.mgmt_class = IB_MGMT_CLASS_DEVICE_MGMT; - reg_req.mgmt_class_version = IB_MGMT_BASE_VERSION; - set_bit(IB_MGMT_METHOD_GET, reg_req.method_mask); - set_bit(IB_MGMT_METHOD_SET, reg_req.method_mask); - - sport->mad_agent = ib_register_mad_agent(sport->sdev->device, - sport->port, - IB_QPT_GSI, - ®_req, 0, - srpt_mad_send_handler, - srpt_mad_recv_handler, - sport); - if (IS_ERR(sport->mad_agent)) - goto err_query_port; - } - - return 0; - - err_query_port: - - port_modify.set_port_cap_mask = 0; - port_modify.clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP; - ib_modify_port(sport->sdev->device, sport->port, 0, &port_modify); - - err_mod_port: - - return ret; -} - -static struct srpt_ioctx *srpt_alloc_ioctx(struct srpt_device *sdev) -{ - struct srpt_ioctx *ioctx; - - ioctx = kmalloc(sizeof *ioctx, GFP_KERNEL); - if (!ioctx) - goto out; - - ioctx->buf = kzalloc(MAX_MESSAGE_SIZE, GFP_KERNEL); - if (!ioctx->buf) - goto out_free_ioctx; - - ioctx->dma = dma_map_single(sdev->device->dma_device, ioctx->buf, - MAX_MESSAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(ioctx->dma)) - goto out_free_buf; - - return ioctx; - - out_free_buf: - kfree(ioctx->buf); - out_free_ioctx: - kfree(ioctx); - out: - return NULL; -} - -static void srpt_free_ioctx(struct srpt_device *sdev, struct srpt_ioctx *ioctx) -{ - if (!ioctx) - return; - - dma_unmap_single(sdev->device->dma_device, ioctx->dma, - MAX_MESSAGE_SIZE, DMA_BIDIRECTIONAL); - kfree(ioctx->buf); - kfree(ioctx); -} - -static int srpt_alloc_ioctx_ring(struct srpt_device *sdev) -{ - int i; - - for (i = 0; i < SRPT_SRQ_SIZE; ++i) { - sdev->ioctx_ring[i] = srpt_alloc_ioctx(sdev); - - if (!sdev->ioctx_ring[i]) - goto err; - - sdev->ioctx_ring[i]->index = i; - } - - return 0; - - err: - while (--i > 0) { - srpt_free_ioctx(sdev, sdev->ioctx_ring[i]); - sdev->ioctx_ring[i] = NULL; - } - return -ENOMEM; -} - -static int srpt_post_recv(struct srpt_device *sdev, struct srpt_ioctx *ioctx) -{ - struct ib_sge list; - struct ib_recv_wr wr, *bad_wr; - - wr.wr_id = ioctx->index | SRPT_OP_RECV; - - list.addr = ioctx->dma; - list.length = MAX_MESSAGE_SIZE; - list.lkey = sdev->mr->lkey; - - wr.next = NULL; - wr.sg_list = &list; - wr.num_sge = 1; - - return ib_post_srq_recv(sdev->srq, &wr, &bad_wr); -} - -static int srpt_post_send(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx, - int len) -{ - struct ib_sge list; - struct ib_send_wr wr, *bad_wr; - struct srpt_device *sdev = ch->sport->sdev; - - dma_sync_single_for_device(sdev->device->dma_device, ioctx->dma, - MAX_MESSAGE_SIZE, DMA_TO_DEVICE); - - list.addr = ioctx->dma; - list.length = len; - list.lkey = sdev->mr->lkey; - - wr.next = NULL; - wr.wr_id = ioctx->index; - wr.sg_list = &list; - wr.num_sge = 1; - wr.opcode = IB_WR_SEND; - wr.send_flags = IB_SEND_SIGNALED; - - return ib_post_send(ch->qp, &wr, &bad_wr); -} - -static int srpt_get_desc_tbl(struct srpt_ioctx *ioctx, struct srp_cmd *srp_cmd, - int *ind) -{ - struct srp_indirect_buf *idb; - struct srp_direct_buf *db; - - *ind = 0; - if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) || - ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) { - ioctx->n_rbuf = 1; - ioctx->rbufs = &ioctx->single_rbuf; - - db = (void *)srp_cmd->add_data; - memcpy(ioctx->rbufs, db, sizeof *db); - ioctx->data_len = be32_to_cpu(db->len); - } else { - idb = (void *)srp_cmd->add_data; - - ioctx->n_rbuf = be32_to_cpu(idb->table_desc.len) / sizeof *db; - - if (ioctx->n_rbuf > - (srp_cmd->data_out_desc_cnt + srp_cmd->data_in_desc_cnt)) { - *ind = 1; - ioctx->n_rbuf = 0; - goto out; - } - - ioctx->rbufs = kmalloc(ioctx->n_rbuf * sizeof *db, GFP_ATOMIC); - if (!ioctx->rbufs) { - ioctx->n_rbuf = 0; - return -ENOMEM; - } - - db = idb->desc_list; - memcpy(ioctx->rbufs, db, ioctx->n_rbuf * sizeof *db); - ioctx->data_len = be32_to_cpu(idb->len); - } - out: - return 0; -} - -static int srpt_init_ch_qp(struct srpt_rdma_ch *ch, struct ib_qp *qp) -{ - struct ib_qp_attr *attr; - int ret; - - attr = kzalloc(sizeof *attr, GFP_KERNEL); - if (!attr) - return -ENOMEM; - - attr->qp_state = IB_QPS_INIT; - attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_READ | - IB_ACCESS_REMOTE_WRITE; - attr->port_num = ch->sport->port; - attr->pkey_index = 0; - - ret = ib_modify_qp(qp, attr, - IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PORT | - IB_QP_PKEY_INDEX); - - kfree(attr); - return ret; -} - -static int srpt_ch_qp_rtr_rts(struct srpt_rdma_ch *ch, struct ib_qp *qp, - enum ib_qp_state qp_state) -{ - struct ib_qp_attr *qp_attr; - int attr_mask; - int ret; - - qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL); - if (!qp_attr) - return -ENOMEM; - - qp_attr->qp_state = qp_state; - ret = ib_cm_init_qp_attr(ch->cm_id, qp_attr, &attr_mask); - if (ret) - goto out; - - if (qp_state == IB_QPS_RTR) - qp_attr->max_dest_rd_atomic = 4; - else - qp_attr->max_rd_atomic = 4; - - ret = ib_modify_qp(qp, qp_attr, attr_mask); - - out: - kfree(qp_attr); - return ret; -} - -static void srpt_reset_ioctx(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx) -{ - int i; - - if (ioctx->n_rdma_ius > 0 && ioctx->rdma_ius) { - struct rdma_iu *riu = ioctx->rdma_ius; - - for (i = 0; i < ioctx->n_rdma_ius; ++i, ++riu) { - if (riu->sge) - kfree(riu->sge); - - if (riu->mem_id) - srpt_free_mem_elem(riu->mem_id); - } - kfree(ioctx->rdma_ius); - } - - if (ioctx->n_rbuf > 1 && ioctx->rbufs) - kfree(ioctx->rbufs); - - if (srpt_post_recv(ch->sport->sdev, ioctx)) - printk(KERN_ERR PFX "SRQ post_recv failed - this is serious\n"); - /* we should queue it back to free_ioctx queue */ - else - atomic_inc(&ch->req_lim_delta); -} - -static void srpt_handle_err_comp(struct srpt_rdma_ch *ch, struct ib_wc *wc) -{ - struct srpt_ioctx *ioctx; - struct srpt_device *sdev = ch->sport->sdev; - scst_data_direction dir = SCST_DATA_NONE; - - if (wc->wr_id & SRPT_OP_RECV) { - ioctx = sdev->ioctx_ring[wc->wr_id & ~SRPT_OP_RECV]; - printk(KERN_ERR PFX "This is serious - SRQ is in bad state\n"); - } else { - ioctx = sdev->ioctx_ring[wc->wr_id]; - - if (ioctx->scmnd) { - struct scst_cmd *scmnd = ioctx->scmnd; - - dir = scst_cmd_get_data_direction(scmnd); - - if (dir == SCST_DATA_NONE) - scst_tgt_cmd_done(scmnd); - else { - dma_unmap_sg(sdev->device->dma_device, - scst_cmd_get_sg(scmnd), - scst_cmd_get_sg_cnt(scmnd), - scst_to_tgt_dma_dir(dir)); - - if (scmnd->data_buf_tgt_alloc && - scmnd->data_buf_alloced) { - kfree(scmnd->sg); - scmnd->sg = NULL; - scmnd->sg_cnt = 0; - } - - if (scmnd->state == SCST_CMD_STATE_RDY_TO_XFER) - scst_rx_data(scmnd, - SCST_RX_STATUS_ERROR, - SCST_CONTEXT_THREAD); - else if (scmnd->state == SCST_CMD_STATE_XMIT_WAIT) - scst_tgt_cmd_done(scmnd); - } - } else - srpt_reset_ioctx(ch, ioctx); - } - -} - -static void srpt_handle_send_comp(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx) -{ - if (ioctx->scmnd) { - scst_data_direction dir = scst_cmd_get_data_direction(ioctx->scmnd); - - if (dir != SCST_DATA_NONE) - dma_unmap_sg(ch->sport->sdev->device->dma_device, - scst_cmd_get_sg(ioctx->scmnd), - scst_cmd_get_sg_cnt(ioctx->scmnd), - scst_to_tgt_dma_dir(dir)); - - if (ioctx->scmnd->data_buf_tgt_alloc && - ioctx->scmnd->data_buf_alloced) { - kfree(ioctx->scmnd->sg); - ioctx->scmnd->sg = NULL; - ioctx->scmnd->sg_cnt = 0; - } - - scst_tgt_cmd_done(ioctx->scmnd); - } else - srpt_reset_ioctx(ch, ioctx); -} - -static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx) -{ - if (!ioctx->scmnd) { - srpt_reset_ioctx(ch, ioctx); - return; - } - - if (scst_cmd_get_data_direction(ioctx->scmnd) == SCST_DATA_WRITE) - scst_rx_data(ioctx->scmnd, SCST_RX_STATUS_SUCCESS, - SCST_CONTEXT_THREAD); -} - -static void srpt_build_cmd_rsp(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx, u8 s_key, u8 s_code, - u64 tag) -{ - struct srp_rsp *srp_rsp; - struct sense_data *sense; - int limit_delta; - - srp_rsp = ioctx->buf; - memset(srp_rsp, 0, sizeof *srp_rsp); - - limit_delta = atomic_read(&ch->req_lim_delta); - atomic_sub(limit_delta, &ch->req_lim_delta); - - srp_rsp->opcode = SRP_RSP; - srp_rsp->req_lim_delta = cpu_to_be32(limit_delta); - srp_rsp->tag = tag; - - if (s_key != NO_SENSE) { - srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID; - srp_rsp->status = SAM_STAT_CHECK_CONDITION; - srp_rsp->sense_data_len = - cpu_to_be32(sizeof *sense + (sizeof *sense % 4)); - - sense = (struct sense_data *)(srp_rsp + 1); - sense->err_code = 0x70; - sense->key = s_key; - sense->asc_ascq = s_code; - } -} - -static void srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx, u8 rsp_code, - u64 tag) -{ - struct srp_rsp *srp_rsp; - int limit_delta; - - dma_sync_single_for_cpu(ch->sport->sdev->device->dma_device, ioctx->dma, - MAX_MESSAGE_SIZE, DMA_TO_DEVICE); - - srp_rsp = ioctx->buf; - memset(srp_rsp, 0, sizeof *srp_rsp); - - limit_delta = atomic_read(&ch->req_lim_delta); - atomic_sub(limit_delta, &ch->req_lim_delta); - - srp_rsp->opcode = SRP_RSP; - srp_rsp->req_lim_delta = cpu_to_be32(limit_delta); - srp_rsp->tag = tag; - - if (rsp_code != SRP_TSK_MGMT_SUCCESS) { - srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; - srp_rsp->resp_data_len = cpu_to_be32(4); - srp_rsp->data[3] = rsp_code; - } -} - -static void srpt_handle_new_iu(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx) -{ - struct scst_cmd *scmnd = NULL; - struct srp_cmd *srp_cmd = NULL; - struct srp_tsk_mgmt *srp_tsk = NULL; - struct srpt_mgmt_ioctx *mgmt_ioctx; - scst_data_direction dir = SCST_DATA_NONE; - int indirect_desc = 0; - u8 op; - int ret; - - if (ch->state != RDMA_CHANNEL_LIVE) { - if (ch->state == RDMA_CHANNEL_CONNECTING) { - spin_lock_irq(&ch->spinlock); - list_add_tail(&ioctx->list, &ch->cmd_wait_list); - spin_unlock_irq(&ch->spinlock); - } else - srpt_reset_ioctx(ch, ioctx); - - return; - } - - dma_sync_single_for_cpu(ch->sport->sdev->device->dma_device, ioctx->dma, - MAX_MESSAGE_SIZE, DMA_FROM_DEVICE); - - ioctx->data_len = 0; - ioctx->n_rbuf = 0; - ioctx->rbufs = NULL; - ioctx->n_rdma = 0; - ioctx->n_rdma_ius = 0; - ioctx->rdma_ius = NULL; - ioctx->scmnd = NULL; - - op = *(u8 *) ioctx->buf; - switch (op) { - case SRP_CMD: - srp_cmd = ioctx->buf; - - if (srp_cmd->buf_fmt) { - ret = srpt_get_desc_tbl(ioctx, srp_cmd, &indirect_desc); - if (ret) { - srpt_build_cmd_rsp(ch, ioctx, NOT_READY, - LUN_NOT_READY, srp_cmd->tag); - goto send_rsp; - } - - if (indirect_desc) { - srpt_build_cmd_rsp(ch, ioctx, NOT_READY, - LUN_NOT_READY, srp_cmd->tag); - goto send_rsp; - } - - if (srp_cmd->buf_fmt & 0xf) - dir = SCST_DATA_READ; - else if (srp_cmd->buf_fmt >> 4) - dir = SCST_DATA_WRITE; - else - dir = SCST_DATA_NONE; - } else - dir = SCST_DATA_NONE; - - scmnd = scst_rx_cmd(ch->scst_sess, (u8 *) & srp_cmd->lun, - sizeof srp_cmd->lun, srp_cmd->cdb, 16, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC); - if (!scmnd) { - srpt_build_cmd_rsp(ch, ioctx, RECOVERED_ERROR, - INTERNAL_TARGET_FAILURE, - srp_cmd->tag); - goto send_rsp; - } - - ioctx->scmnd = scmnd; - - switch (srp_cmd->task_attr) { - case SRP_CMD_HEAD_OF_Q: - scmnd->queue_type = SCST_CMD_QUEUE_HEAD_OF_QUEUE; - break; - case SRP_CMD_ORDERED_Q: - scmnd->queue_type = SCST_CMD_QUEUE_ORDERED; - break; - case SRP_CMD_SIMPLE_Q: - scmnd->queue_type = SCST_CMD_QUEUE_SIMPLE; - break; - case SRP_CMD_ACA: - scmnd->queue_type = SCST_CMD_QUEUE_ACA; - break; - default: - scmnd->queue_type = SCST_CMD_QUEUE_ORDERED; - break; - } - - scst_cmd_set_tag(scmnd, srp_cmd->tag); - scst_cmd_set_tgt_priv(scmnd, ioctx); - - /* - * if we have buffer in mem pool and - * IO is > mem_size - we will allocate the memory buffer - * for data xfer to avoid big scatterlist with 4KB each - * allocated by scst memory module. - */ - if (mem_elements && (ioctx->data_len >= mem_size)) - ioctx->scmnd->data_buf_tgt_alloc = 1; - - spin_lock(&ch->spinlock); - scst_cmd_init_done(scmnd, SCST_CONTEXT_THREAD); - spin_unlock(&ch->spinlock); - - break; - - case SRP_TSK_MGMT: - srp_tsk = ioctx->buf; - - printk(KERN_WARNING PFX - "recv_tsk_mgmt= %d for task_tag= %lld" - " using tag= %lld cm_id= %p sess= %p\n", - srp_tsk->tsk_mgmt_func, - (unsigned long long) srp_tsk->task_tag, - (unsigned long long) srp_tsk->tag, - ch->cm_id, ch->scst_sess); - - mgmt_ioctx = kmalloc(sizeof *mgmt_ioctx, GFP_ATOMIC); - if (!mgmt_ioctx) { - srpt_build_tskmgmt_rsp(ch, ioctx, SRP_TSK_MGMT_FAILED, - srp_tsk->tag); - goto send_rsp; - } - - mgmt_ioctx->ioctx = ioctx; - mgmt_ioctx->ch = ch; - mgmt_ioctx->tag = srp_tsk->tag; - - switch (srp_tsk->tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - ret = scst_rx_mgmt_fn_tag(ch->scst_sess, - SCST_ABORT_TASK, - srp_tsk->task_tag, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC, - mgmt_ioctx); - break; - case SRP_TSK_ABORT_TASK_SET: - ret = scst_rx_mgmt_fn_lun(ch->scst_sess, - SCST_ABORT_TASK_SET, - (u8 *) & srp_tsk->lun, - sizeof srp_tsk->lun, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC, - mgmt_ioctx); - break; - case SRP_TSK_CLEAR_TASK_SET: - ret = scst_rx_mgmt_fn_lun(ch->scst_sess, - SCST_CLEAR_TASK_SET, - (u8 *) & srp_tsk->lun, - sizeof srp_tsk->lun, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC, - mgmt_ioctx); - break; -#if 0 - case SRP_TSK_LUN_RESET: - ret = scst_rx_mgmt_fn_lun(ch->scst_sess, - SCST_LUN_RESET, - (u8 *) & srp_tsk->lun, - sizeof srp_tsk->lun, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC, - mgmt_ioctx); - break; -#endif - case SRP_TSK_CLEAR_ACA: - ret = scst_rx_mgmt_fn_lun(ch->scst_sess, - SCST_CLEAR_ACA, - (u8 *) & srp_tsk->lun, - sizeof srp_tsk->lun, - thread ? SCST_NON_ATOMIC : SCST_ATOMIC, - mgmt_ioctx); - break; - default: - srpt_build_tskmgmt_rsp(ch, ioctx, - SRP_TSK_MGMT_FUNC_NOT_SUPP, - srp_tsk->tag); - goto send_rsp; - } - - break; - case SRP_I_LOGOUT: - case SRP_AER_REQ: - default: - srpt_build_cmd_rsp(ch, ioctx, ILLEGAL_REQUEST, INVALID_CDB, - ((struct srp_cmd *)ioctx->buf)->tag); - - goto send_rsp; - } - - dma_sync_single_for_device(ch->sport->sdev->device->dma_device, - ioctx->dma, MAX_MESSAGE_SIZE, - DMA_FROM_DEVICE); - - return; - - send_rsp: - if (ch->state != RDMA_CHANNEL_LIVE || - srpt_post_send(ch, ioctx, - sizeof(struct srp_rsp) + - be32_to_cpu(((struct srp_rsp *)ioctx->buf)-> - sense_data_len))) - srpt_reset_ioctx(ch, ioctx); -} - -static inline int srpt_test_ioctx_list(void) -{ - int res = (!list_empty(&srpt_thread.thread_ioctx_list) || - unlikely(kthread_should_stop())); - return res; -} - -static inline void srpt_schedule_thread(struct srpt_ioctx *ioctx) -{ - unsigned long flags; - - spin_lock_irqsave(&srpt_thread.thread_lock, flags); - list_add_tail(&ioctx->list_entry, &srpt_thread.thread_ioctx_list); - spin_unlock_irqrestore(&srpt_thread.thread_lock, flags); - wake_up(&ioctx_list_waitQ); -} - -static void srpt_completion(struct ib_cq *cq, void *ctx) -{ - struct srpt_rdma_ch *ch = ctx; - struct srpt_device *sdev = ch->sport->sdev; - struct ib_wc wc; - struct srpt_ioctx *ioctx; - - ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP); - while (ib_poll_cq(ch->cq, 1, &wc) > 0) { - if (wc.status) { - printk(KERN_ERR PFX "failed %s status= %d\n", - wc.wr_id & SRPT_OP_RECV ? "receive" : "send", - wc.status); - srpt_handle_err_comp(ch, &wc); - break; - } - - if (wc.wr_id & SRPT_OP_RECV) { - ioctx = sdev->ioctx_ring[wc.wr_id & ~SRPT_OP_RECV]; - if (thread) { - ioctx->ch = ch; - ioctx->op = IB_WC_RECV; - srpt_schedule_thread(ioctx); - } else - srpt_handle_new_iu(ch, ioctx); - continue; - } else - ioctx = sdev->ioctx_ring[wc.wr_id]; - - if (thread) { - ioctx->ch = ch; - ioctx->op = wc.opcode; - srpt_schedule_thread(ioctx); - } else { - switch (wc.opcode) { - case IB_WC_SEND: - srpt_handle_send_comp(ch, ioctx); - break; - case IB_WC_RDMA_WRITE: - case IB_WC_RDMA_READ: - srpt_handle_rdma_comp(ch, ioctx); - break; - default: - break; - } - } - } -} - -static int srpt_create_ch_ib(struct srpt_rdma_ch *ch) -{ - struct ib_qp_init_attr *qp_init; - struct srpt_device *sdev = ch->sport->sdev; - int cqe; - int ret; - - qp_init = kzalloc(sizeof *qp_init, GFP_KERNEL); - if (!qp_init) - return -ENOMEM; - - cqe = SRPT_RQ_SIZE + SRPT_SQ_SIZE - 1; - ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch, cqe, 0); - if (IS_ERR(ch->cq)) { - ret = PTR_ERR(ch->cq); - printk(KERN_ERR PFX "failed to create_cq cqe= %d ret= %d\n", - cqe, ret); - goto out; - } - - ib_req_notify_cq(ch->cq, IB_CQ_NEXT_COMP); - - qp_init->qp_context = (void *)ch; - qp_init->event_handler = srpt_qp_event; - qp_init->send_cq = ch->cq; - qp_init->recv_cq = ch->cq; - qp_init->srq = sdev->srq; - qp_init->sq_sig_type = IB_SIGNAL_REQ_WR; - qp_init->qp_type = IB_QPT_RC; - qp_init->cap.max_send_wr = SRPT_SQ_SIZE; - qp_init->cap.max_send_sge = SRPT_DEF_SG_TABLESIZE; - - ch->qp = ib_create_qp(sdev->pd, qp_init); - if (IS_ERR(ch->qp)) { - ret = PTR_ERR(ch->qp); - ib_destroy_cq(ch->cq); - printk(KERN_ERR PFX "failed to create_qp ret= %d\n", ret); - goto out; - } - - printk(KERN_DEBUG PFX "%s[%d] max_cqe= %d max_sge= %d cm_id= %p\n", - __FUNCTION__, __LINE__, ch->cq->cqe, qp_init->cap.max_send_sge, - ch->cm_id); - - ret = srpt_init_ch_qp(ch, ch->qp); - if (ret) { - ib_destroy_qp(ch->qp); - ib_destroy_cq(ch->cq); - goto out; - } - - atomic_set(&ch->req_lim_delta, SRPT_RQ_SIZE); - out: - kfree(qp_init); - return ret; -} - -static struct srpt_rdma_ch *srpt_find_channel(struct ib_cm_id *cm_id) -{ - struct srpt_device *sdev = cm_id->context; - struct srpt_rdma_ch *ch, *tmp_ch; - - spin_lock_irq(&sdev->spinlock); - list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) { - if (ch->cm_id == cm_id) { - spin_unlock_irq(&sdev->spinlock); - return ch; - } - } - - spin_unlock_irq(&sdev->spinlock); - - return NULL; -} - -static void srpt_unregister_session_done(struct scst_session *scst_sess) -{ - printk(KERN_DEBUG PFX - "%s[%d] sess= %p\n", - __FUNCTION__, __LINE__, scst_sess); -} - -static int srpt_release_channel(struct srpt_rdma_ch *ch) -{ - spin_lock_irq(&ch->sport->sdev->spinlock); - list_del(&ch->list); - spin_unlock_irq(&ch->sport->sdev->spinlock); - - printk(KERN_DEBUG PFX - "%s[%d] Release channel cm_id= %p\n", - __FUNCTION__, __LINE__, ch->cm_id); - - if (ch->scst_sess) { - printk(KERN_ERR PFX - "%s[%d] Release sess= %p sess_name= %s\n", - __FUNCTION__, __LINE__, ch->scst_sess, ch->sess_name); - scst_unregister_session(ch->scst_sess, 1, - srpt_unregister_session_done); - ch->scst_sess = NULL; - } - - ib_destroy_cm_id(ch->cm_id); - ib_destroy_qp(ch->qp); - ib_destroy_cq(ch->cq); - - kfree(ch); - return 0; -} - -static void srpt_register_channel_done(struct scst_session *scst_sess, - void *data, int status) -{ - struct srpt_rdma_ch *ch = data; - - BUG_ON(!ch); - - if (status) { - if (ch->scst_sess) { - scst_unregister_session(ch->scst_sess, 1, NULL); - ch->scst_sess = NULL; - } - printk(KERN_ERR PFX - "%s[%d] Failed to establish sess= %p status= %d\n", - __FUNCTION__, __LINE__, scst_sess, status); - } - - complete(&ch->scst_sess_done); -} - -static int srpt_disconnect_channel(struct srpt_rdma_ch *ch, int dreq) -{ - spin_lock_irq(&ch->spinlock); - ch->state = RDMA_CHANNEL_DISCONNECTING; - spin_unlock_irq(&ch->spinlock); - - if (dreq) - ib_send_cm_dreq(ch->cm_id, NULL, 0); - else - ib_send_cm_drep(ch->cm_id, NULL, 0); - - return 0; -} - -#ifndef OFED11 -static void srpt_cm_rtu_work(struct work_struct *work) -{ - struct srpt_rdma_ch *ch = container_of(work, struct srpt_rdma_ch, work); - struct srpt_ioctx *ioctx, *ioctx_tmp; - - spin_lock_irq(&ch->spinlock); - ch->state = RDMA_CHANNEL_LIVE; - spin_unlock_irq(&ch->spinlock); - srpt_ch_qp_rtr_rts(ch, ch->qp, IB_QPS_RTS); - - list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list, list) { - list_del(&ioctx->list); - srpt_handle_new_iu(ch, ioctx); - } -} -#else -static void srpt_cm_rtu_work(void *ctx) -{ - struct srpt_rdma_ch *ch = ctx; - struct srpt_ioctx *ioctx, *ioctx_tmp; - - spin_lock_irq(&ch->spinlock); - ch->state = RDMA_CHANNEL_LIVE; - spin_unlock_irq(&ch->spinlock); - srpt_ch_qp_rtr_rts(ch, ch->qp, IB_QPS_RTS); - - list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list, list) { - list_del(&ioctx->list); - srpt_handle_new_iu(ch, ioctx); - } -} -#endif - -static int srpt_cm_req_recv(struct ib_cm_id *cm_id, - struct ib_cm_req_event_param *param, - void *private_data) -{ - struct srpt_device *sdev = cm_id->context; - struct srp_login_req *req; - struct srp_login_rsp *rsp; - struct srp_login_rej *rej; - struct ib_cm_rep_param *rep_param; - struct srpt_rdma_ch *ch, *tmp_ch; - u32 it_iu_len; - int ret = 0; - - if (!sdev || !private_data) - return -EINVAL; - - rsp = kzalloc(sizeof *rsp, GFP_KERNEL); - rej = kzalloc(sizeof *rej, GFP_KERNEL); - rep_param = kzalloc(sizeof *rep_param, GFP_KERNEL); - - if (!rsp || !rej || !rep_param) { - ret = -ENOMEM; - goto out; - } - - req = (struct srp_login_req *)private_data; - - it_iu_len = be32_to_cpu(req->req_it_iu_len); - - printk(KERN_ERR PFX - "Host login i_port_id=0x%llx:0x%llx t_port_id=0x%llx:0x%llx" - " it_iu_len=%d\n", - (unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[0]), - (unsigned long long)be64_to_cpu(*(u64 *)&req->initiator_port_id[8]), - (unsigned long long)be64_to_cpu(*(u64 *)&req->target_port_id[0]), - (unsigned long long)be64_to_cpu(*(u64 *)&req->target_port_id[8]), it_iu_len); - - if (it_iu_len > MAX_MESSAGE_SIZE || it_iu_len < 64) { - rej->reason = - cpu_to_be32(SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE); - ret = -EINVAL; - printk(KERN_WARNING PFX - "Reject invalid it_iu_len=%d\n", it_iu_len); - goto reject; - } - - if ((req->req_flags & 0x3) == SRP_MULTICHAN_SINGLE) { - rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN; - - list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) { - if (!memcmp(ch->i_port_id, req->initiator_port_id, 16) - && !memcmp(ch->t_port_id, req->target_port_id, 16) - && param->port == ch->sport->port - && param->listen_id == ch->sport->sdev->cm_id - && ch->cm_id) { - /* found an existing channel */ - printk(KERN_WARNING PFX - "Found existing channel name= %s" - " cm_id= %p state= %d\n", - ch->sess_name, ch->cm_id, ch->state); - - rsp->rsp_flags = - SRP_LOGIN_RSP_MULTICHAN_TERMINATED; - - if (ch->state == RDMA_CHANNEL_LIVE) - srpt_disconnect_channel(ch, 1); - else if (ch->state == RDMA_CHANNEL_CONNECTING) { - ib_send_cm_rej(ch->cm_id, - IB_CM_REJ_NO_RESOURCES, - NULL, 0, NULL, 0); - srpt_release_channel(ch); - } - } - } - } else - rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED; - - if (((u64) (*(u64 *) req->target_port_id) != - cpu_to_be64(mellanox_ioc_guid)) || - ((u64) (*(u64 *) (req->target_port_id + 8)) != - cpu_to_be64(mellanox_ioc_guid))) { - rej->reason = - cpu_to_be32(SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL); - ret = -ENOMEM; - printk(KERN_WARNING PFX "Reject invalid target_port_id\n"); - goto reject; - } - - ch = kzalloc(sizeof *ch, GFP_KERNEL); - if (!ch) { - rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); - printk(KERN_WARNING PFX "Reject failed allocate rdma_ch\n"); - ret = -ENOMEM; - goto reject; - } - - spin_lock_init(&ch->spinlock); - memcpy(ch->i_port_id, req->initiator_port_id, 16); - memcpy(ch->t_port_id, req->target_port_id, 16); - ch->sport = &sdev->port[param->port - 1]; - ch->cm_id = cm_id; - ch->state = RDMA_CHANNEL_CONNECTING; - INIT_LIST_HEAD(&ch->cmd_wait_list); - -#ifndef OFED11 - INIT_WORK(&ch->work, srpt_cm_rtu_work); -#else - INIT_WORK(&ch->work, srpt_cm_rtu_work, (void *)ch); -#endif - - ret = srpt_create_ch_ib(ch); - if (ret) { - rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); - printk(KERN_WARNING PFX "Reject failed to create rdma_ch\n"); - goto free_ch; - } - - ret = srpt_ch_qp_rtr_rts(ch, ch->qp, IB_QPS_RTR); - if (ret) { - rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); - printk(KERN_WARNING PFX "Reject failed qp to rtr/rts ret=%d\n", ret); - goto destroy_ib; - } - - init_completion(&ch->scst_sess_done); - sprintf(ch->sess_name, "0x%016llx%016llx", - (unsigned long long)be64_to_cpu(*(u64 *)&sdev->port[param->port - 1].gid.raw[8]), - (unsigned long long)be64_to_cpu(*(u64 *) (ch->i_port_id + 8))); - ch->scst_sess = - scst_register_session(sdev->scst_tgt, 1, ch->sess_name, - ch, srpt_register_channel_done); - - wait_for_completion(&ch->scst_sess_done); - - if (!ch->scst_sess) { - rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); - printk(KERN_WARNING PFX "Reject failed to create scst sess"); - goto destroy_ib; - } - - spin_lock_irq(&sdev->spinlock); - list_add_tail(&ch->list, &sdev->rch_list); - spin_unlock_irq(&sdev->spinlock); - - printk(KERN_DEBUG PFX "Establish connection sess= %p name= %s cm_id= %p\n", - ch->scst_sess, ch->sess_name, ch->cm_id); - - scst_sess_set_tgt_priv(ch->scst_sess, ch); - - /* create srp_login_response */ - rsp->opcode = SRP_LOGIN_RSP; - rsp->tag = req->tag; - rsp->max_it_iu_len = req->req_it_iu_len; - rsp->max_ti_iu_len = req->req_it_iu_len; - rsp->buf_fmt = - cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); - rsp->req_lim_delta = cpu_to_be32(SRPT_RQ_SIZE); - atomic_set(&ch->req_lim_delta, 0); - - /* create cm reply */ - rep_param->qp_num = ch->qp->qp_num; - rep_param->private_data = (void *)rsp; - rep_param->private_data_len = sizeof *rsp; - rep_param->rnr_retry_count = 7; - rep_param->flow_control = 1; - rep_param->failover_accepted = 0; - rep_param->srq = 1; - rep_param->responder_resources = 4; - rep_param->initiator_depth = 4; - - ret = ib_send_cm_rep(cm_id, rep_param); - if (ret) - srpt_release_channel(ch); - - goto out; - - destroy_ib: - ib_destroy_qp(ch->qp); - ib_destroy_cq(ch->cq); - - free_ch: - kfree(ch); - - reject: - rej->opcode = SRP_LOGIN_REJ; - rej->tag = req->tag; - rej->buf_fmt = - cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); - - ret = ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, - (void *)rej, sizeof *rej); - - out: - kfree(rep_param); - kfree(rsp); - kfree(rej); - - return ret; -} - -static int srpt_find_and_release_channel(struct ib_cm_id *cm_id) -{ - struct srpt_rdma_ch *ch; - - ch = srpt_find_channel(cm_id); - if (!ch) - return -EINVAL; - - return srpt_release_channel(ch); -} - -static int srpt_cm_rej_recv(struct ib_cm_id *cm_id) -{ - printk(KERN_DEBUG PFX "%s[%d] cm_id= %p\n", - __FUNCTION__, __LINE__, cm_id); - return srpt_find_and_release_channel(cm_id); -} - -static int srpt_cm_rtu_recv(struct ib_cm_id *cm_id) -{ - struct srpt_rdma_ch *ch; - int ret; - - ch = srpt_find_channel(cm_id); - if (!ch) - return -EINVAL; - - if (ch->state == RDMA_CHANNEL_CONNECTING) { - struct srpt_ioctx *ioctx, *ioctx_tmp; - - spin_lock_irq(&ch->spinlock); - ch->state = RDMA_CHANNEL_LIVE; - spin_unlock_irq(&ch->spinlock); - ret = srpt_ch_qp_rtr_rts(ch, ch->qp, IB_QPS_RTS); - - list_for_each_entry_safe(ioctx, ioctx_tmp, &ch->cmd_wait_list, list) { - list_del(&ioctx->list); - srpt_handle_new_iu(ch, ioctx); - } - } else if (ch->state == RDMA_CHANNEL_DISCONNECTING) - ret = -EAGAIN; - else - ret = 0; - - if (ret) { - printk(KERN_ERR PFX "%s[%d] cm_id= %p sess_name= %s state= %d\n", - __FUNCTION__, __LINE__, cm_id, ch->sess_name, ch->state); - srpt_disconnect_channel(ch, 1); - } - - return ret; -} - -static int srpt_cm_timewait_exit(struct ib_cm_id *cm_id) -{ - printk(KERN_DEBUG PFX "%s[%d] cm_id= %p\n", - __FUNCTION__, __LINE__, cm_id); - return srpt_find_and_release_channel(cm_id); -} - -static int srpt_cm_rep_error(struct ib_cm_id *cm_id) -{ - printk(KERN_DEBUG PFX "%s[%d] cm_id= %p\n", - __FUNCTION__, __LINE__, cm_id); - return srpt_find_and_release_channel(cm_id); -} - -static int srpt_cm_dreq_recv(struct ib_cm_id *cm_id) -{ - struct srpt_rdma_ch *ch; - - ch = srpt_find_channel(cm_id); - - if (!ch) - return -EINVAL; - - printk(KERN_DEBUG PFX "%s[%d] cm_id= %p ch->state= %d\n", - __FUNCTION__, __LINE__, cm_id, ch->state); - - switch (ch->state) { - case RDMA_CHANNEL_LIVE: - case RDMA_CHANNEL_CONNECTING: - srpt_disconnect_channel(ch, 0); - break; - case RDMA_CHANNEL_DISCONNECTING: - default: - break; - } - - return 0; -} - -static int srpt_cm_drep_recv(struct ib_cm_id *cm_id) -{ - struct srpt_rdma_ch *ch; - - ch = srpt_find_channel(cm_id); - - if (!ch) - return -EINVAL; - - printk(KERN_DEBUG PFX "%s[%d] cm_id= %p, state= %d\n", - __FUNCTION__, __LINE__, cm_id, ch->state); - - return srpt_release_channel(ch); -} - -static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) -{ - int ret = 0; - - switch (event->event) { - case IB_CM_REQ_RECEIVED: - ret = - srpt_cm_req_recv(cm_id, &event->param.req_rcvd, - event->private_data); - break; - case IB_CM_REJ_RECEIVED: - ret = srpt_cm_rej_recv(cm_id); - break; - case IB_CM_RTU_RECEIVED: - case IB_CM_USER_ESTABLISHED: - ret = srpt_cm_rtu_recv(cm_id); - break; - case IB_CM_DREQ_RECEIVED: - ret = srpt_cm_dreq_recv(cm_id); - break; - case IB_CM_DREP_RECEIVED: - ret = srpt_cm_drep_recv(cm_id); - break; - case IB_CM_TIMEWAIT_EXIT: - ret = srpt_cm_timewait_exit(cm_id); - break; - case IB_CM_REP_ERROR: - ret = srpt_cm_rep_error(cm_id); - break; - default: - break; - } - - return ret; -} - -static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, - struct srpt_ioctx *ioctx, - struct scst_cmd *scmnd) -{ - struct scatterlist *scat; - scst_data_direction dir; - struct rdma_iu *riu; - struct srp_direct_buf *db; - dma_addr_t dma_addr; - struct ib_sge *sge; - u64 raddr; - u32 rsize; - u32 tsize; - u32 dma_len; - int count, nrdma; - int i, j, k; - - scat = scst_cmd_get_sg(scmnd); - dir = scst_cmd_get_data_direction(scmnd); - count = dma_map_sg(ch->sport->sdev->device->dma_device, scat, - scst_cmd_get_sg_cnt(scmnd), - scst_to_tgt_dma_dir(dir)); - if (unlikely(!count)) - return -EBUSY; - - if (ioctx->rdma_ius && ioctx->n_rdma_ius) - nrdma = ioctx->n_rdma_ius; - else { - nrdma = count / SRPT_DEF_SG_TABLESIZE + ioctx->n_rbuf; - - ioctx->rdma_ius = kzalloc(nrdma * sizeof *riu, - scst_cmd_atomic(scmnd) - ? GFP_ATOMIC : GFP_KERNEL); - if (!ioctx->rdma_ius) { - dma_unmap_sg(ch->sport->sdev->device->dma_device, - scat, scst_cmd_get_sg_cnt(scmnd), - scst_to_tgt_dma_dir(dir)); - return -ENOMEM; - } - - ioctx->n_rdma_ius = nrdma; - } - - db = ioctx->rbufs; - tsize = (dir == SCST_DATA_READ) ? - scst_cmd_get_resp_data_len(scmnd) : scst_cmd_get_bufflen(scmnd); - dma_len = sg_dma_len(&scat[0]); - riu = ioctx->rdma_ius; - - /* - * For each remote desc - calculate the #ib_sge. - * If #ib_sge < SRPT_DEF_SG_TABLESIZE per rdma operation then - * each remote desc rdma_iu is required a rdma wr; - * else - * we need to allocate extra rdma_iu to carry extra #ib_sge in - * another rdma wr - */ - for (i = 0, j = 0; - j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) { - rsize = be32_to_cpu(db->len); - raddr = be64_to_cpu(db->va); - riu->raddr = raddr; - riu->rkey = be32_to_cpu(db->key); - riu->sge_cnt = 0; - - /* calculate how many sge required for this remote_buf */ - while (rsize > 0 && tsize > 0) { - - if (rsize >= dma_len) { - tsize -= dma_len; - rsize -= dma_len; - raddr += dma_len; - - if (tsize > 0) { - ++j; - if (j < count) - dma_len = sg_dma_len(&scat[j]); - } - } else { - tsize -= rsize; - dma_len -= rsize; - rsize = 0; - } - - ++riu->sge_cnt; - - if (rsize > 0 && riu->sge_cnt == SRPT_DEF_SG_TABLESIZE) { - riu->sge = - kmalloc(riu->sge_cnt * sizeof *riu->sge, - scst_cmd_atomic(scmnd) - ? GFP_ATOMIC : GFP_KERNEL); - if (!riu->sge) - goto free_mem; - - printk(KERN_WARNING PFX - "Required extra rdma sg_count= %d," - " sg_cnt= %d, rsize= %d tsize=%d\n", - count, scmnd->sg_cnt, rsize, tsize); - - ++ioctx->n_rdma; - ++riu; - riu->sge_cnt = 0; - riu->raddr = raddr; - riu->rkey = be32_to_cpu(db->key); - } - } - - riu->sge = kmalloc(riu->sge_cnt * sizeof *riu->sge, - scst_cmd_atomic(scmnd) - ? GFP_ATOMIC : GFP_KERNEL); - - if (!riu->sge) - goto free_mem; - - ++ioctx->n_rdma; - } - - db = ioctx->rbufs; - scat = scst_cmd_get_sg(scmnd); - tsize = (dir == SCST_DATA_READ) ? - scst_cmd_get_resp_data_len(scmnd) : scst_cmd_get_bufflen(scmnd); - riu = ioctx->rdma_ius; - dma_len = sg_dma_len(&scat[0]); - dma_addr = sg_dma_address(&scat[0]); - - /* this second loop is really mapped sg_addres to rdma_iu->ib_sge */ - for (i = 0, j = 0; - j < count && i < ioctx->n_rbuf && tsize > 0; ++i, ++riu, ++db) { - rsize = be32_to_cpu(db->len); - sge = riu->sge; - k = 0; - - while (rsize > 0 && tsize > 0) { - sge->addr = dma_addr; - sge->lkey = ch->sport->sdev->mr->lkey; - - if (rsize >= dma_len) { - sge->length = (tsize < dma_len) ? tsize : dma_len; - tsize -= dma_len; - rsize -= dma_len; - - if (tsize > 0) { - ++j; - if (j < count) { - dma_len = sg_dma_len(&scat[j]); - dma_addr = sg_dma_address(&scat[j]); - } - } - } else { - sge->length = (tsize < rsize) ? tsize : rsize; - tsize -= rsize; - dma_len -= rsize; - dma_addr += rsize; - rsize = 0; - } - - ++k; - if (k == riu->sge_cnt && rsize > 0) { - ++riu; - sge = riu->sge; - k = 0; - } else if (rsize > 0) - ++sge; - } - } - - return 0; - - free_mem: - while (ioctx->n_rdma) - kfree(ioctx->rdma_ius[ioctx->n_rdma--].sge); - - kfree(ioctx->rdma_ius); - - dma_unmap_sg(ch->sport->sdev->device->dma_device, - scat, scst_cmd_get_sg_cnt(scmnd), - scst_to_tgt_dma_dir(dir)); - - return -ENOMEM; -} - -static int srpt_perform_rdmas(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx, - scst_data_direction dir) -{ - struct ib_send_wr wr; - struct ib_send_wr *bad_wr; - struct rdma_iu *riu; - int i; - int ret = 0; - - riu = ioctx->rdma_ius; - memset(&wr, 0, sizeof wr); - - for (i = 0; i < ioctx->n_rdma; ++i, ++riu) { - wr.opcode = (dir == SCST_DATA_READ) ? - IB_WR_RDMA_WRITE : IB_WR_RDMA_READ; - wr.next = NULL; - wr.wr_id = ioctx->index; - wr.wr.rdma.remote_addr = riu->raddr; - wr.wr.rdma.rkey = riu->rkey; - wr.num_sge = riu->sge_cnt; - wr.sg_list = riu->sge; - - /* only get completion event for the last rdma wr */ - if (i == (ioctx->n_rdma - 1) && dir == SCST_DATA_WRITE) - wr.send_flags = IB_SEND_SIGNALED; - - ret = ib_post_send(ch->qp, &wr, &bad_wr); - if (ret) - break; - } - - return ret; -} - -static int srpt_xfer_data(struct srpt_rdma_ch *ch, struct srpt_ioctx *ioctx, - struct scst_cmd *scmnd) -{ - int ret; - - ret = srpt_map_sg_to_ib_sge(ch, ioctx, scmnd); - if (ret) { - printk(KERN_ERR PFX "%s[%d] ret= %d\n", __FUNCTION__, __LINE__, - ret); - ret = SCST_TGT_RES_QUEUE_FULL; - goto out; - } - - ret = srpt_perform_rdmas(ch, ioctx, scst_cmd_get_data_direction(scmnd)); - if (ret) { - printk(KERN_ERR PFX "%s[%d] ret= %d\n", - __FUNCTION__, __LINE__, ret); - if (ret == -EAGAIN || ret == -ENOMEM) - ret = SCST_TGT_RES_QUEUE_FULL; - else - ret = SCST_TGT_RES_FATAL_ERROR; - goto out; - } - - ret = SCST_TGT_RES_SUCCESS; - - out: - return ret; -} - -static int srpt_rdy_to_xfer(struct scst_cmd *scmnd) -{ - struct srpt_rdma_ch *ch; - struct srpt_ioctx *ioctx; - - ioctx = scst_cmd_get_tgt_priv(scmnd); - BUG_ON(!ioctx); - - ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)); - BUG_ON(!ch); - - if (ch->state == RDMA_CHANNEL_DISCONNECTING) - return SCST_TGT_RES_FATAL_ERROR; - else if (ch->state == RDMA_CHANNEL_CONNECTING) - return SCST_TGT_RES_QUEUE_FULL; - - return srpt_xfer_data(ch, ioctx, scmnd); -} - -static int srpt_xmit_response(struct scst_cmd *scmnd) -{ - struct srpt_rdma_ch *ch; - struct srpt_ioctx *ioctx; - struct srp_rsp *srp_rsp; - u64 tag; - int ret = SCST_TGT_RES_SUCCESS; - int dir; - int status; - - ioctx = scst_cmd_get_tgt_priv(scmnd); - BUG_ON(!ioctx); - - ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)); - BUG_ON(!ch); - - tag = scst_cmd_get_tag(scmnd); - - if (ch->state != RDMA_CHANNEL_LIVE) { - printk(KERN_ERR PFX - "%s[%d] tag= %lld channel in bad state %d\n", - __FUNCTION__, __LINE__, (unsigned long long)tag, ch->state); - - if (ch->state == RDMA_CHANNEL_DISCONNECTING) - ret = SCST_TGT_RES_FATAL_ERROR; - else if (ch->state == RDMA_CHANNEL_CONNECTING) - ret = SCST_TGT_RES_QUEUE_FULL; - - if (unlikely(scst_cmd_aborted(scmnd))) - ret = SCST_TGT_RES_SUCCESS; - - goto out; - } - - dma_sync_single_for_cpu(ch->sport->sdev->device->dma_device, ioctx->dma, - MAX_MESSAGE_SIZE, DMA_TO_DEVICE); - - srp_rsp = ioctx->buf; - - if (unlikely(scst_cmd_aborted(scmnd))) { - printk(KERN_ERR PFX - "%s[%d] tag= %lld already get aborted\n", - __FUNCTION__, __LINE__, (unsigned long long)tag); - - srpt_build_cmd_rsp(ch, ioctx, NO_SENSE, NO_ADD_SENSE, tag); - srp_rsp->status = 0x40; - goto post_send; - } - - dir = scst_cmd_get_data_direction(scmnd); - status = scst_cmd_get_status(scmnd) & 0xff; - - if (SCST_SENSE_VALID(scst_cmd_get_sense_buffer(scmnd))) { - srpt_build_cmd_rsp(ch, ioctx, NO_SENSE, NO_ADD_SENSE, tag); - - srp_rsp->sense_data_len = scst_cmd_get_sense_buffer_len(scmnd); - if (srp_rsp->sense_data_len > - (MAX_MESSAGE_SIZE - sizeof *srp_rsp)) - srp_rsp->sense_data_len = - MAX_MESSAGE_SIZE - sizeof *srp_rsp; - - memcpy((u8 *) (srp_rsp + 1), scst_cmd_get_sense_buffer(scmnd), - srp_rsp->sense_data_len); - - srp_rsp->sense_data_len = cpu_to_be32(srp_rsp->sense_data_len); - srp_rsp->flags |= SRP_RSP_FLAG_SNSVALID; - - if (!status) - status = SAM_STAT_CHECK_CONDITION; - } else - srpt_build_cmd_rsp(ch, ioctx, NO_SENSE, NO_ADD_SENSE, tag); - - srp_rsp->status = status; - - /* transfer read data if any */ - if (dir == SCST_DATA_READ && scst_cmd_get_resp_data_len(scmnd)) { - ret = srpt_xfer_data(ch, ioctx, scmnd); - if (ret != SCST_TGT_RES_SUCCESS) { - printk(KERN_ERR PFX - "%s[%d] tag= %lld xfer_data failed\n", - __FUNCTION__, __LINE__, (unsigned long long)tag); - goto out; - } - } - - post_send: - if (srpt_post_send(ch, ioctx, - sizeof *srp_rsp + - be32_to_cpu(srp_rsp->sense_data_len))) { - printk(KERN_ERR PFX "%s[%d] ch->state= %d tag= %lld\n", - __FUNCTION__, __LINE__, ch->state, - (unsigned long long)tag); - ret = SCST_TGT_RES_FATAL_ERROR; - } - - out: - return ret; -} - -static void srpt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd) -{ - struct srpt_rdma_ch *ch; - struct srpt_mgmt_ioctx *mgmt_ioctx; - struct srpt_ioctx *ioctx; - - mgmt_ioctx = scst_mgmt_cmd_get_tgt_priv(mcmnd); - BUG_ON(!mgmt_ioctx); - - ch = mgmt_ioctx->ch; - BUG_ON(!ch); - - ioctx = mgmt_ioctx->ioctx; - BUG_ON(!ioctx); - - printk(KERN_WARNING PFX - "%s[%d] tsk_mgmt_done for tag= %lld status=%d\n", - __FUNCTION__, __LINE__,(unsigned long long)mgmt_ioctx->tag, - scst_mgmt_cmd_get_status(mcmnd)); - - srpt_build_tskmgmt_rsp(ch, ioctx, - (scst_mgmt_cmd_get_status(mcmnd) == - SCST_MGMT_STATUS_SUCCESS) ? SRP_TSK_MGMT_SUCCESS - : SRP_TSK_MGMT_FAILED, mgmt_ioctx->tag); - srpt_post_send(ch, ioctx, sizeof(struct srp_rsp) + 4); - - scst_mgmt_cmd_set_tgt_priv(mcmnd, NULL); - - kfree(mgmt_ioctx); -} - -static void srpt_on_free_cmd(struct scst_cmd *scmnd) -{ - struct srpt_rdma_ch *ch; - struct srpt_ioctx *ioctx; - - ioctx = scst_cmd_get_tgt_priv(scmnd); - BUG_ON(!ioctx); - - ch = scst_sess_get_tgt_priv(scst_cmd_get_session(scmnd)); - BUG_ON(!ch); - - srpt_reset_ioctx(ch, ioctx); - scst_cmd_set_tgt_priv(scmnd, NULL); -} - -static int srpt_detect(struct scst_tgt_template *tp) -{ - struct srpt_device *sdev; - struct srpt_port *sport; - int i; - int count = 0; - - list_for_each_entry(sdev, &srpt_devices, list) { - - sdev->scst_tgt = scst_register(tp, NULL); - if (!sdev->scst_tgt) - goto out; - - scst_tgt_set_tgt_priv(sdev->scst_tgt, sdev); - - for (i = 1; i <= sdev->device->phys_port_cnt; i++) { - sport = &sdev->port[i - 1]; - sport->sdev = sdev; - sport->port = i; - - if (srpt_refresh_port(sport)) { - scst_unregister(sdev->scst_tgt); - goto out; - } - } - - ++count; - } - out: - return count; -} - -static int srpt_release(struct scst_tgt *scst_tgt) -{ - struct srpt_device *sdev = scst_tgt_get_tgt_priv(scst_tgt); - struct srpt_port *sport; - struct srpt_rdma_ch *ch, *tmp_ch; - struct ib_port_modify port_modify = { - .clr_port_cap_mask = IB_PORT_DEVICE_MGMT_SUP - }; - int i; - - list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) - srpt_release_channel(ch); - - for (i = 1; i <= sdev->device->phys_port_cnt; i++) { - sport = &sdev->port[i - 1]; - ib_modify_port(sdev->device, sport->port, 0, &port_modify); - ib_unregister_mad_agent(sport->mad_agent); - } - - scst_tgt_set_tgt_priv(scst_tgt, NULL); - - complete(&sdev->scst_released); - - return 0; -} - -static int srpt_alloc_data_buf(struct scst_cmd *scmnd) -{ - struct srpt_ioctx *ioctx; - struct mem_elem *mel; - struct scatterlist *scat; - struct rdma_iu *riu; - int nrdma, i, index; - u32 tsize; - struct srp_direct_buf *db; - - ioctx = scst_cmd_get_tgt_priv(scmnd); - BUG_ON(!ioctx); - - tsize = scst_cmd_get_bufflen(scmnd); - nrdma = tsize / mem_size + ioctx->n_rbuf; - - if (nrdma > atomic_read(&mem_avail)) { - printk(KERN_ERR PFX "!!ALERT mem_avail= %d\n", atomic_read(&mem_avail)); - goto out; - } - - riu = kzalloc(nrdma * sizeof *riu, scst_cmd_atomic(scmnd) - ? GFP_ATOMIC : GFP_KERNEL); - if (!riu) - goto out; - - ioctx->n_rdma_ius = nrdma; - - scat = kzalloc(nrdma * sizeof *scat, scst_cmd_atomic(scmnd) - ? GFP_ATOMIC : GFP_KERNEL); - if (!scat) { - kfree(riu); - goto out; - } - - ioctx->rdma_ius = riu; - scmnd->sg = scat; - db = ioctx->rbufs; - - for (i = 0, index = 0; i < nrdma && tsize > 0; ++i) { - mel = srpt_get_mem_elem(&index); - if (!mel || !index) - goto release_mem; - - if (tsize > mem_size) { - tsize -= mem_size; - scat[i].length = mem_size; - } else { - scat[i].length = tsize; - tsize = 0; - } - riu[i].mem_id = index; - scat[i].page = mel->page; - scat[i].offset = 0; - index = 0; - } - scmnd->sg_cnt = i; - return 0; - - release_mem: - printk(KERN_WARNING PFX "ALERT! alloc_mem mem_avail= %d n_mem_elem=%d\n", - atomic_read(&mem_avail), i); - - riu = ioctx->rdma_ius; - while (i) - srpt_free_mem_elem(riu[--i].mem_id); - - kfree(ioctx->rdma_ius); - kfree(scmnd->sg); - - out: - ioctx->rdma_ius = NULL; - ioctx->n_rdma_ius = 0; - scmnd->sg = NULL; - scmnd->sg_cnt = 0; - - /* scst will alloc memory for this command */ - return 1; -} - -int srpt_ioctx_thread(void *arg) -{ - struct srpt_ioctx *ioctx; - - current->flags |= PF_NOFREEZE; - - spin_lock_irq(&srpt_thread.thread_lock); - while(!kthread_should_stop()) { - wait_queue_t wait; - init_waitqueue_entry(&wait, current); - - if(!srpt_test_ioctx_list()) { - add_wait_queue_exclusive(&ioctx_list_waitQ, &wait); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (srpt_test_ioctx_list()) - break; - spin_unlock_irq(&srpt_thread.thread_lock); - schedule(); - spin_lock_irq(&srpt_thread.thread_lock); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&ioctx_list_waitQ, &wait); - } - - while(!list_empty(&srpt_thread.thread_ioctx_list)) { - ioctx = list_entry(srpt_thread.thread_ioctx_list.next, - struct srpt_ioctx, list_entry); - - list_del(&ioctx->list_entry); - - spin_unlock_irq(&srpt_thread.thread_lock); - switch (ioctx->op) { - case IB_WC_SEND: - srpt_handle_send_comp(ioctx->ch, ioctx); - break; - case IB_WC_RDMA_WRITE: - case IB_WC_RDMA_READ: - srpt_handle_rdma_comp(ioctx->ch, ioctx); - break; - case IB_WC_RECV: - srpt_handle_new_iu(ioctx->ch, ioctx); - break; - default: - break; - } - spin_lock_irq(&srpt_thread.thread_lock); - } - } - spin_unlock_irq(&srpt_thread.thread_lock); - - return 0; -} - -struct scst_tgt_template srpt_template = { - .name = DRV_NAME, - .sg_tablesize = SRPT_DEF_SG_TABLESIZE, - .xmit_response_atomic = 1, - .rdy_to_xfer_atomic = 1, - .no_proc_entry = 1, - .detect = srpt_detect, - .release = srpt_release, - .xmit_response = srpt_xmit_response, - .rdy_to_xfer = srpt_rdy_to_xfer, - .on_free_cmd = srpt_on_free_cmd, - .alloc_data_buf = srpt_alloc_data_buf, - .task_mgmt_fn_done = srpt_tsk_mgmt_done -}; - -static void srpt_release_class_dev(struct class_device *class_dev) -{ -} - -static struct class srpt_class = { - .name = "infiniband_srpt", - .release = srpt_release_class_dev -}; - -static ssize_t show_login_info(struct class_device *class_dev, char *buf) -{ - struct srpt_device *sdev = - container_of(class_dev, struct srpt_device, class_dev); - struct srpt_port *sport; - int i; - int len = 0; - - for (i = 0; i < sdev->device->phys_port_cnt; i++) { - sport = &sdev->port[i]; - - len += sprintf(buf, - "tid_ext=%016llx,ioc_guid=%016llx,pkey=ffff," - "dgid=%04x%04x%04x%04x%04x%04x%04x%04x,service_id=%016llx\n", - (unsigned long long) mellanox_ioc_guid, - (unsigned long long) mellanox_ioc_guid, - be16_to_cpu(((__be16 *) sport->gid.raw)[0]), - be16_to_cpu(((__be16 *) sport->gid.raw)[1]), - be16_to_cpu(((__be16 *) sport->gid.raw)[2]), - be16_to_cpu(((__be16 *) sport->gid.raw)[3]), - be16_to_cpu(((__be16 *) sport->gid.raw)[4]), - be16_to_cpu(((__be16 *) sport->gid.raw)[5]), - be16_to_cpu(((__be16 *) sport->gid.raw)[6]), - be16_to_cpu(((__be16 *) sport->gid.raw)[7]), - (unsigned long long) mellanox_ioc_guid); - buf += len; - } - - return len; -} - -static CLASS_DEVICE_ATTR(login_info, S_IRUGO, show_login_info, NULL); - -static ssize_t show_mem_info(struct class_device *class_dev, char *buf) -{ - return sprintf(buf, "mem_avail= %d mem_elements= %d mem_size= %d\n", - atomic_read(&mem_avail), mem_elements, mem_size); -} - -static CLASS_DEVICE_ATTR(mem_info, S_IRUGO, show_mem_info, NULL); - -static void srpt_add_one(struct ib_device *device) -{ - struct srpt_device *sdev; - struct ib_srq_init_attr srq_attr; - int i; - - sdev = kzalloc(sizeof *sdev, GFP_KERNEL); - if (!sdev) - return; - - sdev->device = device; - init_completion(&sdev->scst_released); - - sdev->class_dev.class = &srpt_class; - sdev->class_dev.dev = device->dma_device; - snprintf(sdev->class_dev.class_id, BUS_ID_SIZE, "srpt-%s", device->name); - - if (class_device_register(&sdev->class_dev)) - goto free_dev; - if (class_device_create_file(&sdev->class_dev, &class_device_attr_login_info)) - goto err_class; - if (class_device_create_file(&sdev->class_dev, &class_device_attr_mem_info)) - goto err_class; - - if (ib_query_device(device, &sdev->dev_attr)) - goto err_class; - - sdev->pd = ib_alloc_pd(device); - if (IS_ERR(sdev->pd)) - goto err_class; - - sdev->mr = ib_get_dma_mr(sdev->pd, IB_ACCESS_LOCAL_WRITE); - if (IS_ERR(sdev->mr)) - goto err_pd; - - srq_attr.event_handler = srpt_srq_event; - srq_attr.srq_context = (void *)sdev; - srq_attr.attr.max_wr = min(SRPT_SRQ_SIZE, sdev->dev_attr.max_srq_wr); - srq_attr.attr.max_sge = 1; - srq_attr.attr.srq_limit = 0; - - sdev->srq = ib_create_srq(sdev->pd, &srq_attr); - if (IS_ERR(sdev->srq)) - goto err_mr; - - printk(KERN_DEBUG PFX "%s[%d] create SRQ #wr= %d dev= %s\n", - __FUNCTION__, __LINE__, srq_attr.attr.max_wr, device->name); - - if (!mellanox_ioc_guid) - mellanox_ioc_guid = be64_to_cpu(device->node_guid); - - sdev->cm_id = ib_create_cm_id(device, srpt_cm_handler, sdev); - if (IS_ERR(sdev->cm_id)) - goto err_srq; - - /* print out target login information */ - printk("Target login info: " - "id_ext=%016llx,ioc_guid=%016llx,pkey=ffff,service_id=%016llx\n", - (unsigned long long) mellanox_ioc_guid, - (unsigned long long) mellanox_ioc_guid, - (unsigned long long) mellanox_ioc_guid); - - /* - * We do not have a consistent service_id (ie. also id_ext of target_id) - * to identify this target. We currently use the guid of the first HCA - * in the system as service_id; therefore, the target_id will change - * if this HCA is gone bad and replaced by different HCA - */ - if (ib_cm_listen(sdev->cm_id, cpu_to_be64(mellanox_ioc_guid), 0, NULL)) - goto err_cm; - - INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device, - srpt_event_handler); - if (ib_register_event_handler(&sdev->event_handler)) - goto err_cm; - - if (srpt_alloc_ioctx_ring(sdev)) - goto err_event; - - INIT_LIST_HEAD(&sdev->rch_list); - spin_lock_init(&sdev->spinlock); - - for (i = 0; i < SRPT_SRQ_SIZE; ++i) - srpt_post_recv(sdev, sdev->ioctx_ring[i]); - - list_add_tail(&sdev->list, &srpt_devices); - - ib_set_client_data(device, &srpt_client, sdev); - - return; - - err_event: - ib_unregister_event_handler(&sdev->event_handler); - err_cm: - ib_destroy_cm_id(sdev->cm_id); - err_srq: - ib_destroy_srq(sdev->srq); - err_mr: - ib_dereg_mr(sdev->mr); - err_pd: - ib_dealloc_pd(sdev->pd); - err_class: - class_device_unregister(&sdev->class_dev); - free_dev: - kfree(sdev); -} - -static void srpt_remove_one(struct ib_device *device) -{ - struct srpt_device *sdev; - int i; - - sdev = ib_get_client_data(device, &srpt_client); - if (!sdev) - return; - - wait_for_completion(&sdev->scst_released); - - ib_unregister_event_handler(&sdev->event_handler); - ib_destroy_cm_id(sdev->cm_id); - ib_destroy_srq(sdev->srq); - ib_dereg_mr(sdev->mr); - ib_dealloc_pd(sdev->pd); - class_device_unregister(&sdev->class_dev); - - for (i = 0; i < SRPT_SRQ_SIZE; ++i) - srpt_free_ioctx(sdev, sdev->ioctx_ring[i]); - - list_del(&sdev->list); - kfree(sdev); -} - -static int __init srpt_init_module(void) -{ - int ret; - - INIT_LIST_HEAD(&srpt_devices); - - ret = class_register(&srpt_class); - if (ret) { - printk(KERN_ERR PFX "couldn't register class ib_srpt\n"); - return ret; - } - - ret = srpt_mempool_create(); - if (ret) { - printk(KERN_ERR PFX "couldn't allocate mem buffers\n"); - mem_elements = 0; - } - - ret = ib_register_client(&srpt_client); - if (ret) { - printk(KERN_ERR PFX "couldn't register IB client\n"); - goto mem_out; - } - - ret = scst_register_target_template(&srpt_template); - if (ret < 0) { - printk(KERN_ERR PFX "couldn't register with scst\n"); - ib_unregister_client(&srpt_client); - ret = -ENODEV; - goto ib_out; - } - - if (thread) { - spin_lock_init(&srpt_thread.thread_lock); - INIT_LIST_HEAD(&srpt_thread.thread_ioctx_list); - srpt_thread.thread = kthread_run(srpt_ioctx_thread, - NULL, "srpt_thread"); - if (IS_ERR(srpt_thread.thread)) { - srpt_thread.thread = NULL; - thread = 0; - } - } - - return 0; - - ib_out: - ib_unregister_client(&srpt_client); - mem_out: - srpt_mempool_destroy(); - class_unregister(&srpt_class); - return ret; -} - -static void __exit srpt_cleanup_module(void) -{ - if (srpt_thread.thread) - kthread_stop(srpt_thread.thread); - scst_unregister_target_template(&srpt_template); - ib_unregister_client(&srpt_client); - srpt_mempool_destroy(); - class_unregister(&srpt_class); -} - -module_init(srpt_init_module); -module_exit(srpt_cleanup_module); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h deleted file mode 100644 index cba19b1..0000000 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2006 Mellanox Technology Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef IB_SRPT_H -#define IB_SRPT_H - -#include <linux/version.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/mutex.h> - -#include <rdma/ib_verbs.h> -#include <rdma/ib_sa.h> -#include <rdma/ib_cm.h> - -#include <scsi/srp.h> - -#include <scsi_tgt.h> - -#include "ib_dm_mad.h" - -#define SRP_SERVICE_NAME_PREFIX "SRP.T10:" - -enum { - SRP_PROTOCOL = 0x0108, - SRP_PROTOCOL_VERSION = 0x0001, - SRP_IO_SUBCLASS = 0x609e, - SRP_SEND_TO_IOC = 0x01, - SRP_SEND_FROM_IOC = 0x02, - SRP_RDMA_READ_FROM_IOC = 0x08, - SRP_RDMA_WRITE_FROM_IOC = 0x20, - - SRP_TSK_MGMT_SUCCESS = 0x00, - SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04, - SRP_TSK_MGMT_FAILED = 0x05, - - SRP_CMD_SIMPLE_Q = 0x0, - SRP_CMD_HEAD_OF_Q = 0x1, - SRP_CMD_ORDERED_Q = 0x2, - SRP_CMD_ACA = 0x4, - - SRP_LOGIN_RSP_MULTICHAN_NO_CHAN = 0x0, - SRP_LOGIN_RSP_MULTICHAN_TERMINATED = 0x1, - SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2, - - SRPT_DEF_SG_TABLESIZE = 16, - - SRPT_SQ_SIZE = 128 * SRPT_DEF_SG_TABLESIZE, - SRPT_RQ_SIZE = 128, - SRPT_SRQ_SIZE = 4095, - - MAX_MESSAGE_SIZE = 996, - MAX_RDMA_SIZE = 65536 -}; - -#define SRPT_OP_RECV (1 << 31) - -struct rdma_iu { - u64 raddr; - u32 rkey; - struct ib_sge *sge; - u32 sge_cnt; - int mem_id; -}; - -struct srpt_ioctx { - int index; - void *buf; - dma_addr_t dma; - struct rdma_iu *rdma_ius; - struct srp_direct_buf *rbufs; - struct srp_direct_buf single_rbuf; - struct list_head list; - u16 n_rdma_ius; - u8 n_rdma; - u8 n_rbuf; - - enum ib_wc_opcode op; - struct list_head list_entry; - struct srpt_rdma_ch *ch; - struct scst_cmd *scmnd; - u64 data_len; -}; - -struct srpt_mgmt_ioctx { - struct srpt_ioctx *ioctx; - struct srpt_rdma_ch *ch; - u64 tag; -}; - -/* channel state */ -enum rdma_ch_state { - RDMA_CHANNEL_CONNECTING, - RDMA_CHANNEL_LIVE, - RDMA_CHANNEL_DISCONNECTING -}; - -struct srpt_rdma_ch { - struct ib_cm_id *cm_id; - struct ib_qp *qp; - struct ib_cq *cq; - struct srpt_port *sport; - u8 i_port_id[16]; - u8 t_port_id[16]; - atomic_t req_lim_delta; - spinlock_t spinlock; - enum rdma_ch_state state; - struct list_head list; - struct list_head cmd_wait_list; - struct work_struct work; - - struct completion scst_sess_done; - struct scst_session *scst_sess; - u8 sess_name[32]; -}; - -struct srpt_port { - struct srpt_device *sdev; - struct ib_mad_agent *mad_agent; - u8 port; - u16 sm_lid; - u16 lid; - union ib_gid gid; -}; - -struct srpt_device { - struct ib_device *device; - struct ib_pd *pd; - struct ib_mr *mr; - struct ib_srq *srq; - struct ib_cm_id *cm_id; - struct ib_device_attr dev_attr; - struct srpt_ioctx *ioctx_ring[SRPT_SRQ_SIZE]; - struct list_head list; - struct list_head rch_list; - spinlock_t spinlock; - struct srpt_port port[2]; - struct ib_event_handler event_handler; - struct completion scst_released; - struct class_device class_dev; - - struct scst_tgt *scst_tgt; -}; - -/* sense code/qualifier pairs */ -enum { - NO_ADD_SENSE = 0x00, - LUN_NOT_READY = 0x04, - INVALID_CDB = 0x24, - INTERNAL_TARGET_FAILURE = 0x44 -}; - -struct sense_data { - u8 err_code; - u8 segment_number; - u8 key; - u8 info_bytes[4]; - u8 addl_sense_len; - u8 cmd_info_bytes[4]; - u8 addl_sense_code; - u8 addl_sense_code_qual; - u16 asc_ascq; - u8 fru_code; - u8 sense_bytes[3]; -}; - -#endif /* IB_SRPT_H */ diff --git a/drivers/infiniband/ulp/srpt/scsi_tgt.h b/drivers/infiniband/ulp/srpt/scsi_tgt.h deleted file mode 100644 index f801a7a..0000000 --- a/drivers/infiniband/ulp/srpt/scsi_tgt.h +++ /dev/null @@ -1,2474 +0,0 @@ -/* - * include/scsi_tgt.h - * - * Copyright (C) 2004-2007 Vladislav Bolkhovitin <vst@vlnb.net> - * and Leonid Stoljar - * - * Main SCSI target mid-level include file. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2 - * of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SCST_H -#define __SCST_H - -#include <linux/types.h> -#include <linux/version.h> -#include <linux/blkdev.h> -#include <linux/interrupt.h> -#include <linux/proc_fs.h> - -#ifdef SCST_HIGHMEM -#include <asm/kmap_types.h> -#endif -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_eh.h> -#include <scsi/scsi.h> - -#include <scst_const.h> - -/* Version numbers, the same as for the kernel */ -#define SCST_VERSION_CODE 0x000906 -#define SCST_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#define SCST_VERSION_STRING "0.9.6-pre3" - -/************************************************************* - ** States of command processing state machine - *************************************************************/ - -/* A cmd is created, but scst_cmd_init_done() not called */ -#define SCST_CMD_STATE_INIT_WAIT 1 - -/* LUN translation (cmd->tgt_dev assignment) */ -#define SCST_CMD_STATE_INIT 2 - -/* Dev handler's parse() is going to be called */ -#define SCST_CMD_STATE_DEV_PARSE 4 - -/* Allocation of the cmd's data buffer */ -#define SCST_CMD_STATE_PREPARE_SPACE 5 - -/* Allocation of the cmd's data buffer */ -#define SCST_CMD_STATE_PREPROCESS_DONE 6 - -/* Target driver's rdy_to_xfer() is going to be called */ -#define SCST_CMD_STATE_RDY_TO_XFER 7 - -/* Waiting for data from the initiator (until scst_rx_data() called) */ -#define SCST_CMD_STATE_DATA_WAIT 8 - -/* Target driver's pre_exec() is going to be called */ -#define SCST_CMD_STATE_PRE_EXEC 9 - -/* CDB is going to be sent to SCSI mid-level for execution */ -#define SCST_CMD_STATE_SEND_TO_MIDLEV 10 - -/* Waiting for CDB's execution finish */ -#define SCST_CMD_STATE_EXECUTING 11 - -/* Dev handler's dev_done() is going to be called */ -#define SCST_CMD_STATE_DEV_DONE 12 - -/* Target driver's xmit_response() is going to be called */ -#define SCST_CMD_STATE_XMIT_RESP 13 - -/* Waiting for response's transmission finish */ -#define SCST_CMD_STATE_XMIT_WAIT 14 - -/* The cmd finished */ -#define SCST_CMD_STATE_FINISHED 15 - -/************************************************************* - ** Can be retuned instead of cmd's state by dev handlers' - ** functions, if the command's state should be set by default - *************************************************************/ -#define SCST_CMD_STATE_DEFAULT 0 - -/************************************************************* - ** Can be retuned instead of cmd's state by dev handlers' - ** functions, if it is impossible to complete requested - ** task in atomic context. The cmd will be restarted in thread - ** context. - *************************************************************/ -#define SCST_CMD_STATE_NEED_THREAD_CTX 100 - -/************************************************************* - ** Can be retuned instead of cmd's state by dev handlers' - ** parse function, if the cmd processing should be stopped - ** for now. The cmd will be restarted by dev handlers itself. - *************************************************************/ -#define SCST_CMD_STATE_STOP 101 - -/************************************************************* - ** States of mgmt command processing state machine - *************************************************************/ - -/* LUN translation (mcmd->tgt_dev assignment) */ -#define SCST_MGMT_CMD_STATE_INIT 1 - -/* Mgmt cmd is ready for processing */ -#define SCST_MGMT_CMD_STATE_READY 2 - -/* Mgmt cmd is being executing */ -#define SCST_MGMT_CMD_STATE_EXECUTING 3 - -/* Target driver's task_mgmt_fn_done() is going to be called */ -#define SCST_MGMT_CMD_STATE_DONE 4 - -/* The mcmd finished */ -#define SCST_MGMT_CMD_STATE_FINISHED 5 - -/************************************************************* - ** Constants for "atomic" parameter of SCST's functions - *************************************************************/ -#define SCST_NON_ATOMIC 0 -#define SCST_ATOMIC 1 - -/************************************************************* - ** Values for pref_context parameter of scst_cmd_init_done() and - ** scst_rx_data() - *************************************************************/ - -/* - * Direct cmd's processing (i.e. regular function calls in the current - * context), sleeping is allowed, no restrictions - */ -#define SCST_CONTEXT_DIRECT 0 - -/* - * Direct cmd's processing (i.e. regular function calls in the current - * context) sleeping is not allowed - */ -#define SCST_CONTEXT_DIRECT_ATOMIC 1 - -/* Tasklet or thread context required for cmd's processing */ -#define SCST_CONTEXT_TASKLET 2 - -/* Thread context required for cmd's processing */ -#define SCST_CONTEXT_THREAD 3 - -/************************************************************* - ** Values for status parameter of scst_rx_data() - *************************************************************/ - -/* Success */ -#define SCST_RX_STATUS_SUCCESS 0 - -/* - * Data receiving finished with error, so set the sense and - * finish the command, including xmit_response() call - */ -#define SCST_RX_STATUS_ERROR 1 - -/* - * Data receiving finished with error and the sense is set, - * so finish the command, including xmit_response() call - */ -#define SCST_RX_STATUS_ERROR_SENSE_SET 2 - -/* - * Data receiving finished with fatal error, so finish the command, - * but don't call xmit_response() - */ -#define SCST_RX_STATUS_ERROR_FATAL 3 - -/************************************************************* - ** Values for status parameter of scst_restart_cmd() - *************************************************************/ - -/* Success */ -#define SCST_PREPROCESS_STATUS_SUCCESS 0 - -/* - * Command's processing finished with error, so set the sense and - * finish the command, including xmit_response() call - */ -#define SCST_PREPROCESS_STATUS_ERROR 1 - -/* - * Command's processing finished with error and the sense is set, - * so finish the command, including xmit_response() call - */ -#define SCST_PREPROCESS_STATUS_ERROR_SENSE_SET 2 - -/* - * Command's processing finished with fatal error, so finish the command, - * but don't call xmit_response() - */ -#define SCST_PREPROCESS_STATUS_ERROR_FATAL 3 - -/************************************************************* - ** Allowed return codes for xmit_response(), rdy_to_xfer(), - ** report_aen() - *************************************************************/ - -/* Success */ -#define SCST_TGT_RES_SUCCESS 0 - -/* Internal device queue is full, retry again later */ -#define SCST_TGT_RES_QUEUE_FULL -1 - -/* - * It is impossible to complete requested task in atomic context. - * The cmd will be restarted in thread context. - */ -#define SCST_TGT_RES_NEED_THREAD_CTX -2 - -/* - * Fatal error, if returned by xmit_response() the cmd will - * be destroyed, if by any other function, xmit_response() - * will be called with HARDWARE ERROR sense data - */ -#define SCST_TGT_RES_FATAL_ERROR -3 - -/************************************************************* - ** Allowed return codes for dev handler's exec() - *************************************************************/ - -/* The cmd is done, go to other ones */ -#define SCST_EXEC_COMPLETED 0 - -/* The cmd should be sent to SCSI mid-level */ -#define SCST_EXEC_NOT_COMPLETED 1 - -/* - * Thread context is required to execute the command. - * Exec() will be called again in the thread context. - */ -#define SCST_EXEC_NEED_THREAD 2 - -/************************************************************* - ** Default timeout for cmd's CDB execution - ** by SCSI mid-level (cmd's "timeout" field). - *************************************************************/ -#define SCST_DEFAULT_TIMEOUT (30*HZ) - -/************************************************************* - ** Flags of cmd->tgt_resp_flags - *************************************************************/ - -/* - * Set if cmd is finished and there is status/sense to be sent. - * The status should be not sent (i.e. the flag not set) if the - * possibility to perform a command in "chunks" (i.e. with multiple - * xmit_response()/rdy_to_xfer()) is used (not implemented and, - * probably, will never be). - */ -#define SCST_TSC_FLAG_STATUS 0x2 - -/************************************************************* - ** Additional return code for dev handler's task_mgmt_fn() - *************************************************************/ - -/* Regular standard actions for the command should be done */ -#define SCST_DEV_TM_NOT_COMPLETED 1 - -/************************************************************* - ** Session initialization phases - *************************************************************/ - -/* Set if session is being initialized */ -#define SCST_SESS_IPH_INITING 0 - -/* Set if the session is successfully initialized */ -#define SCST_SESS_IPH_SUCCESS 1 - -/* Set if the session initialization failed */ -#define SCST_SESS_IPH_FAILED 2 - -/* Set if session is initialized and ready */ -#define SCST_SESS_IPH_READY 3 - -/************************************************************* - ** Session shutdown phases - *************************************************************/ - -/* Set if session is initialized and ready */ -#define SCST_SESS_SPH_READY 0 - -/* Set if session is on calling pre_unreg_sess() phase */ -#define SCST_SESS_SPH_PRE_UNREG 1 - -/* Set if session is shutting down */ -#define SCST_SESS_SPH_SHUTDOWN 2 - -/************************************************************* - ** Cmd's async (atomic) flags - *************************************************************/ - -/* Set if the cmd is aborted and ABORTED sense will be sent as the result */ -#define SCST_CMD_ABORTED 0 - -/* Set if the cmd is aborted by other initiator */ -#define SCST_CMD_ABORTED_OTHER 1 - -/* Set if no response should be sent to the target about this cmd */ -#define SCST_CMD_NO_RESP 2 - -/* - * Set if the cmd is being executed. Needed to guarantee that - * "no further responses from the task are sent to - * the SCSI initiator port" after response from the TM function is - * sent (SAM) as well as correct ABORT TASK status code - */ -#define SCST_CMD_EXECUTING 3 - -/* - * Set if the cmd status/data are being xmitted. The purpose is the - * same as for SCST_CMD_EXECUTING - */ -#define SCST_CMD_XMITTING 4 - -/* Set if the cmd is dead and can be destroyed at any time */ -#define SCST_CMD_CAN_BE_DESTROYED 5 - -/************************************************************* - ** Tgt_dev's flags (tgt_dev_flags) - *************************************************************/ - -/* Set if tgt_dev has Unit Attention sense */ -#define SCST_TGT_DEV_UA_PENDING 0 - -/* Set if tgt_dev is RESERVED by another session */ -#define SCST_TGT_DEV_RESERVED 1 - -/* Set if the corresponding context is atomic */ -#define SCST_TGT_DEV_AFTER_INIT_WR_ATOMIC 5 -#define SCST_TGT_DEV_AFTER_INIT_OTH_ATOMIC 6 -#define SCST_TGT_DEV_AFTER_RESTART_WR_ATOMIC 7 -#define SCST_TGT_DEV_AFTER_RESTART_OTH_ATOMIC 8 -#define SCST_TGT_DEV_AFTER_RX_DATA_ATOMIC 9 -#define SCST_TGT_DEV_AFTER_EXEC_ATOMIC 10 - -#ifdef DEBUG_TM -#define SCST_TGT_DEV_UNDER_TM_DBG 20 -#endif - -/************************************************************* - ** Name of the entry in /proc - *************************************************************/ -#define SCST_PROC_ENTRY_NAME "scsi_tgt" - -/************************************************************* - ** Kernel cache creation helper - *************************************************************/ -#ifndef KMEM_CACHE -#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\ - sizeof(struct __struct), __alignof__(struct __struct),\ - (__flags), NULL, NULL) -#endif - -/************************************************************* - * TYPES - *************************************************************/ - -struct scst_tgt; -struct scst_session; -struct scst_cmd; -struct scst_mgmt_cmd; -struct scst_device; -struct scst_tgt_dev; -struct scst_dev_type; -struct scst_info_cdb; -struct scst_acg; -struct scst_acg_dev; -struct scst_acn; - -typedef uint64_t lun_t; - -typedef enum dma_data_direction scst_data_direction; - -/* - * Scsi_Target_Template: defines what functions a target driver will - * have to provide in order to work with the target mid-level. - * MUST HAVEs define functions that are expected to be in order to work. - * OPTIONAL says that there is a choice. - * Also, pay attention to the fact that a command is BLOCKING or NON-BLOCKING. - * NON-BLOCKING means that a function returns immediately and will not wait - * for actual data transfer to finish. Blocking in such command could have - * negative impact on overall system performance. If blocking is necessary, - * it is worth to consider creating dedicated thread(s) in target driver, to - * which the commands would be passed and which would perform blocking - * operations instead of SCST. - * If the function allowed to sleep or not is determined by its last - * argument, which is true, if sleeping is not allowed. In this case, - * if the function requires sleeping, it can return - * SCST_TGT_RES_NEED_THREAD_CTX, and it will be recalled in the thread context, - * where sleeping is allowed. - */ -struct scst_tgt_template -{ - /* public: */ - - /* - * SG tablesize allows to check whether scatter/gather can be used - * or not. - */ - int sg_tablesize; - - /* - * True, if this target adapter uses unchecked DMA onto an ISA bus. - */ - unsigned unchecked_isa_dma:1; - - /* - * True, if this target adapter can benefit from using SG-vector - * clustering (i.e. smaller number of segments). - */ - unsigned use_clustering:1; - - /* - * True, if this target adapter doesn't support SG-vector clustering - */ - unsigned no_clustering:1; - - /* - * True, if corresponding function supports execution in - * the atomic (non-sleeping) context - */ - unsigned xmit_response_atomic:1; - unsigned rdy_to_xfer_atomic:1; - unsigned preprocessing_done_atomic:1; - - /* True, if the template doesn't need the entry in /proc */ - unsigned no_proc_entry:1; - - /* - * This function is equivalent to the SCSI - * queuecommand. The target should transmit the response - * buffer and the status in the scst_cmd struct. - * The expectation is that this executing this command is NON-BLOCKING. - * - * After the response is actually transmitted, the target - * should call the scst_tgt_cmd_done() function of the - * mid-level, which will allow it to free up the command. - * Returns one of the SCST_TGT_RES_* constants. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * MUST HAVE - */ - int (*xmit_response) (struct scst_cmd *cmd); - - /* - * This function informs the driver that data - * buffer corresponding to the said command have now been - * allocated and it is OK to receive data for this command. - * This function is necessary because a SCSI target does not - * have any control over the commands it receives. Most lower - * level protocols have a corresponding function which informs - * the initiator that buffers have been allocated e.g., XFER_ - * RDY in Fibre Channel. After the data is actually received - * the low-level driver needs to call scst_rx_data() in order to - * continue processing this command. - * Returns one of the SCST_TGT_RES_* constants. - * This command is expected to be NON-BLOCKING. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * OPTIONAL - */ - int (*rdy_to_xfer) (struct scst_cmd *cmd); - - /* - * Called to notify the driver that the command is about to be freed. - * Necessary, because for aborted commands xmit_response() could not - * be called. Could be called on IRQ context. - * - * OPTIONAL - */ - void (*on_free_cmd) (struct scst_cmd *cmd); - - /* - * This function allows target driver to handle data buffer - * allocations on its own. - * - * Target driver doesn't have to always allocate buffer in this - * function, but if it decide to do it, it must check that - * scst_cmd_get_data_buff_alloced() returns 0, otherwise to avoid - * double buffer allocation and memory leaks alloc_data_buf() shall - * fail. - * - * Shall return 0 in case of success or < 0 (preferrably -ENOMEM) - * in case of error, or > 0 if the regular SCST allocation should be - * done. In case of returning successfully, scst_cmd->data_buf_alloced - * will be set by SCST. - * - * If allocation in atomic context - cf. scst_cmd_atomic() - is not - * desired or fails and consequently < 0 is returned, this function - * will be re-called in thread context. - * - * Please note that the driver will have to handle itself all relevant - * details such as scatterlist setup, highmem, freeing the allocated - * memory, etc. - * - * OPTIONAL. - */ - int (*alloc_data_buf) (struct scst_cmd *cmd); - - /* - * This function informs the driver that data - * buffer corresponding to the said command have now been - * allocated and other preprocessing tasks have been done. - * A target driver could need to do some actions at this stage. - * After the target driver done the needed actions, it shall call - * scst_restart_cmd() in order to continue processing this command. - * - * Called only if the cmd is queued using scst_cmd_init_stage1_done() - * instead of scst_cmd_init_done(). - * - * Returns void, the result is expected to be returned using - * scst_restart_cmd(). - * - * This command is expected to be NON-BLOCKING. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * OPTIONAL. - */ - void (*preprocessing_done) (struct scst_cmd *cmd); - - /* - * This function informs the driver that the said command is about - * to be executed. - * - * Returns one of the SCST_PREPROCESS_* constants. - * - * This command is expected to be NON-BLOCKING. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * OPTIONAL - */ - int (*pre_exec) (struct scst_cmd *cmd); - - /* - * This function informs the driver that a - * received task management function has been completed. This - * function is necessary because low-level protocols have some - * means of informing the initiator about the completion of a - * Task Management function. This function being called will - * signify that a Task Management function is completed as far - * as the mid-level is concerned. Any information that must be - * stored about the command is the responsibility of the low- - * level driver. No return value expected. - * This function is expected to be NON-BLOCKING - * - * Called without any locks held from a thread context. - * - * MUST HAVE if the target supports ABORTs - */ - void (*task_mgmt_fn_done) (struct scst_mgmt_cmd *mgmt_cmd); - - /* - * This function should detect the target adapters that - * are present in the system. The function should return a value - * >= 0 to signify the number of detected target adapters. - * A negative value should be returned whenever there is - * an error. - * - * MUST HAVE - */ - int (*detect) (struct scst_tgt_template *tgt_template); - - /* - * This function should free up the resources allocated to the device. - * The function should return 0 to indicate successful release - * or a negative value if there are some issues with the release. - * In the current version the return value is ignored. - * - * MUST HAVE - */ - int (*release) (struct scst_tgt *tgt); - - /* - * This function is used for Asynchronous Event Notification. - * It is the responsibility of the driver to notify any/all - * initiators about the Asynchronous Event reported. - * Returns one of the SCST_TGT_RES_* constants. - * This command is expected to be NON-BLOCKING, but can sleep. - * - * MUST HAVE if low-level protocol supports AEN - * - * ToDo - */ - int (*report_aen) (int mgmt_fn, const uint8_t *lun, int lun_len); - - /* - * Those functions can be used to export the driver's statistics and - * other infos to the world outside the kernel as well as to get some - * management commands from it. - * - * OPTIONAL - */ - int (*read_proc) (struct seq_file *seq, struct scst_tgt *tgt); - int (*write_proc) (char *buffer, char **start, off_t offset, - int length, int *eof, struct scst_tgt *tgt); - - /* - * Name of the template. Must be unique to identify - * the template. MUST HAVE - */ - const char name[50]; - - /* - * Number of additional threads to the pool of dedicated threads. - * Used if xmit_response() or rdy_to_xfer() is blocking. - * It is the target driver's duty to ensure that not more, than that - * number of threads, are blocked in those functions at any time. - */ - int threads_num; - - /* Private, must be inited to 0 by memset() */ - - /* List of targets per template, protected by scst_mutex */ - struct list_head tgt_list; - - /* List entry of global templates list */ - struct list_head scst_template_list_entry; - - /* The pointer to the /proc directory entry */ - struct proc_dir_entry *proc_tgt_root; - - /* Device number in /proc */ - int proc_dev_num; -}; - -struct scst_dev_type -{ - /* - * True, if corresponding function supports execution in - * the atomic (non-sleeping) context - */ - unsigned parse_atomic:1; - unsigned exec_atomic:1; - unsigned dev_done_atomic:1; - - /* Set, if no /proc files should be automatically created by SCST */ - unsigned no_proc:1; - - /* Set if increment expected_sn in cmd->scst_cmd_done() */ - unsigned inc_expected_sn_on_done:1; - - /* - * Called to parse CDB from the cmd and initialize - * cmd->bufflen and cmd->data_direction (both - REQUIRED). - * Returns the command's next state or SCST_CMD_STATE_DEFAULT, - * if the next default state should be used, or - * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic - * context, but requires sleeping, or SCST_CMD_STATE_STOP if the - * command should not be further processed for now. In the - * SCST_CMD_STATE_NEED_THREAD_CTX case the function - * will be recalled in the thread context, where sleeping is allowed. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * MUST HAVE - */ - int (*parse) (struct scst_cmd *cmd, struct scst_info_cdb *cdb_info); - - /* - * Called to execute CDB. Useful, for instance, to implement - * data caching. The result of CDB execution is reported via - * cmd->scst_cmd_done() callback. - * Returns: - * - SCST_EXEC_COMPLETED - the cmd is done, go to other ones - * - SCST_EXEC_NEED_THREAD - thread context is required to execute - * the command. Exec() will be called again in the thread context. - * - SCST_EXEC_NOT_COMPLETED - the cmd should be sent to SCSI mid-level. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - * - * !! If this function is implemented, scst_check_local_events() shall !! - * !! be called inside it just before the actual command's execution. !! - * - * OPTIONAL, if not set, the commands will be sent directly to SCSI - * device. - */ - int (*exec) (struct scst_cmd *cmd); - - /* - * Called to notify dev handler about the result of cmd execution - * and perform some post processing. Cmd's fields tgt_resp_flags and - * resp_data_len should be set by this function, but SCST offers good - * defaults. - * Returns the command's next state or SCST_CMD_STATE_DEFAULT, - * if the next default state should be used, or - * SCST_CMD_STATE_NEED_THREAD_CTX if the function called in atomic - * context, but requires sleeping. In the last case, the function - * will be recalled in the thread context, where sleeping is allowed. - * - * Pay attention to "atomic" attribute of the cmd, which can be get - * by scst_cmd_atomic(): it is true if the function called in the - * atomic (non-sleeping) context. - */ - int (*dev_done) (struct scst_cmd *cmd); - - /* - * Called to notify dev hander that the command is about to be freed. - * Could be called on IRQ context. - */ - void (*on_free_cmd) (struct scst_cmd *cmd); - - /* - * Called to execute a task management command. - * Returns: - * - SCST_MGMT_STATUS_SUCCESS - the command is done with success, - * no firther actions required - * - The SCST_MGMT_STATUS_* error code if the command is failed and - * no firther actions required - * - SCST_DEV_TM_NOT_COMPLETED - regular standard actions for the command - * should be done - * - * Called without any locks held from a thread context. - */ - int (*task_mgmt_fn) (struct scst_mgmt_cmd *mgmt_cmd, - struct scst_tgt_dev *tgt_dev); - - /* - * Called when new device is attaching to the dev handler - * Returns 0 on success, error code otherwise. - */ - int (*attach) (struct scst_device *dev); - - /* Called when new device is detaching from the dev handler */ - void (*detach) (struct scst_device *dev); - - /* - * Called when new tgt_dev (session) is attaching to the dev handler. - * Returns 0 on success, error code otherwise. - */ - int (*attach_tgt) (struct scst_tgt_dev *tgt_dev); - - /* - * Called when a session, corresponding to a tgt_dev, is about to be - * unregistered and the tgt_dev - detached. Supposed to be used to - * clean out "stalled" commands, which otherwise could prevent SCST - * from entering into the suspended activity state and, so, - * unregistering the device. - */ - void (*pre_unreg_sess) (struct scst_tgt_dev *tgt_dev); - - /* Called when tgt_dev (session) is detaching from the dev handler */ - void (*detach_tgt) (struct scst_tgt_dev *tgt_dev); - - /* - * Those functions can be used to export the handler's statistics and - * other infos to the world outside the kernel as well as to get some - * management commands from it. - * - * OPTIONAL - */ - int (*read_proc) (struct seq_file *seq, struct scst_dev_type *dev_type); - int (*write_proc) (char *buffer, char **start, off_t offset, - int length, int *eof, struct scst_dev_type *dev_type); - - /* Name of the dev handler. Must be unique. MUST HAVE */ - char name[15]; - - /* SCSI type of the supported device. MUST HAVE */ - int type; - - /* - * Number of dedicated threads. If 0 - no dedicated threads will - * be created, if <0 - creation of dedicated threads is prohibited. - */ - int threads_num; - - struct module *module; - - /* private: */ - - /* list entry in scst_dev_type_list */ - struct list_head dev_type_list_entry; - - /* The pointer to the /proc directory entry */ - struct proc_dir_entry *proc_dev_type_root; -}; - -struct scst_tgt -{ - /* List of remote sessions per target, protected by scst_mutex */ - struct list_head sess_list; - - /* List entry of targets per template (tgts_list) */ - struct list_head tgt_list_entry; - - struct scst_tgt_template *tgtt; /* corresponding target template */ - - /* Used to wait until session finished to unregister */ - wait_queue_head_t unreg_waitQ; - - /* Device number in /proc */ - int proc_num; - - /* - * The following fields used to store and retry cmds if - * target's internal queue is full, so the target is unable to accept - * the cmd returning QUEUE FULL - */ - atomic_t finished_cmds; - int retry_cmds; /* protected by tgt_lock */ - spinlock_t tgt_lock; - struct list_head retry_cmd_list; /* protected by tgt_lock */ - struct timer_list retry_timer; - int retry_timer_active; - - /* - * Maximum SG table size. Needed here, since different cards on the - * same target template can have different SG table limitations. - */ - int sg_tablesize; - - /* Used for storage of target driver private stuff */ - void *tgt_priv; - - /* Name on the default security group ("Default_target_name") */ - char *default_group_name; -}; - -/* Hash size and hash fn for hash based lun translation */ -#define TGT_DEV_HASH_SHIFT 5 -#define TGT_DEV_HASH_SIZE (1<<TGT_DEV_HASH_SHIFT) -#define HASH_VAL(_val) (_val & (TGT_DEV_HASH_SIZE - 1)) - -struct scst_session -{ - /* - * Initialization phase, one of SCST_SESS_IPH_* constants, protected by - * sess_list_lock - */ - int init_phase; - - atomic_t refcnt; /* get/put counter */ - - /**************************************************************/ - - /* Alive commands for this session. ToDo: make it part of the common IO flow control */ - atomic_t sess_cmd_count; - - spinlock_t sess_list_lock; /* protects search_cmd_list, etc */ - - /* - * List of cmds in this session. Used to find a cmd in the - * session. Protected by sess_list_lock. - */ - struct list_head search_cmd_list; - - /* - * Hash list of tgt_dev's for this session, protected by scst_mutex - * and suspended activity - */ - struct list_head sess_tgt_dev_list_hash[TGT_DEV_HASH_SIZE]; - - /* Access control for this session and list entry there */ - struct scst_acg *acg; - - /* List entry for the sessions list inside ACG */ - struct list_head acg_sess_list_entry; - - struct scst_tgt *tgt; /* corresponding target */ - - /* Used for storage of target driver private stuff */ - void *tgt_priv; - - /* Name of attached initiator */ - const char *initiator_name; - - /* List entry of sessions per target */ - struct list_head sess_list_entry; - - /* List entry for the list that keeps session, waiting for the init */ - struct list_head sess_init_list_entry; - - /* List entry for the list that keeps session, waiting for the shutdown */ - struct list_head sess_shut_list_entry; - - /* - * Lists of deffered during session initialization commands. - * Protected by sess_list_lock. - */ - struct list_head init_deferred_cmd_list; - struct list_head init_deferred_mcmd_list; - - /* - * Shutdown phase, one of SCST_SESS_SPH_* constants, unprotected. - * Async. relating to init_phase, must be a separate variable, because - * session could be unregistered before async. registration is finished. - */ - unsigned long shut_phase; - - /* Used if scst_unregister_session() called in wait mode */ - struct completion *shutdown_compl; - - /* - * Functions and data for user callbacks from scst_register_session() - * and scst_unregister_session() - */ - void *reg_sess_data; - void (*init_result_fn) (struct scst_session *sess, void *data, - int result); - void (*unreg_done_fn) (struct scst_session *sess); -}; - -struct scst_cmd_lists -{ - spinlock_t cmd_list_lock; - struct list_head active_cmd_list; - wait_queue_head_t cmd_list_waitQ; - struct list_head lists_list_entry; -}; - -struct scst_cmd -{ - /* List entry for below *_cmd_lists */ - struct list_head cmd_list_entry; - - /* Pointer to lists of commands with the lock */ - struct scst_cmd_lists *cmd_lists; - - atomic_t cmd_ref; - - struct scst_session *sess; /* corresponding session */ - - /* Cmd state, one of SCST_CMD_STATE_* constants */ - int state; - - /************************************************************* - ** Cmd's flags - *************************************************************/ - /* - * Set if expected_sn was incremented, i.e. cmd was sent to - * SCSI mid-level for execution - */ - unsigned int sent_to_midlev:1; - - /* Set if the cmd's action is completed */ - unsigned int completed:1; - - /* Set if we should ignore Unit Attention in scst_check_sense() */ - unsigned int ua_ignore:1; - - /* Set if cmd is being processed in atomic context */ - unsigned int atomic:1; - - /* Set if cmd is internally generated */ - unsigned int internal:1; - - /* Set if cmd is being retried */ - unsigned int retry:1; - - /* Set if the device was blocked by scst_inc_on_dev_cmd() (for debug) */ - unsigned int inc_blocking:1; - - /* Set if the device should be unblocked after cmd's finish */ - unsigned int needs_unblocking:1; - - /* Set if scst_dec_on_dev_cmd() call is needed on the cmd's finish */ - unsigned int dec_on_dev_needed:1; - - /* - * Set if the target driver wants to alloc data buffers on its own. - * In this case alloc_data_buf() must be provided in the target driver - * template. - */ - unsigned int data_buf_tgt_alloc:1; - - /* - * Set by SCST if the custom data buffer allocation by the target driver - * succeeded. - */ - unsigned int data_buf_alloced:1; - - /* Set if the target driver called scst_set_expected() */ - unsigned int expected_values_set:1; - - /* - * Set if the cmd was delayed by task management debugging code. - * Used only if DEBUG_TM is on. - */ - unsigned int tm_dbg_delayed:1; - - /* - * Set if the cmd must be ignored by task management debugging code. - * Used only if DEBUG_TM is on. - */ - unsigned int tm_dbg_immut:1; - - /* - * Set if the SG buffer was modified by scst_set_resp_data_len() - */ - unsigned int sg_buff_modified:1; - - /* - * Set if the cmd's memory requirements are checked and found - * acceptable - */ - unsigned int mem_checked:1; - - /* - * Set if scst_cmd_init_stage1_done() called and the target - * want that preprocessing_done() will be called - */ - unsigned int preprocessing_only:1; - - /* Set if scst_cmd_set_sn() was called */ - unsigned int sn_set:1; - - /* - * Set if scst_cmd_init_stage1_done() called and the target wants - * that the SN for the cmd won't be assigned until scst_restart_cmd() - */ - unsigned int set_sn_on_restart_cmd:1; - - /* Set if the cmd's must not use sgv cache for data buffer */ - unsigned int no_sgv:1; - - /* - * Set if target driver may need to call dma_sync_sg() or similar - * function before transferring cmd' data to the target device - * via DMA. - */ - unsigned int may_need_dma_sync:1; - - /* Set if the cmd was done or aborted out of its SN */ - unsigned int out_of_sn:1; - - /* Set if the cmd is deferred HEAD OF QUEUE */ - unsigned int hq_deferred:1; - - /* Set if the internal parse should be skipped */ - unsigned int skip_parse:1; - - /* - * Set if increment expected_sn in cmd->scst_cmd_done() (to save - * extra dereferences) - */ - unsigned int inc_expected_sn_on_done:1; - - /* Set if tgt_sn field is valid */ - unsigned int tgt_sn_set:1; - - /**************************************************************/ - - unsigned long cmd_flags; /* cmd's async flags */ - - struct scst_tgt_template *tgtt; /* to save extra dereferences */ - struct scst_tgt *tgt; /* to save extra dereferences */ - struct scst_device *dev; /* to save extra dereferences */ - - lun_t lun; /* LUN for this cmd */ - - struct scst_tgt_dev *tgt_dev; /* corresponding device for this cmd */ - - /* The corresponding mgmt cmd, if any, protected by sess_list_lock */ - struct scst_mgmt_cmd *mgmt_cmnd; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - struct scsi_request *scsi_req; /* SCSI request */ -#endif - - /* List entry for tgt_dev's SN related lists */ - struct list_head sn_cmd_list_entry; - - /* Cmd's serial number, used to execute cmd's in order of arrival */ - unsigned long sn; - - /* The corresponding sn_slot in tgt_dev->sn_slots */ - atomic_t *sn_slot; - - /* List entry for session's search_cmd_list */ - struct list_head search_cmd_list_entry; - - /* - * Used to found the cmd by scst_find_cmd_by_tag(). Set by the - * target driver on the cmd's initialization time - */ - uint64_t tag; - - uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */ - - /* CDB and its len */ - uint8_t cdb[SCST_MAX_CDB_SIZE]; - int cdb_len; - - enum scst_cmd_queue_type queue_type; - - int timeout; /* CDB execution timeout */ - int retries; /* Amount of retries that will be done by SCSI mid-level */ - - /* SCSI data direction, one of SCST_DATA_* constants */ - scst_data_direction data_direction; - - /* Remote initiator supplied values, if any */ - scst_data_direction expected_data_direction; - int expected_transfer_len; - - /* - * Cmd data length. Could be different from bufflen for commands like - * VERIFY, which transfer different amount of data (if any), than - * processed. - */ - int data_len; - - /* Completition routine */ - void (*scst_cmd_done) (struct scst_cmd *cmd, int next_state); - - struct sgv_pool_obj *sgv; /* sgv object */ - - int bufflen; /* cmd buffer length */ - struct scatterlist *sg; /* cmd data buffer SG vector */ - int sg_cnt; /* SG segments count */ - - /* scst_get_sg_buf_[first,next]() support */ - int get_sg_buf_entry_num; - - /* - * The following two fields should be corrected by the dev_done(), - * if necessary - */ - int tgt_resp_flags; /* response flags (SCST_TSC_FLAG_* constants) */ - - /* - * Response data length in data buffer. This field must not be set - * directly, use scst_set_resp_data_len() for that - */ - int resp_data_len; - - uint8_t status; /* status byte from target device */ - uint8_t msg_status; /* return status from host adapter itself */ - uint8_t host_status; /* set by low-level driver to indicate status */ - uint8_t driver_status; /* set by mid-level */ - - /* Used for storage of target driver private stuff */ - void *tgt_priv; - - /* Used for storage of dev handler private stuff */ - void *dh_priv; - - /* - * Used to restore the SG vector if it was modified by - * scst_set_resp_data_len() - */ - int orig_sg_cnt, orig_sg_entry, orig_entry_len; - - uint8_t sense_buffer[SCST_SENSE_BUFFERSIZE]; /* sense buffer */ - - /* List entry for dev's blocked_cmd_list */ - struct list_head blocked_cmd_list_entry; - - struct scst_cmd *orig_cmd; /* Used to issue REQUEST SENSE */ -}; - -struct scst_rx_mgmt_params -{ - int fn; - uint64_t tag; - const uint8_t *lun; - int lun_len; - uint32_t cmd_sn; - int atomic; - void *tgt_priv; - unsigned char tag_set; - unsigned char lun_set; - unsigned char cmd_sn_set; -}; - -struct scst_mgmt_cmd -{ - /* List entry for *_mgmt_cmd_list */ - struct list_head mgmt_cmd_list_entry; - - struct scst_session *sess; - - /* Mgmt cmd state, one of SCST_MGMT_CMD_STATE_* constants */ - int state; - - int fn; - - unsigned int completed:1; /* set, if the mcmd is completed */ - unsigned int active:1; /* set, if the mcmd is active */ - /* Set if device(s) should be unblocked after mcmd's finish */ - unsigned int needs_unblocking:1; - unsigned int lun_set:1; /* set, if lun field is valid */ - unsigned int cmd_sn_set:1; /* set, if cmd_sn field is valid */ - - /* - * Number of commands to complete before sending response, - * protected by scst_mcmd_lock - */ - int cmd_wait_count; - - /* Number of completed commands, protected by scst_mcmd_lock */ - int completed_cmd_count; - - lun_t lun; /* LUN for this mgmt cmd */ - /* or (and for iSCSI) */ - uint64_t tag; /* tag of the corresponding cmd */ - - uint32_t cmd_sn; /* affected command's highest SN */ - - /* corresponding cmd (to be aborted, found by tag) */ - struct scst_cmd *cmd_to_abort; - - /* corresponding device for this mgmt cmd (found by lun) */ - struct scst_tgt_dev *mcmd_tgt_dev; - - /* completition status, one of the SCST_MGMT_STATUS_* constants */ - int status; - - /* Used for storage of target driver private stuff */ - void *tgt_priv; -}; - -struct scst_device -{ - struct scst_dev_type *handler; /* corresponding dev handler */ - - /* Pointer to lists of commands with the lock */ - struct scst_cmd_lists *p_cmd_lists; - - /* Lists of commands with lock, if dedicated threads are used */ - struct scst_cmd_lists cmd_lists; - - /* How many cmds alive on this dev */ - atomic_t dev_cmd_count; - - unsigned short type; /* SCSI type of the device */ - - /************************************************************* - ** Dev's flags. Updates serialized by dev_lock or suspended - ** activity - *************************************************************/ - - /* Set if dev is RESERVED */ - unsigned short dev_reserved:1; - - /* Set if dev accepts only one command at time */ - unsigned short dev_serialized:1; - - /* Set if double reset UA is possible */ - unsigned short dev_double_ua_possible:1; - - /* Set if reset UA sent (to avoid double reset UAs) */ - unsigned short dev_reset_ua_sent:1; - - /**************************************************************/ - - spinlock_t dev_lock; /* device lock */ - - /* - * How many times device was blocked for new cmds execution. - * Protected by dev_lock - */ - int block_count; - - /* - * How many there are "on_dev" commands, i.e. ones those are being - * executed by the underlying SCSI/virtual device. - */ - atomic_t on_dev_count; - - struct list_head blocked_cmd_list; /* protected by dev_lock */ - - /* Used for storage of dev handler private stuff */ - void *dh_priv; - - /* Used to translate SCSI's cmd to SCST's cmd */ - struct gendisk *rq_disk; - - /* Corresponding real SCSI device, could be NULL for virtual devices */ - struct scsi_device *scsi_dev; - - /* Used to wait for requested amount of "on_dev" commands */ - wait_queue_head_t on_dev_waitQ; - - /* A list entry used during RESETs, protected by scst_mutex */ - struct list_head reset_dev_list_entry; - - /* Virtual device internal ID */ - int virt_id; - - /* Pointer to virtual device name, for convenience only */ - const char *virt_name; - - /* List entry in global devices list */ - struct list_head dev_list_entry; - - /* - * List of tgt_dev's, one per session, protected by scst_mutex and - * suspended activity - */ - struct list_head dev_tgt_dev_list; - - /* List of acg_dev's, one per acg, protected by scst_mutex */ - struct list_head dev_acg_dev_list; - - /* List of dedicated threads, protected by scst_mutex */ - struct list_head threads_list; - - /* Device number */ - int dev_num; -}; - -/* - * Used to store threads local tgt_dev specific data - */ -struct scst_thr_data_hdr -{ - /* List entry in tgt_dev->thr_data_list */ - struct list_head thr_data_list_entry; - pid_t pid; /* PID of the owner thread */ - atomic_t ref; - /* Function that will be called on the tgt_dev destruction */ - void (*free_fn) (struct scst_thr_data_hdr *data); -}; - -/* - * Used to store per-session specific device information - */ -struct scst_tgt_dev -{ - /* List entry in sess->sess_tgt_dev_list_hash */ - struct list_head sess_tgt_dev_list_entry; - - struct scst_device *dev; /* to save extra dereferences */ - lun_t lun; /* to save extra dereferences */ - - /* How many cmds alive on this dev in this session */ - atomic_t tgt_dev_cmd_count; - - int gfp_mask; - struct sgv_pool *pool; - int max_sg_cnt; - - unsigned long tgt_dev_flags; /* tgt_dev's async flags */ - - /* - * Used to execute cmd's in order of arrival, honoring SCSI task - * attributes. - * - * Protected by sn_lock, except expected_sn, which is protected by - * itself. Curr_sn must have the same size as expected_sn to - * overflow simultaneously. - */ - int def_cmd_count; - spinlock_t sn_lock; - unsigned long expected_sn; - unsigned long curr_sn; - int hq_cmd_count; - struct list_head deferred_cmd_list; - struct list_head skipped_sn_list; - - /* - * Set if the prev cmd was ORDERED. Size must allow unprotected - * modifications - */ - unsigned long prev_cmd_ordered; - - int num_free_sn_slots; - atomic_t *cur_sn_slot; - atomic_t sn_slots[10]; - - /* Used for storage of dev handler private stuff */ - void *dh_priv; - - /* List of scst_thr_data_hdr and lock */ - spinlock_t thr_data_lock; - struct list_head thr_data_list; - - spinlock_t tgt_dev_lock; /* per-session device lock */ - - /* List of UA's for this device, protected by tgt_dev_lock */ - struct list_head UA_list; - - struct scst_session *sess; /* corresponding session */ - struct scst_acg_dev *acg_dev; /* corresponding acg_dev */ - - /* list entry in dev->dev_tgt_dev_list */ - struct list_head dev_tgt_dev_list_entry; - - /* internal tmp list entry */ - struct list_head extra_tgt_dev_list_entry; - - -}; - -/* - * Used to store ACG-specific device information, like LUN - */ -struct scst_acg_dev -{ - struct scst_device *dev; /* corresponding device */ - lun_t lun; /* device's LUN in this acg */ - unsigned int rd_only_flag:1; /* if != 0, then read only */ - struct scst_acg *acg; /* parent acg */ - - /* list entry in dev->dev_acg_dev_list */ - struct list_head dev_acg_dev_list_entry; - - /* list entry in acg->acg_dev_list */ - struct list_head acg_dev_list_entry; -}; - -/* - * ACG - access control group. Used to store group related - * control information. - */ -struct scst_acg -{ - /* List of acg_dev's in this acg, protected by scst_mutex */ - struct list_head acg_dev_list; - - /* List of attached sessions, protected by scst_mutex */ - struct list_head acg_sess_list; - - /* List of attached acn's, protected by scst_mutex */ - struct list_head acn_list; - - /* List entry in scst_acg_list */ - struct list_head scst_acg_list_entry; - - /* Name of this acg */ - const char *acg_name; - - /* The pointer to the /proc directory entry */ - struct proc_dir_entry *acg_proc_root; -}; - -/* - * ACN - access control name. Used to store names, by which - * incoming sessions will be assigned to appropriate ACG. - */ -struct scst_acn -{ - /* Initiator's name */ - const char *name; - /* List entry in acg->acn_list */ - struct list_head acn_list_entry; -}; - -/* - * Used to store per-session UNIT ATTENTIONs - */ -struct scst_tgt_dev_UA -{ - /* List entry in tgt_dev->UA_list */ - struct list_head UA_list_entry; - /* Unit Attention sense */ - uint8_t UA_sense_buffer[SCST_SENSE_BUFFERSIZE]; -}; - -enum scst_cdb_flags -{ - SCST_TRANSFER_LEN_TYPE_FIXED = 0x01, /* must be equviv 1 (FIXED_BIT in cdb) */ - SCST_SMALL_TIMEOUT = 0x02, - SCST_LONG_TIMEOUT = 0x04, - SCST_UNKNOWN_LENGTH = 0x08, - SCST_INFO_INVALID = 0x10, -}; - -struct scst_info_cdb -{ - enum scst_cdb_flags flags; - scst_data_direction direction; - unsigned int transfer_len; - unsigned short cdb_len; - const char *op_name; -}; - -#ifndef smp_mb__after_set_bit -/* There is no smp_mb__after_set_bit() in the kernel */ -#define smp_mb__after_set_bit() smp_mb(); -#endif - -/* - * Registers target template - * Returns 0 on success or appropriate error code otherwise - */ -int scst_register_target_template(struct scst_tgt_template *vtt); - -/* - * Unregisters target template - */ -void scst_unregister_target_template(struct scst_tgt_template *vtt); - -/* - * Registers and returns target adapter - * Returns new target structure on success or NULL otherwise. - * - * If parameter "target_name" isn't NULL, then security group with name - * "Default_##target_name", if created, will be used as the default - * instead of "Default" one for all initiators not assigned to any other group. - */ -struct scst_tgt *scst_register(struct scst_tgt_template *vtt, - const char *target_name); - -/* - * Unregisters target adapter - */ -void scst_unregister(struct scst_tgt *tgt); - -/* - * Registers and returns a session - * - * Returns new session on success or NULL otherwise - * - * Parameters: - * tgt - target - * atomic - true, if the function called in the atomic context - * initiator_name - remote initiator's name, any NULL-terminated string, - * e.g. iSCSI name, which used as the key to found appropriate access - * control group. Could be NULL, then "default" group is used. - * The groups are set up via /proc interface. - * data - any target driver supplied data - * result_fn - pointer to the function that will be - * asynchronously called when session initialization finishes. - * Can be NULL. Parameters: - * - sess - session - * - data - target driver supplied to scst_register_session() data - * - result - session initialization result, 0 on success or - * appropriate error code otherwise - * - * Note: A session creation and initialization is a complex task, - * which requires sleeping state, so it can't be fully done - * in interrupt context. Therefore the "bottom half" of it, if - * scst_register_session() is called from atomic context, will be - * done in SCST thread context. In this case scst_register_session() - * will return not completely initialized session, but the target - * driver can supply commands to this session via scst_rx_cmd(). - * Those commands processing will be delayed inside SCST until - * the session initialization is finished, then their processing - * will be restarted. The target driver will be notified about - * finish of the session initialization by function result_fn(). - * On success the target driver could do nothing, but if the - * initialization fails, the target driver must ensure that - * no more new commands being sent or will be sent to SCST after - * result_fn() returns. All already sent to SCST commands for - * failed session will be returned in xmit_response() with BUSY status. - * In case of failure the driver shall call scst_unregister_session() - * inside result_fn(), it will NOT be called automatically. - */ -struct scst_session *scst_register_session(struct scst_tgt *tgt, int atomic, - const char *initiator_name, void *data, - void (*result_fn) (struct scst_session *sess, void *data, int result)); - -/* - * Unregisters a session. - * Parameters: - * sess - session to be unregistered - * wait - if true, instructs to wait until all commands, which - * currently is being executed and belonged to the session, finished. - * Otherwise, target driver should be prepared to receive - * xmit_response() for the session's command after - * scst_unregister_session() returns. - * unreg_done_fn - pointer to the function that will be - * asynchronously called when the last session's command finishes and - * the session is about to be completely freed. Can be NULL. - * Parameter: - * - sess - session - * - * Note: All outstanding commands will be finished regularly. After - * scst_unregister_session() returned no new commands must be sent to - * SCST via scst_rx_cmd(). Also, the caller must ensure that no - * scst_rx_cmd() or scst_rx_mgmt_fn_*() is called in paralell with - * scst_unregister_session(). - * Can be called before result_fn() of scst_register_session() called, - * i.e. during the session registration/initialization. - */ -void scst_unregister_session(struct scst_session *sess, int wait, - void (*unreg_done_fn) (struct scst_session *sess)); - -/* - * Registers dev handler driver - * Returns 0 on success or appropriate error code otherwise - */ -int scst_register_dev_driver(struct scst_dev_type *dev_type); - -/* - * Unregisters dev handler driver - */ -void scst_unregister_dev_driver(struct scst_dev_type *dev_type); - -/* - * Registers dev handler driver for virtual devices (eg VDISK) - * Returns 0 on success or appropriate error code otherwise - */ -int scst_register_virtual_dev_driver(struct scst_dev_type *dev_type); - -/* - * Unregisters dev handler driver for virtual devices - */ -void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type); - -/* - * Creates and sends new command to SCST. - * Must not be called in parallel with scst_unregister_session() for the - * same sess. Returns the command on success or NULL otherwise - */ -struct scst_cmd *scst_rx_cmd(struct scst_session *sess, - const uint8_t *lun, int lun_len, - const uint8_t *cdb, int cdb_len, int atomic); - -/* - * Notifies SCST that the driver finished its part of the command - * initialization, and the command is ready for execution. - * The second argument sets preferred command execition context. - * See SCST_CONTEXT_* constants for details. - * - * !!IMPORTANT!! - * - * If cmd->set_sn_on_restart_cmd not set, this function, as well as - * scst_cmd_init_stage1_done() and scst_restart_cmd(), must not be - * called simultaneously for the same session (more precisely, - * for the same session/LUN, i.e. tgt_dev), i.e. they must be - * somehow externally serialized. This is needed to have lock free fast path in - * scst_cmd_set_sn(). For majority of targets those functions are naturally - * serialized by the single source of commands. Only iSCSI immediate commands - * with multiple connections per session seems to be an exception. For it, some - * mutex/lock shall be used for the serialization. - */ -void scst_cmd_init_done(struct scst_cmd *cmd, int pref_context); - -/* - * Notifies SCST that the driver finished the first stage of the command - * initialization, and the command is ready for execution, but after - * SCST done the command's preprocessing preprocessing_done() function - * should be called. The second argument sets preferred command execition - * context. See SCST_CONTEXT_* constants for details. - * - * See also scst_cmd_init_done() comment for the serialization requirements. - */ -static inline void scst_cmd_init_stage1_done(struct scst_cmd *cmd, - int pref_context, int set_sn) -{ - cmd->preprocessing_only = 1; - cmd->set_sn_on_restart_cmd = !set_sn; - scst_cmd_init_done(cmd, pref_context); -} - -/* - * Notifies SCST that the driver finished its part of the command's - * preprocessing and it is ready for further processing. - * The second argument sets data receiving completion status - * (see SCST_PREPROCESS_STATUS_* constants for details) - * The third argument sets preferred command execition context - * (see SCST_CONTEXT_* constants for details). - * - * See also scst_cmd_init_done() comment for the serialization requirements. - */ -void scst_restart_cmd(struct scst_cmd *cmd, int status, int pref_context); - -/* - * Notifies SCST that the driver received all the necessary data - * and the command is ready for further processing. - * The second argument sets data receiving completion status - * (see SCST_RX_STATUS_* constants for details) - * The third argument sets preferred command execition context - * (see SCST_CONTEXT_* constants for details) - */ -void scst_rx_data(struct scst_cmd *cmd, int status, int pref_context); - -/* - * Notifies SCST that the driver sent the response and the command - * can be freed now. - */ -void scst_tgt_cmd_done(struct scst_cmd *cmd); - -/* - * Creates new management command sends it for execution. - * Must not be called in parallel with scst_unregister_session() for the - * same sess. Returns 0 for success, error code otherwise. - */ -int scst_rx_mgmt_fn(struct scst_session *sess, - const struct scst_rx_mgmt_params *params); - -/* - * Creates new management command using tag and sends it for execution. - * Can be used for SCST_ABORT_TASK only. - * Must not be called in parallel with scst_unregister_session() for the - * same sess. Returns 0 for success, error code otherwise. - * - * Obsolete in favor of scst_rx_mgmt_fn() - */ -static inline int scst_rx_mgmt_fn_tag(struct scst_session *sess, int fn, - uint64_t tag, int atomic, void *tgt_priv) -{ - struct scst_rx_mgmt_params params; - - BUG_ON(fn != SCST_ABORT_TASK); - - memset(¶ms, 0, sizeof(params)); - params.fn = fn; - params.tag = tag; - params.tag_set = 1; - params.atomic = atomic; - params.tgt_priv = tgt_priv; - return scst_rx_mgmt_fn(sess, ¶ms); -} - -/* - * Creates new management command using LUN and sends it for execution. - * Currently can be used for any fn, except SCST_ABORT_TASK. - * Must not be called in parallel with scst_unregister_session() for the - * same sess. Returns 0 for success, error code otherwise. - * - * Obsolete in favor of scst_rx_mgmt_fn() - */ -static inline int scst_rx_mgmt_fn_lun(struct scst_session *sess, int fn, - const uint8_t *lun, int lun_len, int atomic, void *tgt_priv) -{ - struct scst_rx_mgmt_params params; - - BUG_ON(fn == SCST_ABORT_TASK); - - memset(¶ms, 0, sizeof(params)); - params.fn = fn; - params.lun = lun; - params.lun_len = lun_len; - params.lun_set = 1; - params.atomic = atomic; - params.tgt_priv = tgt_priv; - return scst_rx_mgmt_fn(sess, ¶ms); -} - -/* - * Provides various CDB info - * Parameters: - * cdb_p - pointer to CDB - * dev_type - SCSI device type - * info_p - the result structure (output) - * Returns 0 on success, -1 otherwise - */ -int scst_get_cdb_info(const uint8_t *cdb_p, int dev_type, - struct scst_info_cdb *info_p); - -/* - * Set error SCSI status in the command and prepares it for returning it - */ -void scst_set_cmd_error_status(struct scst_cmd *cmd, int status); - -/* - * Set error in the command and fill the sense buffer - */ -void scst_set_cmd_error(struct scst_cmd *cmd, int key, int asc, int ascq); - -/* - * Sets BUSY or TASK QUEUE FULL status - */ -void scst_set_busy(struct scst_cmd *cmd); - -/* - * Finds a command based on the supplied tag comparing it with one - * that previously set by scst_cmd_set_tag(). - * Returns the command on success or NULL otherwise - */ -struct scst_cmd *scst_find_cmd_by_tag(struct scst_session *sess, uint64_t tag); - -/* - * Finds a command based on user supplied data and comparision - * callback function, that should return true, if the command is found. - * Returns the command on success or NULL otherwise - */ -struct scst_cmd *scst_find_cmd(struct scst_session *sess, void *data, - int (*cmp_fn) (struct scst_cmd *cmd, - void *data)); - -/* - * Translates SCST's data direction to DMA one - */ -static inline int scst_to_dma_dir(int scst_dir) -{ - return scst_dir; -} - -/* - * Translates SCST data direction to DMA one from the perspective - * of the target device. - */ -static inline int scst_to_tgt_dma_dir(int scst_dir) -{ - if (scst_dir == SCST_DATA_WRITE) - return DMA_FROM_DEVICE; - else if (scst_dir == SCST_DATA_READ) - return DMA_TO_DEVICE; - return scst_dir; -} - -/* - * Returns 1, if cmd's CDB is locally handled by SCST and 0 otherwise. - * Dev handlers parse() and dev_done() not called for such commands. - */ -static inline int scst_is_cmd_local(struct scst_cmd *cmd) -{ - int res = 0; - switch (cmd->cdb[0]) { - case REPORT_LUNS: - res = 1; - } - return res; -} - -/* - * Registers a virtual device. - * Parameters: - * dev_type - the device's device handler - * dev_name - the new device name, NULL-terminated string. Must be uniq - * among all virtual devices in the system. The value isn't - * copied, only the reference is stored, so the value must - * remain valid during the device lifetime. - * Returns assinged to the device ID on success, or negative value otherwise - */ -int scst_register_virtual_device(struct scst_dev_type *dev_handler, - const char *dev_name); - -/* - * Unegisters a virtual device. - * Parameters: - * id - the device's ID, returned by the registration function - */ -void scst_unregister_virtual_device(int id); - -/* - * Get/Set functions for tgt's target private data - */ -static inline void *scst_tgt_get_tgt_priv(struct scst_tgt *tgt) -{ - return tgt->tgt_priv; -} - -static inline void scst_tgt_set_tgt_priv(struct scst_tgt *tgt, void *val) -{ - tgt->tgt_priv = val; -} - -/* - * Get/Set functions for session's target private data - */ -static inline void *scst_sess_get_tgt_priv(struct scst_session *sess) -{ - return sess->tgt_priv; -} - -static inline void scst_sess_set_tgt_priv(struct scst_session *sess, - void *val) -{ - sess->tgt_priv = val; -} - -/* Returns TRUE if cmd is being executed in atomic context */ -static inline int scst_cmd_atomic(struct scst_cmd *cmd) -{ - int res = cmd->atomic; -#ifdef EXTRACHECKS - if (unlikely(in_atomic() && !res)) { - printk(KERN_ERR "ERROR: in_atomic() and non-atomic cmd\n"); - dump_stack(); - cmd->atomic = 1; - res = 1; - } -#endif - return res; -} - -/* Returns cmd's session */ -static inline struct scst_session *scst_cmd_get_session(struct scst_cmd *cmd) -{ - return cmd->sess; -} - -/* Returns cmd's response data length */ -static inline int scst_cmd_get_resp_data_len(struct scst_cmd *cmd) -{ - return cmd->resp_data_len; -} - -/* Returns cmd's response flags (SCST_TSC_FLAG_* constants) */ -static inline int scst_cmd_get_tgt_resp_flags(struct scst_cmd *cmd) -{ - return cmd->tgt_resp_flags; -} - -/* - * Returns pointer to cmd's SG data buffer. - * - * Usage of this function is not recommended, use scst_get_buf_*() - * family of functions instead. - */ -static inline struct scatterlist *scst_cmd_get_sg(struct scst_cmd *cmd) -{ - return cmd->sg; -} - -/* - * Returns cmd's data buffer length. - * - * In case if you need to iterate over data in the buffer, usage of - * this function is not recommended, use scst_get_buf_*() - * family of functions instead. - */ -static inline unsigned int scst_cmd_get_bufflen(struct scst_cmd *cmd) -{ - return cmd->bufflen; -} - -/* - * Returns cmd's sg_cnt. - * - * Usage of this function is not recommended, use scst_get_buf_*() - * family of functions instead. - */ -static inline unsigned short scst_cmd_get_sg_cnt(struct scst_cmd *cmd) -{ - return cmd->sg_cnt; -} - -/* Returns cmd's data direction */ -static inline scst_data_direction scst_cmd_get_data_direction( - struct scst_cmd *cmd) -{ - return cmd->data_direction; -} - -/* Returns cmd's relative data offset */ -static inline unsigned int scst_cmd_get_offset(struct scst_cmd *cmd) -{ - return 0; -} - -/* Returns cmd's status byte from host device */ -static inline uint8_t scst_cmd_get_status(struct scst_cmd *cmd) -{ - return cmd->status; -} - -/* Returns cmd's status from host adapter itself */ -static inline uint8_t scst_cmd_get_msg_status(struct scst_cmd *cmd) -{ - return cmd->msg_status; -} - -/* Returns cmd's status set by low-level driver to indicate its status */ -static inline uint8_t scst_cmd_get_host_status(struct scst_cmd *cmd) -{ - return cmd->host_status; -} - -/* Returns cmd's status set by SCSI mid-level */ -static inline uint8_t scst_cmd_get_driver_status(struct scst_cmd *cmd) -{ - return cmd->driver_status; -} - -/* Returns pointer to cmd's sense buffer */ -static inline uint8_t *scst_cmd_get_sense_buffer(struct scst_cmd *cmd) -{ - return cmd->sense_buffer; -} - -/* Returns cmd's sense buffer length */ -static inline int scst_cmd_get_sense_buffer_len(struct scst_cmd *cmd) -{ - return sizeof(cmd->sense_buffer); -} - -/* - * Get/Set functions for cmd's target SN - */ -static inline uint64_t scst_cmd_get_tag(struct scst_cmd *cmd) -{ - return cmd->tag; -} - -static inline void scst_cmd_set_tag(struct scst_cmd *cmd, uint64_t tag) -{ - cmd->tag = tag; -} - -/* - * Get/Set functions for cmd's target private data. - * Variant with *_lock must be used if target driver uses - * scst_find_cmd() to avoid race with it, except inside scst_find_cmd()'s - * callback, where lock is already taken. - */ -static inline void *scst_cmd_get_tgt_priv(struct scst_cmd *cmd) -{ - return cmd->tgt_priv; -} - -static inline void scst_cmd_set_tgt_priv(struct scst_cmd *cmd, void *val) -{ - cmd->tgt_priv = val; -} - -void *scst_cmd_get_tgt_priv_lock(struct scst_cmd *cmd); -void scst_cmd_set_tgt_priv_lock(struct scst_cmd *cmd, void *val); - -/* - * Get/Set functions for data_buf_tgt_alloc flag - */ -static inline int scst_cmd_get_data_buf_tgt_alloc(struct scst_cmd *cmd) -{ - return cmd->data_buf_tgt_alloc; -} - -static inline void scst_cmd_set_data_buf_tgt_alloc(struct scst_cmd *cmd) -{ - cmd->data_buf_tgt_alloc = 1; -} - -/* - * Get/Set functions for data_buf_alloced flag - */ -static inline int scst_cmd_get_data_buff_alloced(struct scst_cmd *cmd) -{ - return cmd->data_buf_alloced; -} - -static inline void scst_cmd_set_data_buff_alloced(struct scst_cmd *cmd) -{ - cmd->data_buf_alloced = 1; -} - -/* - * Get/Set functions for no_sgv flag - */ -static inline int scst_cmd_get_no_sgv(struct scst_cmd *cmd) -{ - return cmd->no_sgv; -} - -static inline void scst_cmd_set_no_sgv(struct scst_cmd *cmd) -{ - cmd->no_sgv = 1; -} - -/* - * Get/Set functions for tgt_sn - */ -static inline int scst_cmd_get_tgt_sn(struct scst_cmd *cmd) -{ - BUG_ON(!cmd->tgt_sn_set); - return cmd->tgt_sn; -} - -static inline void scst_cmd_set_tgt_sn(struct scst_cmd *cmd, uint32_t tgt_sn) -{ - cmd->tgt_sn_set = 1; - cmd->tgt_sn = tgt_sn; -} - - -/* - * Returns 1 if the cmd was aborted, so its status is invalid and no - * reply shall be sent to the remote initiator. A target driver should - * only clear internal resources, associated with cmd. - */ -static inline int scst_cmd_aborted(struct scst_cmd *cmd) -{ - return test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags) && - !test_bit(SCST_CMD_ABORTED_OTHER, &cmd->cmd_flags); -} - -/* - * Get/Set functions for expected data direction, transfer length - * and its validity flag - */ -static inline int scst_cmd_is_expected_set(struct scst_cmd *cmd) -{ - return cmd->expected_values_set; -} - -static inline scst_data_direction scst_cmd_get_expected_data_direction( - struct scst_cmd *cmd) -{ - return cmd->expected_data_direction; -} - -static inline int scst_cmd_get_expected_transfer_len( - struct scst_cmd *cmd) -{ - return cmd->expected_transfer_len; -} - -static inline void scst_cmd_set_expected(struct scst_cmd *cmd, - scst_data_direction expected_data_direction, - int expected_transfer_len) -{ - cmd->expected_data_direction = expected_data_direction; - cmd->expected_transfer_len = expected_transfer_len; - cmd->expected_values_set = 1; -} - -/* - * Get/clear functions for cmd's may_need_dma_sync - */ -static inline int scst_get_may_need_dma_sync(struct scst_cmd *cmd) -{ - return cmd->may_need_dma_sync; -} - -static inline void scst_clear_may_need_dma_sync(struct scst_cmd *cmd) -{ - cmd->may_need_dma_sync = 0; -} - -/* - * Get/Set function for mgmt cmd's target private data - */ -static inline void *scst_mgmt_cmd_get_tgt_priv(struct scst_mgmt_cmd *mcmd) -{ - return mcmd->tgt_priv; -} - -static inline void scst_mgmt_cmd_set_tgt_priv(struct scst_mgmt_cmd *mcmd, - void *val) -{ - mcmd->tgt_priv = val; -} - -/* - * Returns mgmt cmd's completition status (SCST_MGMT_STATUS_* constants) - */ -static inline int scst_mgmt_cmd_get_status(struct scst_mgmt_cmd *mcmd) -{ - return mcmd->status; -} - -/* - * Functions for access to the commands data (SG) buffer, - * including HIGHMEM environment. Should be used instead of direct - * access. Returns the mapped buffer length for success, 0 for EOD, - * negative error code otherwise. - * - * "Buf" argument returns the mapped buffer - * - * The "put" function unmaps the buffer. - */ -int __scst_get_buf(struct scst_cmd *cmd, uint8_t **buf); -static inline int scst_get_buf_first(struct scst_cmd *cmd, uint8_t **buf) -{ - cmd->get_sg_buf_entry_num = 0; - cmd->may_need_dma_sync = 1; - return __scst_get_buf(cmd, buf); -} - -static inline int scst_get_buf_next(struct scst_cmd *cmd, uint8_t **buf) -{ - return __scst_get_buf(cmd, buf); -} - -static inline void scst_put_buf(struct scst_cmd *cmd, void *buf) -{ -#ifdef SCST_HIGHMEM - if (cmd->sg_cnt) { - if (scst_cmd_atomic(cmd)) { - enum km_type km; - BUG_ON(in_irq()); - if (in_softirq()) - km = KM_SOFTIRQ0; - else - km = KM_USER0; - kunmap_atomic(buf, km); - } else - kunmap(buf); - } -#endif -} - -/* - * Returns approximate higher rounded buffers count that - * scst_get_buf_[first|next]() return. - */ -static inline int scst_get_buf_count(struct scst_cmd *cmd) -{ - int res; -#ifdef SCST_HIGHMEM - res = (cmd->bufflen >> PAGE_SHIFT) + 1; -#else - res = (cmd->sg_cnt == 0) ? 1 : cmd->sg_cnt; -#endif - return res; -} - -/* - * Suspends and resumes any activity. - * scst_suspend_activity() doesn't return until there are any - * active commands (state after SCST_CMD_STATE_INIT). New arriving - * commands stay in that state until scst_resume_activity() is called. - */ -void scst_suspend_activity(void); -void scst_resume_activity(void); - -/* - * Main SCST commands processing routing. Must be used only by dev handlers. - * Argument context sets the execution context, only SCST_CONTEXT_DIRECT and - * SCST_CONTEXT_DIRECT_ATOMIC are allowed. - */ -void scst_process_active_cmd(struct scst_cmd *cmd, int context); - -/* - * Checks if command can be executed (reservations, etc.) or there are local - * events, like pending UAs. Returns < 0 if command must be aborted, > 0 if - * there is an event and command should be immediately completed, or 0 - * otherwise. - * - * !! Dev handlers implementing exec() callback must call this function there !! - * !! just before the actual command's execution !! - */ -int scst_check_local_events(struct scst_cmd *cmd); - -/* - * Returns target driver's root entry in SCST's /proc hierarchy. - * The driver can create own files/directoryes here, which should - * be deleted in the driver's release(). - */ -static inline struct proc_dir_entry *scst_proc_get_tgt_root( - struct scst_tgt_template *vtt) -{ - return vtt->proc_tgt_root; -} - -/* - * Returns device handler's root entry in SCST's /proc hierarchy. - * The driver can create own files/directoryes here, which should - * be deleted in the driver's detach()/release(). - */ -static inline struct proc_dir_entry *scst_proc_get_dev_type_root( - struct scst_dev_type *dtt) -{ - return dtt->proc_dev_type_root; -} - -/** - ** Two library functions and the structure to help the drivers - ** that use scst_debug.* facilities manage "trace_level" /proc entry. - ** The functions service "standard" log levels and allow to work - ** with driver specific levels, which should be passed inside as - ** NULL-terminated array of struct scst_proc_log's, where: - ** - val - the level's numeric value - ** - token - its string representation - **/ - -struct scst_proc_log { - unsigned int val; - const char *token; -}; - -int scst_proc_log_entry_read(struct seq_file *seq, unsigned long log_level, - const struct scst_proc_log *tbl); - -int scst_proc_log_entry_write(struct file *file, const char *buf, - unsigned long length, unsigned long *log_level, - unsigned long default_level, const struct scst_proc_log *tbl); - -/* - * helper data structure and function to create proc entry. - */ -struct scst_proc_data { - struct file_operations seq_op; - int (*show)(struct seq_file *, void *); - void *data; -}; - -int scst_single_seq_open(struct inode *inode, struct file *file); - -struct proc_dir_entry *scst_create_proc_entry(struct proc_dir_entry * root, - const char *name, struct scst_proc_data *pdata); - -#define SCST_DEF_RW_SEQ_OP(x) \ - .seq_op = { \ - .owner = THIS_MODULE, \ - .open = scst_single_seq_open,\ - .read = seq_read, \ - .write = x, \ - .llseek = seq_lseek, \ - .release = single_release, \ - }, - -/* - * Adds and deletes (stops) num SCST's threads. Returns 0 on success, - * error code otherwise. - */ -int scst_add_cmd_threads(int num); -void scst_del_cmd_threads(int num); - -void scst_set_cmd_error_sense(struct scst_cmd *cmd, uint8_t *sense, - unsigned int len); - -/* - * Returnes a pseudo-random number for debugging purposes. Available only with - * DEBUG on - */ -unsigned long scst_random(void); - -/* - * Sets response data length for cmd and truncates its SG vector accordingly. - * The cmd->resp_data_len must not be set directly, it must be set only - * using this function. Value of resp_data_len must be <= cmd->bufflen. - */ -void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len); - -/* - * Checks if total memory allocated by commands is less, than defined - * limit (scst_cur_max_cmd_mem) and returns 0, if it is so. Otherwise, - * returnes 1 and sets on cmd QUEUE FULL or BUSY status as well as - * SCST_CMD_STATE_XMIT_RESP state. Target drivers and dev handlers are - * required to call this function if they allocate data buffers on their - * own. - */ -int scst_check_mem(struct scst_cmd *cmd); - -/* - * Get/put global ref counter that prevents from entering into suspended - * activities stage, so protects from any global management operations. - */ -void scst_get(void); -void scst_put(void); - -/* - * Allocates and returns pointer to SG vector with data size "size". - * In *count returned the count of entries in the vector. - * Returns NULL for failure. - */ -struct scatterlist *scst_alloc(int size, unsigned long gfp_mask, int *count); - -/* Frees SG vector returned by scst_alloc() */ -void scst_free(struct scatterlist *sg, int count); - -/* - * Adds local to the current thread data to tgt_dev - * (they will be local for the tgt_dev and current thread). - */ -void scst_add_thr_data(struct scst_tgt_dev *tgt_dev, - struct scst_thr_data_hdr *data, - void (*free_fn) (struct scst_thr_data_hdr *data)); - -/* Deletes all local to threads data from tgt_dev */ -void scst_del_all_thr_data(struct scst_tgt_dev *tgt_dev); - -/* Deletes all local to threads data from all tgt_dev's of the dev */ -void scst_dev_del_all_thr_data(struct scst_device *dev); - -/* Finds local to the current thread data. Returns NULL, if they not found. */ -struct scst_thr_data_hdr *scst_find_thr_data(struct scst_tgt_dev *tgt_dev); - -static inline void scst_thr_data_get(struct scst_thr_data_hdr *data) -{ - atomic_inc(&data->ref); -} - -static inline void scst_thr_data_put(struct scst_thr_data_hdr *data) -{ - if (atomic_dec_and_test(&data->ref)) - data->free_fn(data); -} - -/* SGV pool routines and flag bits */ - -/* Set if the allocated object must be not from the cache */ -#define SCST_POOL_ALLOC_NO_CACHED 1 - -/* Set if there should not be any memory allocations on a cache miss */ -#define SCST_POOL_NO_ALLOC_ON_CACHE_MISS 2 - -/* Set an object should be returned even if it doesn't have SG vector built */ -#define SCST_POOL_RETURN_OBJ_ON_ALLOC_FAIL 4 - -struct sgv_pool_obj; -struct sgv_pool; - -struct sgv_pool *sgv_pool_create(const char *name, int clustered); -void sgv_pool_destroy(struct sgv_pool *pool); - -void sgv_pool_set_allocator(struct sgv_pool *pool, - struct page *(*alloc_pages_fn)(struct scatterlist *, gfp_t, void *), - void (*free_pages_fn)(struct scatterlist *, int, void *)); - -struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size, - unsigned long gfp_mask, int atomic, int *count, - struct sgv_pool_obj **sgv, void *priv); -void sgv_pool_free(struct sgv_pool_obj *sgv); - -void *sgv_get_priv(struct sgv_pool_obj *sgv); - -/** - ** Generic parse() support routines. - ** Done via pointer on functions to avoid unneeded dereferences on - ** the fast path. - **/ - -/* Calculates and returns block shift for the given sector size */ -int scst_calc_block_shift(int sector_size); - -/* Generic parse() for SBC (disk) devices */ -int scst_sbc_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*get_block_shift)(struct scst_cmd *cmd)); - -/* Generic parse() for MMC (cdrom) devices */ -int scst_cdrom_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*get_block_shift)(struct scst_cmd *cmd)); - -/* Generic parse() for MO disk devices */ -int scst_modisk_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*get_block_shift)(struct scst_cmd *cmd)); - -/* Generic parse() for tape devices */ -int scst_tape_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*get_block_size)(struct scst_cmd *cmd)); - -/* Generic parse() for changer devices */ -int scst_changer_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*nothing)(struct scst_cmd *cmd)); - -/* Generic parse() for "processor" devices */ -int scst_processor_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*nothing)(struct scst_cmd *cmd)); - -/* Generic parse() for RAID devices */ -int scst_raid_generic_parse(struct scst_cmd *cmd, - struct scst_info_cdb *info_cdb, - int (*nothing)(struct scst_cmd *cmd)); - -/** - ** Generic dev_done() support routines. - ** Done via pointer on functions to avoid unneeded dereferences on - ** the fast path. - **/ - -/* Generic dev_done() for block devices */ -int scst_block_generic_dev_done(struct scst_cmd *cmd, - void (*set_block_shift)(struct scst_cmd *cmd, int block_shift)); - -/* Generic dev_done() for tape devices */ -int scst_tape_generic_dev_done(struct scst_cmd *cmd, - void (*set_block_size)(struct scst_cmd *cmd, int block_size)); - -#endif /* __SCST_H */ diff --git a/drivers/infiniband/ulp/srpt/scst_const.h b/drivers/infiniband/ulp/srpt/scst_const.h deleted file mode 100644 index 218fa74..0000000 --- a/drivers/infiniband/ulp/srpt/scst_const.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * include/scst_const.h - * - * Copyright (C) 2004-2007 Vladislav Bolkhovitin <vst@vlnb.net> - * - * Contains macroses for execution tracing and error reporting - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, version 2 - * of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SCST_CONST_H -#define __SCST_CONST_H - -#include <scsi/scsi.h> - -/*** Shared constants between user and kernel spaces ***/ - -/* Max size of CDB */ -#define SCST_MAX_CDB_SIZE 16 - -/* Max size of sense */ -#define SCST_SENSE_BUFFERSIZE 96 - -/************************************************************* - ** Values for task management functions - *************************************************************/ -#define SCST_ABORT_TASK 0 -#define SCST_ABORT_TASK_SET 1 -#define SCST_CLEAR_ACA 2 -#define SCST_CLEAR_TASK_SET 3 -#define SCST_LUN_RESET 4 -#define SCST_TARGET_RESET 5 - -/** SCST extensions **/ - -/* - * Notifies about I_T nexus loss event in the corresponding session. - * Aborts all tasks there, resets the reservation, if any, and sets - * up the I_T Nexus loss UA. - */ -#define SCST_NEXUS_LOSS_SESS 6 - -/* Aborts all tasks in the corresponding session with TASK_ABORTED status */ -#define SCST_ABORT_ALL_TASKS_SESS 7 - -/* - * Notifies about I_T nexus loss event. Aborts all tasks in all sessions - * of the tgt, resets the reservations, if any, and sets up the I_T Nexus - * loss UA. - */ -#define SCST_NEXUS_LOSS 8 - -/* Aborts all tasks in all sessions of the tgt with TASK_ABORTED status */ -#define SCST_ABORT_ALL_TASKS 9 - -/************************************************************* - ** Values for mgmt cmd's status field. Codes taken from iSCSI - *************************************************************/ -#define SCST_MGMT_STATUS_SUCCESS 0 -#define SCST_MGMT_STATUS_TASK_NOT_EXIST -1 -#define SCST_MGMT_STATUS_LUN_NOT_EXIST -2 -#define SCST_MGMT_STATUS_FN_NOT_SUPPORTED -5 -#define SCST_MGMT_STATUS_REJECTED -255 -#define SCST_MGMT_STATUS_FAILED -129 - -/************************************************************* - ** SCSI task attribute queue types - *************************************************************/ -enum scst_cmd_queue_type -{ - SCST_CMD_QUEUE_UNTAGGED = 0, - SCST_CMD_QUEUE_SIMPLE, - SCST_CMD_QUEUE_ORDERED, - SCST_CMD_QUEUE_HEAD_OF_QUEUE, - SCST_CMD_QUEUE_ACA -}; - -/************************************************************* - ** Data direction aliases - *************************************************************/ -#define SCST_DATA_UNKNOWN 0 -#define SCST_DATA_WRITE 1 -#define SCST_DATA_READ 2 -#define SCST_DATA_NONE 3 - -/************************************************************* - ** Sense manipulation and examination - *************************************************************/ -#define SCST_LOAD_SENSE(key_asc_ascq) key_asc_ascq - -#define SCST_SENSE_VALID(sense) ((((uint8_t *)(sense))[0] & 0x70) == 0x70) - -#define SCST_NO_SENSE(sense) (((uint8_t *)(sense))[2] == 0) - -/************************************************************* - ** Sense data for the appropriate errors. Can be used with - ** scst_set_cmd_error() - *************************************************************/ -#define scst_sense_no_sense NO_SENSE, 0x00, 0 -#define scst_sense_hardw_error HARDWARE_ERROR, 0x44, 0 -#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0 -#define scst_sense_invalid_opcode ILLEGAL_REQUEST, 0x20, 0 -#define scst_sense_invalid_field_in_cdb ILLEGAL_REQUEST, 0x24, 0 -#define scst_sense_invalid_field_in_parm_list ILLEGAL_REQUEST, 0x26, 0 -#define scst_sense_reset_UA UNIT_ATTENTION, 0x29, 0 -#define scst_sense_nexus_loss_UA UNIT_ATTENTION, 0x29, 0x7 -#define scst_sense_saving_params_unsup ILLEGAL_REQUEST, 0x39, 0 -#define scst_sense_lun_not_supported ILLEGAL_REQUEST, 0x25, 0 -#define scst_sense_data_protect DATA_PROTECT, 0x00, 0 -#define scst_sense_miscompare_error MISCOMPARE, 0x1D, 0 -#define scst_sense_block_out_range_error ILLEGAL_REQUEST, 0x21, 0 -#define scst_sense_medium_changed_UA UNIT_ATTENTION, 0x28, 0 -#define scst_sense_read_error MEDIUM_ERROR, 0x11, 0 -#define scst_sense_write_error MEDIUM_ERROR, 0x03, 0 -#define scst_sense_not_ready NOT_READY, 0x04, 0x10 -#define scst_sense_invalid_message ILLEGAL_REQUEST, 0x49, 0 - -/************************************************************* - * SCSI opcodes not listed anywhere else - *************************************************************/ -#ifndef REPORT_DEVICE_IDENTIFIER -#define REPORT_DEVICE_IDENTIFIER 0xA3 -#endif -#ifndef INIT_ELEMENT_STATUS -#define INIT_ELEMENT_STATUS 0x07 -#endif -#ifndef INIT_ELEMENT_STATUS_RANGE -#define INIT_ELEMENT_STATUS_RANGE 0x37 -#endif -#ifndef PREVENT_ALLOW_MEDIUM -#define PREVENT_ALLOW_MEDIUM 0x1E -#endif -#ifndef READ_ATTRIBUTE -#define READ_ATTRIBUTE 0x8C -#endif -#ifndef REQUEST_VOLUME_ADDRESS -#define REQUEST_VOLUME_ADDRESS 0xB5 -#endif -#ifndef WRITE_ATTRIBUTE -#define WRITE_ATTRIBUTE 0x8D -#endif -#ifndef WRITE_VERIFY_16 -#define WRITE_VERIFY_16 0x8E -#endif -#ifndef VERIFY_6 -#define VERIFY_6 0x13 -#endif -#ifndef VERIFY_12 -#define VERIFY_12 0xAF -#endif -#ifndef READ_16 -#define READ_16 0x88 -#endif -#ifndef WRITE_16 -#define WRITE_16 0x8a -#endif -#ifndef VERIFY_16 -#define VERIFY_16 0x8f -#endif -#ifndef SERVICE_ACTION_IN -#define SERVICE_ACTION_IN 0x9e -#endif -#ifndef SAI_READ_CAPACITY_16 -/* values for service action in */ -#define SAI_READ_CAPACITY_16 0x10 -#endif -#ifndef MI_REPORT_TARGET_PGS -/* values for maintenance in */ -#define MI_REPORT_TARGET_PGS 0x0a -#endif -#ifndef REPORT_LUNS -#define REPORT_LUNS 0xa0 -#endif - -/************************************************************* - ** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft - ** T10/1561-D Revision 4 Draft dated 7th November 2002. - *************************************************************/ -#define SAM_STAT_GOOD 0x00 -#define SAM_STAT_CHECK_CONDITION 0x02 -#define SAM_STAT_CONDITION_MET 0x04 -#define SAM_STAT_BUSY 0x08 -#define SAM_STAT_INTERMEDIATE 0x10 -#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14 -#define SAM_STAT_RESERVATION_CONFLICT 0x18 -#define SAM_STAT_COMMAND_TERMINATED 0x22 /* obsolete in SAM-3 */ -#define SAM_STAT_TASK_SET_FULL 0x28 -#define SAM_STAT_ACA_ACTIVE 0x30 -#define SAM_STAT_TASK_ABORTED 0x40 - -/************************************************************* - ** Control byte field in CDB - *************************************************************/ -#ifndef CONTROL_BYTE_LINK_BIT -#define CONTROL_BYTE_LINK_BIT 0x01 -#endif -#ifndef CONTROL_BYTE_NACA_BIT -#define CONTROL_BYTE_NACA_BIT 0x04 -#endif - -/************************************************************* - ** Byte 1 in INQUIRY CDB - *************************************************************/ -#define SCST_INQ_EVPD 0x01 - -/************************************************************* - ** Byte 3 in Standard INQUIRY data - *************************************************************/ -#define SCST_INQ_BYTE3 3 - -#define SCST_INQ_NORMACA_BIT 0x20 - -/************************************************************* - ** Byte 2 in RESERVE_10 CDB - *************************************************************/ -#define SCST_RES_3RDPTY 0x10 -#define SCST_RES_LONGID 0x02 - -/************************************************************* - ** Bits in the READ POSITION command - *************************************************************/ -#define TCLP_BIT 4 -#define LONG_BIT 2 -#define BT_BIT 1 - -/************************************************************* - ** Misc SCSI constants - *************************************************************/ -#define SCST_SENSE_ASC_UA_RESET 0x29 -#define READ_CAP_LEN 8 -#define READ_CAP16_LEN 12 -#define BYTCHK 0x02 -#define POSITION_LEN_SHORT 20 -#define POSITION_LEN_LONG 32 - -#endif /* __SCST_CONST_H */ diff --git a/drivers/infiniband/ulp/vnic/Kconfig b/drivers/infiniband/ulp/vnic/Kconfig deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/Makefile b/drivers/infiniband/ulp/vnic/Makefile deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_config.c b/drivers/infiniband/ulp/vnic/vnic_config.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_config.h b/drivers/infiniband/ulp/vnic/vnic_config.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_control.c b/drivers/infiniband/ulp/vnic/vnic_control.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_control.h b/drivers/infiniband/ulp/vnic/vnic_control.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_control_pkt.h b/drivers/infiniband/ulp/vnic/vnic_control_pkt.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_data.c b/drivers/infiniband/ulp/vnic/vnic_data.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_data.h b/drivers/infiniband/ulp/vnic/vnic_data.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_ib.c b/drivers/infiniband/ulp/vnic/vnic_ib.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_ib.h b/drivers/infiniband/ulp/vnic/vnic_ib.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_main.c b/drivers/infiniband/ulp/vnic/vnic_main.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_main.h b/drivers/infiniband/ulp/vnic/vnic_main.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_netpath.c b/drivers/infiniband/ulp/vnic/vnic_netpath.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_netpath.h b/drivers/infiniband/ulp/vnic/vnic_netpath.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_stats.c b/drivers/infiniband/ulp/vnic/vnic_stats.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_stats.h b/drivers/infiniband/ulp/vnic/vnic_stats.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_sys.c b/drivers/infiniband/ulp/vnic/vnic_sys.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_sys.h b/drivers/infiniband/ulp/vnic/vnic_sys.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_trailer.h b/drivers/infiniband/ulp/vnic/vnic_trailer.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_util.h b/drivers/infiniband/ulp/vnic/vnic_util.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.c b/drivers/infiniband/ulp/vnic/vnic_viport.c deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/infiniband/ulp/vnic/vnic_viport.h b/drivers/infiniband/ulp/vnic/vnic_viport.h deleted file mode 100644 index e69de29..0000000