Added out-of-tree build infrastructure for the ibmvstgt driver together with copies of the relevant ibmvstgt source files from Linux 2.6.35.

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1977 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2010-08-24 17:31:21 +00:00
parent ed4e1e91c0
commit bcec8f6484
6 changed files with 1850 additions and 0 deletions

44
ibmvstgt/Makefile Normal file
View File

@@ -0,0 +1,44 @@
#
# Makefile for ibmvstgt.ko.
#
SCST_DIR := $(shell pwd)/../scst/src
SUBDIRS := $(shell pwd)
ifeq ($(KVER),)
ifeq ($(KDIR),)
KVER = $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build
else
KVER = $$KERNELRELEASE
endif
else
KDIR ?= /lib/modules/$(KVER)/build
endif
# The file Modules.symvers has been renamed in the 2.6.18 kernel to
# Module.symvers. Find out which name to use by looking in $(KDIR).
MODULE_SYMVERS:=$(shell if [ -e $(KDIR)/Module.symvers ]; then \
echo Module.symvers; else echo Modules.symvers; fi)
all: src/$(MODULE_SYMVERS)
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd)/src modules
install: all src/ib_srpt.ko
@eval `sed -n 's/#define UTS_RELEASE /KERNELRELEASE=/p' $(KDIR)/include/linux/version.h $(KDIR)/include/linux/utsrelease.h 2>/dev/null`; \
install -vD -m 644 src/ib_srpt.ko \
$(DESTDIR)$(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra/ib_srpt.ko
-/sbin/depmod -aq $(KVER)
src/Module.symvers src/Modules.symvers: $(SCST_DIR)/$(MODULE_SYMVERS)
cp $< $@;
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd)/src clean
rm -f src/Modules.symvers src/Module.symvers src/Module.markers \
src/modules.order
extraclean: clean
.PHONY: all install clean extraclean

10
ibmvstgt/src/Makefile Normal file
View File

@@ -0,0 +1,10 @@
IBMVSTGT_INC_DIR := $(SUBDIRS)/../../scst/include/
EXTRA_CFLAGS += -I$(SCST_INC_DIR)
#EXTRA_CFLAGS += -DCONFIG_SCST_TRACING
#EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG
#EXTRA_CFLAGS += -g -fno-inline -fno-inline-functions
#EXTRA_CFLAGS += -DCONFIG_SCST_EXTRACHECKS
#EXTRA_CFLAGS += -Wextra -Wno-unused-parameter
obj-m += libsrp.o ibmvstgt.o

129
ibmvstgt/src/ibmvscsi.h Normal file
View File

