From 2f289c967b3091e37c7b15d74381072f181be18f Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 11 Sep 2010 18:20:24 +0000 Subject: [PATCH] More conversions towards SCST. There are still several to-do items left though. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2098 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- ibmvstgt/src/Makefile | 5 +- ibmvstgt/src/ibmvstgt.c | 551 +++++++++++++++++++++++++-------------- ibmvstgt/src/libsrpnew.c | 50 ++-- ibmvstgt/src/libsrpnew.h | 24 +- 4 files changed, 393 insertions(+), 237 deletions(-) diff --git a/ibmvstgt/src/Makefile b/ibmvstgt/src/Makefile index a202c43c7..b9ed8bc0d 100644 --- a/ibmvstgt/src/Makefile +++ b/ibmvstgt/src/Makefile @@ -7,6 +7,5 @@ EXTRA_CFLAGS += -I$(IBMVSTGT_INC_DIR) #EXTRA_CFLAGS += -DCONFIG_SCST_EXTRACHECKS #EXTRA_CFLAGS += -Wextra -Wno-unused-parameter -obj-m := ibmvstgt.o -ibmvstgt-y += libsrpnew.o -ibmvstgt-y += ibmvstgt.o +obj-m += ibmvstgt.o +obj-m += libsrpnew.o diff --git a/ibmvstgt/src/ibmvstgt.c b/ibmvstgt/src/ibmvstgt.c index da0d3bfdc..c8a1c7d79 100644 --- a/ibmvstgt/src/ibmvstgt.c +++ b/ibmvstgt/src/ibmvstgt.c @@ -24,15 +24,14 @@ #include #include #include -#include -#include -#include #ifdef INSIDE_KERNEL_TREE #include +#include #else #include "scst.h" +#include "scst_debug.h" #endif -#include +#include "libsrpnew.h" /* */ #include #ifdef __powerpc__ #include @@ -80,12 +79,10 @@ struct vio_port { unsigned long liobn; unsigned long riobn; struct srp_target *target; - - struct srp_rport *rport; }; +static atomic_t ibmvstgt_device_count; static struct workqueue_struct *vtgtd; -static struct scsi_transport_template *ibmvstgt_transport_template; /* * These are fixed for the system and come from the Open Firmware device tree. @@ -146,7 +143,7 @@ static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format) #define SRP_RSP_SENSE_DATA_LEN 18 -static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, +static int send_rsp(struct iu_entry *iue, struct scst_cmd *sc, unsigned char status, unsigned char asc) { union viosrp_iu *iu = vio_iu(iue); @@ -175,9 +172,16 @@ static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, uint8_t *sense = iu->srp.rsp.data; if (sc) { + uint8_t *sc_sense; + int sense_data_len; + + sc_sense = scst_cmd_get_sense_buffer(sc); + sense_data_len = min(scst_cmd_get_sense_buffer_len(sc), + SRP_RSP_SENSE_DATA_LEN); iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; - memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); + iu->srp.rsp.sense_data_len + = cpu_to_be32(sense_data_len); + memcpy(sense, sc_sense, sense_data_len); } else { iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; @@ -203,12 +207,12 @@ static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, static void handle_cmd_queue(struct srp_target *target) { struct scst_session *sess = target->sess; - struct srp_rport *rport = target_to_port(target)->rport; struct iu_entry *iue; struct srp_cmd *cmd; unsigned long flags; int err; + BUG_ON(!sess); retry: spin_lock_irqsave(&target->lock, flags); @@ -216,8 +220,7 @@ retry: if (!test_and_set_bit(V_FLYING, &iue->flags)) { spin_unlock_irqrestore(&target->lock, flags); cmd = iue->sbuf->buf; - err = srp_cmd_queue(sess, cmd, iue, - (unsigned long)rport); + err = srp_cmd_queue(sess, cmd, iue); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue); @@ -229,11 +232,11 @@ retry: spin_unlock_irqrestore(&target->lock, flags); } -static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, +static int ibmvstgt_rdma(struct scst_cmd *sc, struct scatterlist *sg, int nsg, struct srp_direct_buf *md, int nmd, enum dma_data_direction dir, unsigned int rest) { - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); dma_addr_t token; @@ -292,34 +295,146 @@ static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, return 0; } -static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, - void (*done)(struct scsi_cmnd *)) +#if !defined(CONFIG_SCST_PROC) +/** + * ibmvstgt_enable_target() - Allows to enable a target via sysfs. + */ +static int ibmvstgt_enable_target(struct scst_tgt *scst_tgt, bool enable) +{ + struct srp_target *target = scst_tgt_get_tgt_priv(scst_tgt); + + EXTRACHECKS_WARN_ON_ONCE(irqs_disabled()); + + TRACE_DBG("%s target %s", enable ? "Enabling" : "Disabling", + target->sess ? target->sess->name : "???"); + + target->enabled = enable; + + return 0; +} + +/** + * ibmvstgt_is_target_enabled() - Allows to query a targets status via sysfs. + */ +static bool ibmvstgt_is_target_enabled(struct scst_tgt *scst_tgt) +{ + struct srp_target *target = scst_tgt_get_tgt_priv(scst_tgt); + + EXTRACHECKS_WARN_ON_ONCE(irqs_disabled()); + + return target->enabled; +} +#endif + +/** + * ibmvstgt_detect() - Returns the number of target adapters. + * + * Callback function called by the SCST core. + */ +static int ibmvstgt_detect(struct scst_tgt_template *tp) +{ + return atomic_read(&ibmvstgt_device_count); +} + +/** + * ibmvstgt_release() - Free the resources associated with an SCST target. + * + * Callback function called by the SCST core from scst_unregister_target(). + */ +static int ibmvstgt_release(struct scst_tgt *scst_tgt) +{ + /* To do: implement this function. */ + return 0; +} + +/** + * ibmvstgt_xmit_response() - Transmits the response to a SCSI command. + * + * Callback function called by the SCST core. Must not block. Must ensure that + * scst_tgt_cmd_done() will get invoked when returning SCST_TGT_RES_SUCCESS. + */ +static int ibmvstgt_xmit_response(struct scst_cmd *sc) +{ + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); + int ret = SCST_TGT_RES_SUCCESS; + enum dma_data_direction dir; + + if (unlikely(scst_cmd_aborted(sc))) { + scst_set_delivery_status(sc, SCST_CMD_DELIVERY_ABORTED); + goto out; + } + + dir = srp_cmd_direction(&vio_iu(iue)->srp.cmd); + WARN_ON(dir != DMA_FROM_DEVICE && dir != DMA_TO_DEVICE); + + /* For read commands, transfer the data to the initiator. */ + if (dir == DMA_FROM_DEVICE && scst_cmd_get_resp_data_len(sc)) { + ret = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, + ibmvstgt_rdma, 1, 1); + + if (ret != SCST_TGT_RES_SUCCESS) { + PRINT_ERROR("%s: tag= %llu xfer_data failed", + __func__, scst_cmd_get_tag(sc)); + scst_set_cmd_error(sc, + SCST_LOAD_SENSE(scst_sense_read_error)); + } + } + + send_rsp(iue, sc, scst_cmd_get_status(sc), 0); + +out: + scst_tgt_cmd_done(sc, SCST_CONTEXT_DIRECT); + + return SCST_TGT_RES_SUCCESS; +} + +/** + * ibmvstgt_rdy_to_xfer() - Transfers data from initiator to target. + * + * Called by the SCST core to transfer data from the initiator to the target + * (SCST_DATA_WRITE). Must not block. + */ +static int ibmvstgt_rdy_to_xfer(struct scst_cmd *sc) +{ + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); + int ret = SCST_TGT_RES_SUCCESS; + enum dma_data_direction dir; + + dir = srp_cmd_direction(&vio_iu(iue)->srp.cmd); + WARN_ON(dir != DMA_FROM_DEVICE && dir != DMA_TO_DEVICE); + + /* For write commands, transfer the data from the initiator. */ + if (dir == DMA_TO_DEVICE && scst_cmd_get_resp_data_len(sc)) { + ret = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, + ibmvstgt_rdma, 1, 1); + + if (ret != SCST_TGT_RES_SUCCESS) { + PRINT_ERROR("%s: tag= %llu xfer_data failed", + __func__, scst_cmd_get_tag(sc)); + scst_set_cmd_error(sc, + SCST_LOAD_SENSE(scst_sense_write_error)); + } + } + + return SCST_TGT_RES_SUCCESS; +} + +/** + * ibmvstgt_on_free_cmd() - Free command-private data. + * + * Called by the SCST core. May be called in IRQ context. + */ +static void ibmvstgt_on_free_cmd(struct scst_cmd *sc) { unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; + struct iu_entry *iue = scst_cmd_get_tgt_priv(sc); struct srp_target *target = iue->target; - int err = 0; - - dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], - scsi_sg_count(sc)); - - if (scsi_sg_count(sc)) - err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); spin_lock_irqsave(&target->lock, flags); list_del(&iue->ilist); spin_unlock_irqrestore(&target->lock, flags); - if (err|| sc->result != SAM_STAT_GOOD) { - eprintk("operation failed %p %d %x\n", - iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); - send_rsp(iue, sc, HARDWARE_ERROR, 0x00); - } else - send_rsp(iue, sc, NO_SENSE, 0x00); - - done(sc); srp_iu_put(iue); - return 0; } int send_adapter_info(struct iu_entry *iue, @@ -327,7 +442,6 @@ int send_adapter_info(struct iu_entry *iue, { struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); - struct scst_session *sess = target->sess; dma_addr_t data_token; struct mad_adapter_info_data *info; int err; @@ -355,7 +469,7 @@ int send_adapter_info(struct iu_entry *iue, info->partition_number = partition_number; info->mad_version = 1; info->os_type = 2; - info->port_max_txu[0] = sess->hostt->max_sectors << 9; + info->port_max_txu[0] = 255 << 9;/*sess->hostt->max_sectors << 9;*/ /* Send our info to remote */ err = h_copy_rdma(sizeof(*info), vport->liobn, data_token, @@ -375,31 +489,52 @@ static void process_login(struct iu_entry *iue) { union viosrp_iu *iu = vio_iu(iue); struct srp_login_rsp *rsp = &iu->srp.login_rsp; + struct srp_login_rej *rej = &iu->srp.login_rej; uint64_t tag = iu->srp.rsp.tag; - struct scst_session *sess = iue->target->sess; - struct srp_target *target = host_to_srp_target(sess); + struct scst_session *sess; + struct srp_target *target = iue->target; struct vio_port *vport = target_to_port(target); - struct srp_rport_identifiers ids; + char name[16]; - memset(&ids, 0, sizeof(ids)); - sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); - ids.roles = SRP_RPORT_ROLE_INITIATOR; - if (!vport->rport) - vport->rport = srp_rport_add(sess, &ids); + BUG_ON(target->sess); + + memset(iu, 0, max(sizeof *rsp, sizeof *rej)); + + snprintf(name, sizeof(name), "%x", vport->dma_dev->unit_address); + + BUG_ON(!target); + sess = scst_register_session(target->tgt, 0, name, target, NULL, NULL); + if (!sess) { + rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES); + TRACE_DBG("%s", "Failed to create SCST session"); + goto reject; + } + + target->sess = sess; /* TODO handle case that requested size is wrong and * buffer format is wrong */ - memset(iu, 0, sizeof(struct srp_login_rsp)); rsp->opcode = SRP_LOGIN_RSP; rsp->req_lim_delta = INITIAL_SRP_LIMIT; rsp->tag = tag; rsp->max_it_iu_len = sizeof(union srp_iu); rsp->max_ti_iu_len = sizeof(union srp_iu); /* direct and indirect */ - rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; + rsp->buf_fmt + = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); + + return; + +reject: + rej->opcode = SRP_LOGIN_REJ; + rej->tag = tag; + rej->buf_fmt = + cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); + + send_iu(iue, sizeof *rsp, VIOSRP_SRP_FORMAT); } static inline void queue_cmd(struct iu_entry *iue) @@ -412,44 +547,131 @@ static inline void queue_cmd(struct iu_entry *iue) spin_unlock_irqrestore(&target->lock, flags); } +/** + * struct mgmt_ctx - management command context information. + * @iue: VIO SRP information unit associated with the management command. + * @sess: SCST session via which the management command has been received. + * @tag: SCSI tag of the management command. + */ +struct mgmt_ctx { + struct iu_entry *iue; + struct scst_session *sess; +}; + static int process_tsk_mgmt(struct iu_entry *iue) { union viosrp_iu *iu = vio_iu(iue); struct scst_session *sess = iue->target->sess; - int fn; + struct srp_tsk_mgmt *srp_tsk; + struct mgmt_ctx *mgmt_ctx; + int ret = 0; - dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); + srp_tsk = &iu->srp.tsk_mgmt; - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { + dprintk("%p %u\n", iue, srp_tsk->tsk_mgmt_func); + + ret = SCST_MGMT_STATUS_FAILED; + mgmt_ctx = kmalloc(sizeof *mgmt_ctx, GFP_ATOMIC); + if (!mgmt_ctx) + goto err; + + mgmt_ctx->iue = iue; + mgmt_ctx->sess = sess; + iu->srp.rsp.tag = srp_tsk->tag; + + switch (srp_tsk->tsk_mgmt_func) { case SRP_TSK_ABORT_TASK: - fn = ABORT_TASK; + ret = scst_rx_mgmt_fn_tag(sess, SCST_ABORT_TASK, + srp_tsk->task_tag, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_ABORT_TASK_SET: - fn = ABORT_TASK_SET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_ABORT_TASK_SET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_CLEAR_TASK_SET: - fn = CLEAR_TASK_SET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_CLEAR_TASK_SET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_LUN_RESET: - fn = LOGICAL_UNIT_RESET; + ret = scst_rx_mgmt_fn_lun(sess, SCST_LUN_RESET, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; case SRP_TSK_CLEAR_ACA: - fn = CLEAR_ACA; + ret = scst_rx_mgmt_fn_lun(sess, SCST_CLEAR_ACA, + (u8 *) &srp_tsk->lun, + sizeof srp_tsk->lun, + SCST_ATOMIC, mgmt_ctx); break; default: - fn = 0; + ret = SCST_MGMT_STATUS_FN_NOT_SUPPORTED; } - if (fn) - scsi_tgt_tsk_mgmt_request(sess, - (unsigned long)sess, - fn, - iu->srp.tsk_mgmt.task_tag, - (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, - iue); - else - send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); - return !fn; + if (ret != SCST_MGMT_STATUS_SUCCESS) + goto err; + return ret; + +err: + kfree(mgmt_ctx); + return ret; +} + +enum { + /* See also table 24 in the T10 r16a document. */ + SRP_TSK_MGMT_SUCCESS = 0x00, + SRP_TSK_MGMT_FUNC_NOT_SUPP = 0x04, + SRP_TSK_MGMT_FAILED = 0x05, +}; + +static u8 scst_to_srp_tsk_mgmt_status(const int scst_mgmt_status) +{ + switch (scst_mgmt_status) { + case SCST_MGMT_STATUS_SUCCESS: + return SRP_TSK_MGMT_SUCCESS; + case SCST_MGMT_STATUS_FN_NOT_SUPPORTED: + return SRP_TSK_MGMT_FUNC_NOT_SUPP; + case SCST_MGMT_STATUS_TASK_NOT_EXIST: + case SCST_MGMT_STATUS_LUN_NOT_EXIST: + case SCST_MGMT_STATUS_REJECTED: + case SCST_MGMT_STATUS_FAILED: + default: + break; + } + return SRP_TSK_MGMT_FAILED; +} + +static void ibmvstgt_tsk_mgmt_done(struct scst_mgmt_cmd *mcmnd) +{ + struct mgmt_ctx *mgmt_ctx; + struct scst_session *sess; + struct iu_entry *iue; + union viosrp_iu *iu; + + mgmt_ctx = scst_mgmt_cmd_get_tgt_priv(mcmnd); + BUG_ON(!mgmt_ctx); + + sess = mgmt_ctx->sess; + BUG_ON(!sess); + + iue = mgmt_ctx->iue; + BUG_ON(!iue); + + iu = vio_iu(iue); + + TRACE_DBG("%s: tsk_mgmt_done for tag= %lld status=%d", + __func__, mgmt_ctx->tag, scst_mgmt_cmd_get_status(mcmnd)); + + send_rsp(iue, NULL, + scst_to_srp_tsk_mgmt_status(scst_mgmt_cmd_get_status(mcmnd)), + 0/*asc*/); + + kfree(mgmt_ctx); } static int process_mad_iu(struct iu_entry *iue) @@ -485,10 +707,10 @@ static int process_mad_iu(struct iu_entry *iue) return 1; } -static int process_srp_iu(struct iu_entry *iue) +static bool process_srp_iu(struct iu_entry *iue) { union viosrp_iu *iu = vio_iu(iue); - int done = 1; + bool done = true; u8 opcode = iu->srp.rsp.opcode; switch (opcode) { @@ -496,7 +718,7 @@ static int process_srp_iu(struct iu_entry *iue) process_login(iue); break; case SRP_TSK_MGMT: - done = process_tsk_mgmt(iue); + done = process_tsk_mgmt(iue) != SCST_MGMT_STATUS_SUCCESS; break; case SRP_CMD: queue_cmd(iue); @@ -733,65 +955,6 @@ static void handle_crq(struct work_struct *work) handle_cmd_queue(target); } - -static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - - dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_tsk_mgmt_response(struct scst_session *sess, - u64 itn_id, u64 mid, int result) -{ - struct iu_entry *iue = (struct iu_entry *) ((void *) mid); - union viosrp_iu *iu = vio_iu(iue); - unsigned char status, asc; - - eprintk("%p %d\n", iue, result); - status = NO_SENSE; - asc = 0; - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - asc = 0x14; - if (result) - status = ABORTED_COMMAND; - break; - default: - break; - } - - send_rsp(iue, NULL, status, asc); - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_it_nexus_response(struct scst_session *sess, u64 itn_id, - int result) -{ - struct srp_target *target = host_to_srp_target(sess); - struct vio_port *vport = target_to_port(target); - - if (result) { - eprintk("%p %d\n", sess, result); - srp_rport_del(vport->rport); - vport->rport = NULL; - } - return 0; -} - static ssize_t system_id_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -807,40 +970,54 @@ static ssize_t partition_number_show(struct device *dev, static ssize_t unit_address_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct scst_session *sess = class_to_shost(dev); - struct srp_target *target = host_to_srp_target(sess); + struct srp_target *target = container_of(dev, struct srp_target, dev2); struct vio_port *vport = target_to_port(target); return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); } -static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); -static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); -static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); - -static struct device_attribute *ibmvstgt_attrs[] = { - &dev_attr_system_id, - &dev_attr_partition_number, - &dev_attr_unit_address, - NULL, +static struct class_attribute ibmvstgt_class_attrs[] = { + __ATTR_NULL, }; -static struct scsi_host_template ibmvstgt_sht = { +static struct device_attribute ibmvstgt_attrs[] = { + __ATTR(system_id, S_IRUGO, system_id_show, NULL), + __ATTR(partition_number, S_IRUGO, partition_number_show, NULL), + __ATTR(unit_address, S_IRUGO, unit_address_show, NULL), + __ATTR_NULL, +}; + +static void ibmvstgt_dev_release(struct device *dev) +{ } + +static struct class ibmvstgt_class = { + .name = "ibmvstgt", + .dev_release = ibmvstgt_dev_release, + .class_attrs = ibmvstgt_class_attrs, + .dev_attrs = ibmvstgt_attrs, +}; + +static struct scst_tgt_template ibmvstgt_template = { .name = TGT_NAME, - .module = THIS_MODULE, - .can_queue = INITIAL_SRP_LIMIT, - .sg_tablesize = SG_ALL, - .use_clustering = DISABLE_CLUSTERING, - .max_sectors = DEFAULT_MAX_SECTORS, - .transfer_response = ibmvstgt_cmd_done, - .eh_abort_handler = ibmvstgt_eh_abort_handler, - .shost_attrs = ibmvstgt_attrs, - .proc_name = TGT_NAME, - .supported_mode = MODE_TARGET, + .sg_tablesize = SCSI_MAX_SG_SEGMENTS, +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags = DEFAULT_IBMVSTGT_TRACE_FLAGS, + .trace_flags = &trace_flag, +#endif +#if !defined(CONFIG_SCST_PROC) + .enable_target = ibmvstgt_enable_target, + .is_target_enabled = ibmvstgt_is_target_enabled, +#endif + .detect = ibmvstgt_detect, + .release = ibmvstgt_release, + .xmit_response = ibmvstgt_xmit_response, + .rdy_to_xfer = ibmvstgt_rdy_to_xfer, + .on_free_cmd = ibmvstgt_on_free_cmd, + .task_mgmt_fn_done = ibmvstgt_tsk_mgmt_done, }; static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) { - struct scst_session *sess; + struct scst_tgt *scst_tgt; struct srp_target *target; struct vio_port *vport; unsigned int *dma, dma_size; @@ -849,20 +1026,24 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); if (!vport) return err; - sess = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); - if (!sess) - goto free_vport; - sess->transportt = ibmvstgt_transport_template; - target = host_to_srp_target(sess); - target->sess = sess; + target = kzalloc(sizeof(struct srp_target), GFP_KERNEL); + if (!target) + goto free_vport; + + scst_tgt = scst_register_target(&ibmvstgt_template, NULL); + if (!scst_tgt) + goto free_target; + + scst_tgt_set_tgt_priv(scst_tgt, target); + target->tgt = scst_tgt; vport->dma_dev = dev; target->ldata = vport; vport->target = target; err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, SRP_MAX_IU_LEN); if (err) - goto put_host; + goto unregister_target; dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", &dma_size); @@ -876,31 +1057,27 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) INIT_WORK(&vport->crq_work, handle_crq); - err = scsi_add_host(sess, target->dev); + err = crq_queue_create(&vport->crq_queue, target); if (err) goto free_srp_target; -#if 0 - err = scsi_tgt_alloc_queue(sess); - if (err) - goto remove_host; -#endif + target->dev2.class = &ibmvstgt_class; + target->dev2.parent = &dev->dev; + dev_set_name(&target->dev2, "ibmvstgt-%d", + vport->dma_dev->unit_address); + if (device_register(&target->dev2)) + /* to do: handle failure */; - err = crq_queue_create(&vport->crq_queue, target); - if (err) - goto free_queue; + atomic_inc(&ibmvstgt_device_count); return 0; -free_queue: -#if 0 - scsi_tgt_free_queue(sess); -remove_host: -#endif - scsi_remove_host(sess); + free_srp_target: srp_target_free(target); -put_host: - scsi_host_put(sess); +unregister_target: + scst_unregister_target(scst_tgt); +free_target: + kfree(target); free_vport: kfree(vport); return err; @@ -909,18 +1086,15 @@ free_vport: static int ibmvstgt_remove(struct vio_dev *dev) { struct srp_target *target = dev_get_drvdata(&dev->dev); - struct scst_session *sess = target->sess; struct vio_port *vport = target->ldata; + atomic_dec(&ibmvstgt_device_count); + crq_queue_destroy(target); - srp_remove_host(sess); - scsi_remove_host(sess); -#if 0 - scsi_tgt_free_queue(sess); -#endif srp_target_free(target); + scst_unregister_target(target->tgt); + kfree(target); kfree(vport); - scsi_host_put(sess); return 0; } @@ -968,25 +1142,15 @@ static int get_system_info(void) return 0; } -static struct srp_function_template ibmvstgt_transport_functions = { - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, - .it_nexus_response = ibmvstgt_it_nexus_response, -}; - static int ibmvstgt_init(void) { int err = -ENOMEM; printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); - ibmvstgt_transport_template = - srp_attach_transport(&ibmvstgt_transport_functions); - if (!ibmvstgt_transport_template) - return err; - vtgtd = create_workqueue("ibmvtgtd"); if (!vtgtd) - goto release_transport; + return err; err = get_system_info(); if (err) @@ -999,8 +1163,6 @@ static int ibmvstgt_init(void) return 0; destroy_wq: destroy_workqueue(vtgtd); -release_transport: - srp_release_transport(ibmvstgt_transport_template); return err; } @@ -1010,7 +1172,6 @@ static void ibmvstgt_exit(void) destroy_workqueue(vtgtd); vio_unregister_driver(&ibmvstgt_driver); - srp_release_transport(ibmvstgt_transport_template); } MODULE_DESCRIPTION("IBM Virtual SCSI Target"); diff --git a/ibmvstgt/src/libsrpnew.c b/ibmvstgt/src/libsrpnew.c index 0072ff143..668771afc 100644 --- a/ibmvstgt/src/libsrpnew.c +++ b/ibmvstgt/src/libsrpnew.c @@ -23,17 +23,8 @@ #include #include #include -#include -#include -#include -#include #include #include "libsrpnew.h" -#ifdef INSIDE_KERNEL_TREE -#include -#else -#include "scst.h" -#endif enum srp_task_attributes { SRP_SIMPLE_TASK = 0, @@ -190,7 +181,7 @@ void srp_iu_put(struct iu_entry *iue) } EXPORT_SYMBOL_GPL(srp_iu_put); -static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, +static int srp_direct_data(struct scst_cmd *sc, struct srp_direct_buf *md, enum dma_data_direction dir, srp_rdma_t rdma_io, int dma_map, int ext_desc) { @@ -199,19 +190,21 @@ static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, int err, nsg = 0, len; if (dma_map) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); + iue = scst_cmd_get_tgt_priv(sc); + sg = scst_cmd_get_sg(sc); dprintk("%p %u %u %d\n", iue, scsi_bufflen(sc), - md->len, scsi_sg_count(sc)); + md->len, scst_cmd_get_sg_cnt(sc)); - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), + nsg = dma_map_sg(iue->target->dev, sg, scst_cmd_get_sg_cnt(sc), DMA_BIDIRECTIONAL); if (!nsg) { - printk("fail to map %p %d\n", iue, scsi_sg_count(sc)); + printk(KERN_ERR "fail to map %p %d\n", iue, + scst_cmd_get_sg_cnt(sc)); return 0; } - len = min(scsi_bufflen(sc), md->len); + len = min_t(int, scst_cmd_get_expected_transfer_len(sc), + md->len); } else len = md->len; @@ -223,7 +216,7 @@ static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, return err; } -static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, +static int srp_indirect_data(struct scst_cmd *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) @@ -236,8 +229,8 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, int nmd, nsg = 0, len; if (dma_map || ext_desc) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); + iue = scst_cmd_get_tgt_priv(sc); + sg = scst_cmd_get_sg(sc); dprintk("%p %u %u %d %d\n", iue, scsi_bufflen(sc), id->len, @@ -276,14 +269,16 @@ static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, rdma: if (dma_map) { - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), + nsg = dma_map_sg(iue->target->dev, sg, scst_cmd_get_sg_cnt(sc), DMA_BIDIRECTIONAL); if (!nsg) { - eprintk("fail to map %p %d\n", iue, scsi_sg_count(sc)); + eprintk("fail to map %p %d\n", iue, + scst_cmd_get_sg_cnt(sc)); err = -EIO; goto free_mem; } - len = min(scsi_bufflen(sc), id->len); + len = min_t(int, scst_cmd_get_expected_transfer_len(sc), + id->len); } else len = id->len; @@ -325,7 +320,7 @@ static int data_out_desc_size(struct srp_cmd *cmd) * 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, +int srp_transfer_data(struct scst_cmd *sc, struct srp_cmd *cmd, srp_rdma_t rdma_io, int dma_map, int ext_desc) { struct srp_direct_buf *md; @@ -400,8 +395,7 @@ static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) return len; } -int srp_cmd_queue(struct scst_session *sess, struct srp_cmd *cmd, void *info, - u64 itn_id) +int srp_cmd_queue(struct scst_session *sess, struct srp_cmd *cmd, void *info) { enum dma_data_direction dir; struct scst_cmd *sc; @@ -432,15 +426,15 @@ int srp_cmd_queue(struct scst_session *sess, struct srp_cmd *cmd, void *info, cmd->lun, dir, len, tag, (unsigned long long) cmd->tag); sc = scst_rx_cmd(sess, (u8 *) &cmd->lun, sizeof(cmd->lun), - cmd->cdb, 16, SCST_CONTEXT_THREAD); + cmd->cdb, sizeof(cmd->cdb), SCST_CONTEXT_THREAD); if (!sc) return -ENOMEM; scst_cmd_set_queue_type(sc, tag); + scst_cmd_set_tag(sc, cmd->tag); + scst_cmd_set_tgt_priv(sc, info); scst_cmd_set_expected(sc, dir == DMA_TO_DEVICE ? SCST_DATA_WRITE : SCST_DATA_READ, len); - scst_cmd_set_tgt_priv(sc, info); - scst_cmd_set_tag(sc, itn_id); scst_cmd_init_done(sc, SCST_CONTEXT_THREAD); return 0; diff --git a/ibmvstgt/src/libsrpnew.h b/ibmvstgt/src/libsrpnew.h index 2ce0d2444..7a35b9283 100644 --- a/ibmvstgt/src/libsrpnew.h +++ b/ibmvstgt/src/libsrpnew.h @@ -3,9 +3,12 @@ #include #include -#include -#include #include +#ifdef INSIDE_KERNEL_TREE +#include +#else +#include "scst.h" +#endif enum iue_flags { V_DIOVER, @@ -29,8 +32,10 @@ struct srp_queue { }; struct srp_target { + struct scst_tgt *tgt; struct scst_session *sess; - struct device *dev; + struct device *dev; /* to do: invent a better name */ + struct device dev2; /* to do: invent a better name */ spinlock_t lock; struct list_head cmd_queue; @@ -41,6 +46,8 @@ struct srp_target { struct srp_buf **rx_ring; void *ldata; + + bool enabled; }; struct iu_entry { @@ -53,7 +60,7 @@ struct iu_entry { struct srp_buf *sbuf; }; -typedef int (srp_rdma_t)(struct scsi_cmnd *, struct scatterlist *, int, +typedef int (srp_rdma_t)(struct scst_cmd *, struct scatterlist *, int, struct srp_direct_buf *, int, enum dma_data_direction, unsigned int); extern int srp_target_alloc(struct srp_target *, struct device *, size_t, size_t); @@ -62,16 +69,11 @@ extern void srp_target_free(struct srp_target *); extern struct iu_entry *srp_iu_get(struct srp_target *); extern void srp_iu_put(struct iu_entry *); -extern int srp_cmd_queue(struct scst_session *, struct srp_cmd *, void *, u64); -extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, +extern int srp_cmd_queue(struct scst_session *, struct srp_cmd *, void *); +extern int srp_transfer_data(struct scst_cmd *, struct srp_cmd *, srp_rdma_t, int, int); -static inline struct srp_target *host_to_srp_target(struct Scsi_Host *host) -{ - return (struct srp_target *) host->hostdata; -} - static inline int srp_cmd_direction(struct srp_cmd *cmd) { return (cmd->buf_fmt >> 4) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;