@@ -0,0 +1,129 @@
/* ------------------------------------------------------------
* ibmvscsi.h
* (C) Copyright IBM Corporation 1994, 2003
* Authors: Colin DeVilbiss (devilbis@us.ibm.com)
* Santiago Leon (santil@us.ibm.com)
* Dave Boutcher (sleddog@us.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* ------------------------------------------------------------
* Emulation of a SCSI host adapter for Virtual I/O devices
*
* This driver allows the Linux SCSI peripheral drivers to directly
* access devices in the hosting partition, either on an iSeries
* hypervisor system or a converged hypervisor system.
*/
#ifndef IBMVSCSI_H
#define IBMVSCSI_H
#include <linux/types.h>
#include <linux/list.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include "viosrp.h"
struct scsi_cmnd;
struct Scsi_Host;
/* Number of indirect bufs...the list of these has to fit in the
* additional data of the srp_cmd struct along with the indirect
* descriptor
*/
#define MAX_INDIRECT_BUFS 10
#define IBMVSCSI_MAX_REQUESTS_DEFAULT 100
#define IBMVSCSI_CMDS_PER_LUN_DEFAULT 16
#define IBMVSCSI_MAX_SECTORS_DEFAULT 256 /* 32 * 8 = default max I/O 32 pages */
#define IBMVSCSI_MAX_CMDS_PER_LUN 64
/* ------------------------------------------------------------
* Data Structures
*/
/* an RPA command/response transport queue */
struct crq_queue {
struct viosrp_crq *msgs;
int size, cur;
dma_addr_t msg_token;
spinlock_t lock;
};
/* a unit of work for the hosting partition */
struct srp_event_struct {
union viosrp_iu *xfer_iu;
struct scsi_cmnd *cmnd;
struct list_head list;
void (*done) (struct srp_event_struct *);
struct viosrp_crq crq;
struct ibmvscsi_host_data *hostdata;
atomic_t free;
union viosrp_iu iu;
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
struct timer_list timer;
union viosrp_iu *sync_srp;
struct srp_direct_buf *ext_list;
dma_addr_t ext_list_token;
};
/* a pool of event structs for use */
struct event_pool {
struct srp_event_struct *events;
u32 size;
int next;
union viosrp_iu *iu_storage;
dma_addr_t iu_token;
};
/* all driver data associated with a host adapter */
struct ibmvscsi_host_data {
atomic_t request_limit;
int client_migrated;
struct device *dev;
struct event_pool pool;
struct crq_queue queue;
struct tasklet_struct srp_task;
struct list_head sent;
struct Scsi_Host *host;
struct mad_adapter_info_data madapter_info;
struct capabilities caps;
dma_addr_t caps_addr;
dma_addr_t adapter_info_addr;
};
/* routines for managing a command/response queue */
void ibmvscsi_handle_crq(struct viosrp_crq *crq,
struct ibmvscsi_host_data *hostdata);
struct ibmvscsi_ops {
int (*init_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests);
void (*release_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata,
int max_requests);
int (*reset_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
int (*reenable_crq_queue)(struct crq_queue *queue,
struct ibmvscsi_host_data *hostdata);
int (*send_crq)(struct ibmvscsi_host_data *hostdata,
u64 word1, u64 word2);
int (*resume) (struct ibmvscsi_host_data *hostdata);
};
extern struct ibmvscsi_ops iseriesvscsi_ops;
extern struct ibmvscsi_ops rpavscsi_ops;
#endif /* IBMVSCSI_H */

1004
ibmvstgt/src/ibmvstgt.c Normal file

File diff suppressed because it is too large Load Diff

446
ibmvstgt/src/libsrp.c Normal file
View File

@@ -0,0 +1,446 @@
/*
* SCSI RDMA Protocol lib functions
*
* Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_tgt.h>
#include <scsi/srp.h>
#include <scsi/libsrp.h>
enum srp_task_attributes {
SRP_SIMPLE_TASK = 0,
SRP_HEAD_TASK = 1,
SRP_ORDERED_TASK = 2,
SRP_ACA_TASK = 4
};
/* tmp - will replace with SCSI logging stuff */
#define eprintk(fmt, args...) \
do { \
printk("%s(%d) " fmt, __func__, __LINE__, ##args); \
} while (0)
/* #define dprintk eprintk */
#define dprintk(fmt, args...)
static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
struct srp_buf **ring)
{
int i;
struct iu_entry *iue;
q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL);
if (!q->pool)
return -ENOMEM;
q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL);
if (!q->items)
goto free_pool;
spin_lock_init(&q->lock);
kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *));
for (i = 0, iue = q->items; i < max; i++) {
kfifo_in(&q->queue, (void *) &iue, sizeof(void *));
iue->sbuf = ring[i];
iue++;
}
return 0;
kfree(q->items);
free_pool:
kfree(q->pool);
return -ENOMEM;
}
static void srp_iu_pool_free(struct srp_queue *q)
{
kfree(q->items);
kfree(q->pool);
}
static struct srp_buf **srp_ring_alloc(struct device *dev,
size_t max, size_t size)
{
int i;
struct srp_buf **ring;
ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL);
if (!ring)
return NULL;
for (i = 0; i < max; i++) {
ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL);
if (!ring[i])
goto out;
ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma,
GFP_KERNEL);
if (!ring[i]->buf)
goto out;
}
return ring;
out:
for (i = 0; i < max && ring[i]; i++) {
if (ring[i]->buf)
dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
kfree(ring[i]);
}
kfree(ring);
return NULL;
}
static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max,
size_t size)
{
int i;
for (i = 0; i < max; i++) {
dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
kfree(ring[i]);
}
kfree(ring);
}
int srp_target_alloc(struct srp_target *target, struct device *dev,
size_t nr, size_t iu_size)
{
int err;
spin_lock_init(&target->lock);
INIT_LIST_HEAD(&target->cmd_queue);
target->dev = dev;
dev_set_drvdata(target->dev, target);
target->srp_iu_size = iu_size;
target->rx_ring_size = nr;
target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size);
if (!target->rx_ring)
return -ENOMEM;
err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring);
if (err)
goto free_ring;
return 0;
free_ring:
srp_ring_free(target->dev, target->rx_ring, nr, iu_size);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(srp_target_alloc);
void srp_target_free(struct srp_target *target)
{
srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size,
target->srp_iu_size);
srp_iu_pool_free(&target->iu_queue);
}
EXPORT_SYMBOL_GPL(srp_target_free);
struct iu_entry *srp_iu_get(struct srp_target *target)
{
struct iu_entry *iue = NULL;
if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue,
sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) {
WARN_ONCE(1, "unexpected fifo state");
return NULL;
}
if (!iue)
return iue;
iue->target = target;
INIT_LIST_HEAD(&iue->ilist);
iue->flags = 0;
return iue;
}
EXPORT_SYMBOL_GPL(srp_iu_get);
void srp_iu_put(struct iu_entry *iue)
{
kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue,
sizeof(void *), &iue->target->iu_queue.lock);
}
EXPORT_SYMBOL_GPL(srp_iu_put);
static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md,
enum dma_data_direction dir, srp_rdma_t rdma_io,
int dma_map, int ext_desc)
{
struct iu_entry *iue = NULL;
struct scatterlist *sg = NULL;
int err, nsg = 0, len;
if (dma_map) {
iue = (struct iu_entry *) sc->SCp.ptr;
sg = scsi_sglist(sc);
dprintk("%p %u %u %d\n", iue, scsi_bufflen(sc),
md->len, scsi_sg_count(sc));
nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc),
DMA_BIDIRECTIONAL);
if (!nsg) {
printk("fail to map %p %d\n", iue, scsi_sg_count(sc));
return 0;
}
len = min(scsi_bufflen(sc), md->len);
} else
len = md->len;
err = rdma_io(sc, sg, nsg, md, 1, dir, len);
if (dma_map)
dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
return err;
}
static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
struct srp_indirect_buf *id,
enum dma_data_direction dir, srp_rdma_t rdma_io,
int dma_map, int ext_desc)
{
struct iu_entry *iue = NULL;
struct srp_direct_buf *md = NULL;
struct scatterlist dummy, *sg = NULL;
dma_addr_t token = 0;
int err = 0;
int nmd, nsg = 0, len;
if (dma_map || ext_desc) {
iue = (struct iu_entry *) sc->SCp.ptr;
sg = scsi_sglist(sc);
dprintk("%p %u %u %d %d\n",
iue, scsi_bufflen(sc), id->len,
cmd->data_in_desc_cnt, cmd->data_out_desc_cnt);
}
nmd = id->table_desc.len / sizeof(struct srp_direct_buf);
if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) ||
(dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) {
md = &id->desc_list[0];
goto rdma;
}
if (ext_desc && dma_map) {
md = dma_alloc_coherent(iue->target->dev, id->table_desc.len,
&token, GFP_KERNEL);
if (!md) {
eprintk("Can't get dma memory %u\n", id->table_desc.len);
return -ENOMEM;
}
sg_init_one(&dummy, md, id->table_desc.len);
sg_dma_address(&dummy) = token;
sg_dma_len(&dummy) = id->table_desc.len;
err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
id->table_desc.len);
if (err) {
eprintk("Error copying indirect table %d\n", err);
goto free_mem;
}
} else {
eprintk("This command uses external indirect buffer\n");
return -EINVAL;
}
rdma:
if (dma_map) {
nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc),
DMA_BIDIRECTIONAL);
if (!nsg) {
eprintk("fail to map %p %d\n", iue, scsi_sg_count(sc));
err = -EIO;
goto free_mem;
}
len = min(scsi_bufflen(sc), id->len);
} else
len = id->len;
err = rdma_io(sc, sg, nsg, md, nmd, dir, len);
if (dma_map)
dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
free_mem:
if (token && dma_map)
dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
return err;
}
static int data_out_desc_size(struct srp_cmd *cmd)
{
int size = 0;
u8 fmt = cmd->buf_fmt >> 4;
switch (fmt) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
size = sizeof(struct srp_direct_buf);
break;
case SRP_DATA_DESC_INDIRECT:
size = sizeof(struct srp_indirect_buf) +
sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt;
break;
default:
eprintk("client error. Invalid data_out_format %x\n", fmt);
break;
}
return size;
}
/*
* TODO: this can be called multiple times for a single command if it
* has very long data.
*/
int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
srp_rdma_t rdma_io, int dma_map, int ext_desc)
{
struct srp_direct_buf *md;
struct srp_indirect_buf *id;
enum dma_data_direction dir;
int offset, err = 0;
u8 format;
offset = cmd->add_cdb_len & ~3;
dir = srp_cmd_direction(cmd);
if (dir == DMA_FROM_DEVICE)
offset += data_out_desc_size(cmd);
if (dir == DMA_TO_DEVICE)
format = cmd->buf_fmt >> 4;
else
format = cmd->buf_fmt & ((1U << 4) - 1);
switch (format) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
md = (struct srp_direct_buf *)
(cmd->add_data + offset);
err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc);
break;
case SRP_DATA_DESC_INDIRECT:
id = (struct srp_indirect_buf *)
(cmd->add_data + offset);
err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map,
ext_desc);
break;
default:
eprintk("Unknown format %d %x\n", dir, format);
err = -EINVAL;
}
return err;
}
EXPORT_SYMBOL_GPL(srp_transfer_data);
static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir)
{
struct srp_direct_buf *md;
struct srp_indirect_buf *id;
int len = 0, offset = cmd->add_cdb_len & ~3;
u8 fmt;
if (dir == DMA_TO_DEVICE)
fmt = cmd->buf_fmt >> 4;
else {
fmt = cmd->buf_fmt & ((1U << 4) - 1);
offset += data_out_desc_size(cmd);
}
switch (fmt) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
md = (struct srp_direct_buf *) (cmd->add_data + offset);
len = md->len;
break;
case SRP_DATA_DESC_INDIRECT:
id = (struct srp_indirect_buf *) (cmd->add_data + offset);
len = id->len;
break;
default:
eprintk("invalid data format %x\n", fmt);
break;
}
return len;
}
int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
u64 itn_id, u64 addr)
{
enum dma_data_direction dir;
struct scsi_cmnd *sc;
int tag, len, err;
switch (cmd->task_attr) {
case SRP_SIMPLE_TASK:
tag = MSG_SIMPLE_TAG;
break;
case SRP_ORDERED_TASK:
tag = MSG_ORDERED_TAG;
break;
case SRP_HEAD_TASK:
tag = MSG_HEAD_TAG;
break;
default:
eprintk("Task attribute %d not supported\n", cmd->task_attr);
tag = MSG_ORDERED_TAG;
}
dir = srp_cmd_direction(cmd);
len = vscsis_data_length(cmd, dir);
dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0],
cmd->lun, dir, len, tag, (unsigned long long) cmd->tag);
sc = scsi_host_get_command(shost, dir, GFP_KERNEL);
if (!sc)
return -ENOMEM;
sc->SCp.ptr = info;
memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
sc->sdb.length = len;
sc->sdb.table.sgl = (void *) (unsigned long) addr;
sc->tag = tag;
err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
cmd->tag);
if (err)
scsi_host_put_command(shost, sc);
return err;
}
EXPORT_SYMBOL_GPL(srp_cmd_queue);
MODULE_DESCRIPTION("SCSI RDMA Protocol lib functions");
MODULE_AUTHOR("FUJITA Tomonori");
MODULE_LICENSE("GPL");

217
ibmvstgt/src/viosrp.h Normal file
View File

@@ -0,0 +1,217 @@
/*****************************************************************************/
/* srp.h -- SCSI RDMA Protocol definitions */
/* */
/* Written By: Colin Devilbis, IBM Corporation */
/* */
/* Copyright (C) 2003 IBM Corporation */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* */
/* This file contains structures and definitions for IBM RPA (RS/6000 */
/* platform architecture) implementation of the SRP (SCSI RDMA Protocol) */
/* standard. SRP is used on IBM iSeries and pSeries platforms to send SCSI */
/* commands between logical partitions. */
/* */
/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ) */
/* between partitions. The definitions in this file are architected, */
/* and cannot be changed without breaking compatibility with other versions */
/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
/* between logical partitions */
/*****************************************************************************/
#ifndef VIOSRP_H
#define VIOSRP_H
#include <scsi/srp.h>
#define SRP_VERSION "16.a"
#define SRP_MAX_IU_LEN 256
#define SRP_MAX_LOC_LEN 32
union srp_iu {
struct srp_login_req login_req;
struct srp_login_rsp login_rsp;
struct srp_login_rej login_rej;
struct srp_i_logout i_logout;
struct srp_t_logout t_logout;
struct srp_tsk_mgmt tsk_mgmt;
struct srp_cmd cmd;
struct srp_rsp rsp;
u8 reserved[SRP_MAX_IU_LEN];
};
enum viosrp_crq_formats {
VIOSRP_SRP_FORMAT = 0x01,
VIOSRP_MAD_FORMAT = 0x02,
VIOSRP_OS400_FORMAT = 0x03,
VIOSRP_AIX_FORMAT = 0x04,
VIOSRP_LINUX_FORMAT = 0x06,
VIOSRP_INLINE_FORMAT = 0x07
};
enum viosrp_crq_status {
VIOSRP_OK = 0x0,
VIOSRP_NONRECOVERABLE_ERR = 0x1,
VIOSRP_VIOLATES_MAX_XFER = 0x2,
VIOSRP_PARTNER_PANIC = 0x3,
VIOSRP_DEVICE_BUSY = 0x8,
VIOSRP_ADAPTER_FAIL = 0x10,
VIOSRP_OK2 = 0x99,
};
struct viosrp_crq {
u8 valid; /* used by RPA */
u8 format; /* SCSI vs out-of-band */
u8 reserved;
u8 status; /* non-scsi failure? (e.g. DMA failure) */
u16 timeout; /* in seconds */
u16 IU_length; /* in bytes */
u64 IU_data_ptr; /* the TCE for transferring data */
};
/* MADs are Management requests above and beyond the IUs defined in the SRP
* standard.
*/
enum viosrp_mad_types {
VIOSRP_EMPTY_IU_TYPE = 0x01,
VIOSRP_ERROR_LOG_TYPE = 0x02,
VIOSRP_ADAPTER_INFO_TYPE = 0x03,
VIOSRP_HOST_CONFIG_TYPE = 0x04,
VIOSRP_CAPABILITIES_TYPE = 0x05,
VIOSRP_ENABLE_FAST_FAIL = 0x08,
};
enum viosrp_mad_status {
VIOSRP_MAD_SUCCESS = 0x00,
VIOSRP_MAD_NOT_SUPPORTED = 0xF1,
VIOSRP_MAD_FAILED = 0xF7,
};
enum viosrp_capability_type {
MIGRATION_CAPABILITIES = 0x01,
RESERVATION_CAPABILITIES = 0x02,
};
enum viosrp_capability_support {
SERVER_DOES_NOT_SUPPORTS_CAP = 0x0,
SERVER_SUPPORTS_CAP = 0x01,
SERVER_CAP_DATA = 0x02,
};
enum viosrp_reserve_type {
CLIENT_RESERVE_SCSI_2 = 0x01,
};
enum viosrp_capability_flag {
CLIENT_MIGRATED = 0x01,
CLIENT_RECONNECT = 0x02,
CAP_LIST_SUPPORTED = 0x04,
CAP_LIST_DATA = 0x08,
};
/*
* Common MAD header
*/
struct mad_common {
u32 type;
u16 status;
u16 length;
u64 tag;
};
/*
* All SRP (and MAD) requests normally flow from the
* client to the server. There is no way for the server to send
* an asynchronous message back to the client. The Empty IU is used
* to hang out a meaningless request to the server so that it can respond
* asynchrouously with something like a SCSI AER
*/
struct viosrp_empty_iu {
struct mad_common common;
u64 buffer;
u32 port;
};
struct viosrp_error_log {
struct mad_common common;
u64 buffer;
};
struct viosrp_adapter_info {
struct mad_common common;
u64 buffer;
};
struct viosrp_host_config {
struct mad_common common;
u64 buffer;
};
struct viosrp_fast_fail {
struct mad_common common;
};
struct viosrp_capabilities {
struct mad_common common;
u64 buffer;
};
struct mad_capability_common {
u32 cap_type;
u16 length;
u16 server_support;
};
struct mad_reserve_cap {
struct mad_capability_common common;
u32 type;
};
struct mad_migration_cap {
struct mad_capability_common common;
u32 ecl;
};
struct capabilities{
u32 flags;
char name[SRP_MAX_LOC_LEN];
char loc[SRP_MAX_LOC_LEN];
struct mad_migration_cap migration;
struct mad_reserve_cap reserve;
};
union mad_iu {
struct viosrp_empty_iu empty_iu;
struct viosrp_error_log error_log;
struct viosrp_adapter_info adapter_info;
struct viosrp_host_config host_config;
struct viosrp_fast_fail fast_fail;
struct viosrp_capabilities capabilities;
};
union viosrp_iu {
union srp_iu srp;
union mad_iu mad;
};
struct mad_adapter_info_data {
char srp_version[8];
char partition_name[96];
u32 partition_number;
u32 mad_version;
u32 os_type;
u32 port_max_txu[8]; /* per-port maximum transfer */
};
#endif