]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'target-updates/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 6 Sep 2012 02:26:36 +0000 (12:26 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 6 Sep 2012 02:26:36 +0000 (12:26 +1000)
1  2 
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_sess.c
drivers/vhost/tcm_vhost.c

index 9e1449f8c6a26ea62349352de3f8178db2faa6fe,2c4cf64751c818f57a6fb06f97c597166c21ecd4..cf23c46185b25e8024c5a3e8e90d856bfc3ab1bc
@@@ -1469,7 -1469,7 +1469,7 @@@ static void srpt_handle_send_comp(struc
   *
   * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping
   * the data that has been transferred via IB RDMA had to be postponed until the
 - * check_stop_free() callback.  None of this is nessecary anymore and needs to
 + * check_stop_free() callback.  None of this is necessary anymore and needs to
   * be cleaned up.
   */
  static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
@@@ -3564,16 -3564,6 +3564,6 @@@ static int srpt_get_tcm_cmd_state(struc
        return srpt_get_cmd_state(ioctx);
  }
  
- static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)
- {
-       return 0;
- }
- static u16 srpt_get_fabric_sense_len(void)
- {
-       return 0;
- }
  /**
   * srpt_parse_i_port_id() - Parse an initiator port ID.
   * @name: ASCII representation of a 128-bit initiator port ID.
@@@ -3953,8 -3943,6 +3943,6 @@@ static struct target_core_fabric_ops sr
        .queue_data_in                  = srpt_queue_response,
        .queue_status                   = srpt_queue_status,
        .queue_tm_rsp                   = srpt_queue_response,
-       .get_fabric_sense_len           = srpt_get_fabric_sense_len,
-       .set_fabric_sense_len           = srpt_set_fabric_sense_len,
        /*
         * Setup function pointers for generic logic in
         * target_core_fabric_configfs.c
index 5552fa7426bc9b317da906dec2e395bbf854ae78,5ff2d92551b05dfc5fcbe5e8a9fcf3c204277041..dc455bc0d8eef7c919ba42b534cfb139c7e7b96b
@@@ -264,7 -264,7 +264,7 @@@ pscsi_get_inquiry_vpd_device_ident(stru
                                        " length zero!\n");
                        break;
                }
-               pr_debug("T10 VPD Identifer Length: %d\n", ident_len);
+               pr_debug("T10 VPD Identifier Length: %d\n", ident_len);
  
                vpd = kzalloc(sizeof(struct t10_vpd), GFP_KERNEL);
                if (!vpd) {
@@@ -673,15 -673,8 +673,15 @@@ static int pscsi_transport_complete(str
        struct scsi_device *sd = pdv->pdv_sd;
        int result;
        struct pscsi_plugin_task *pt = cmd->priv;
 -      unsigned char *cdb = &pt->pscsi_cdb[0];
 +      unsigned char *cdb;
 +      /*
 +       * Special case for REPORT_LUNs handling where pscsi_plugin_task has
 +       * not been allocated because TCM is handling the emulation directly.
 +       */
 +      if (!pt)
 +              return 0;
  
 +      cdb = &pt->pscsi_cdb[0];
        result = pt->pscsi_result;
        /*
         * Hack to make sure that Write-Protect modepage is set if R/O mode is
index 4de3186dc44e99672d3666a24ec145e058183691,7182c43bcdba1406716602a5ad9fdd24a615a1d5..878ef5c17b6853a04ff8ba796f1f45033b2ab2c9
@@@ -55,8 -55,6 +55,6 @@@
  #include "target_core_pr.h"
  #include "target_core_ua.h"
  
- static int sub_api_initialized;
  static struct workqueue_struct *target_completion_wq;
  static struct kmem_cache *se_sess_cache;
  struct kmem_cache *se_ua_cache;
@@@ -195,6 -193,7 +193,7 @@@ u32 scsi_get_new_index(scsi_index_t typ
  void transport_subsystem_check_init(void)
  {
        int ret;
+       static int sub_api_initialized;
  
        if (sub_api_initialized)
                return;
        if (ret != 0)
                pr_err("Unable to load target_core_pscsi\n");
  
-       ret = request_module("target_core_stgt");
-       if (ret != 0)
-               pr_err("Unable to load target_core_stgt\n");
        sub_api_initialized = 1;
-       return;
  }
  
  struct se_session *transport_init_session(void)
@@@ -941,7 -935,7 +935,7 @@@ in
  transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
  {
        static const char hex_str[] = "0123456789abcdef";
-       int j = 0, i = 4; /* offset to start of the identifer */
+       int j = 0, i = 4; /* offset to start of the identifier */
  
        /*
         * The VPD Code Set (encoding)
@@@ -1165,6 -1159,8 +1159,6 @@@ int target_cmd_size_check(struct se_cm
                        " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
                                cmd->data_length, size, cmd->t_task_cdb[0]);
  
 -              cmd->cmd_spdtl = size;
 -
                if (cmd->data_direction == DMA_TO_DEVICE) {
                        pr_err("Rejecting underflow/overflow"
                                        " WRITE data\n");
@@@ -1823,7 -1819,6 +1817,6 @@@ static int transport_get_sense_data(str
        unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
        struct se_device *dev = cmd->se_dev;
        unsigned long flags;
-       u32 offset = 0;
  
        WARN_ON(!cmd->se_lun);
  
  
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
  
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
-       /* Automatically padded */
-       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
+       memcpy(buffer, sense_buffer, TRANSPORT_SENSE_BUFFER);
+       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
  
        pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
                dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
@@@ -2292,9 -2283,9 +2281,9 @@@ transport_generic_get_mem(struct se_cm
        return 0;
  
  out:
 -      while (i >= 0) {
 -              __free_page(sg_page(&cmd->t_data_sg[i]));
 +      while (i > 0) {
                i--;
 +              __free_page(sg_page(&cmd->t_data_sg[i]));
        }
        kfree(cmd->t_data_sg);
        cmd->t_data_sg = NULL;
@@@ -2321,12 -2312,9 +2310,12 @@@ int transport_generic_new_cmd(struct se
                if (ret < 0)
                        goto out_fail;
        }
 -
 -      /* Workaround for handling zero-length control CDBs */
 -      if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) {
 +      /*
 +       * If this command doesn't have any payload and we don't have to call
 +       * into the fabric for data transfers, go ahead and complete it right
 +       * away.
 +       */
 +      if (!cmd->data_length) {
                spin_lock_irq(&cmd->t_state_lock);
                cmd->t_state = TRANSPORT_COMPLETE;
                cmd->transport_state |= CMD_T_ACTIVE;
@@@ -2797,7 -2785,7 +2786,7 @@@ bool transport_wait_for_tasks(struct se
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP);
  
-       pr_debug("wait_for_tasks: Stopped wait_for_compltion("
+       pr_debug("wait_for_tasks: Stopped wait_for_completion("
                "&cmd->t_transport_stop_comp) for ITT: 0x%08x\n",
                cmd->se_tfo->get_task_tag(cmd));
  
@@@ -2836,7 -2824,6 +2825,6 @@@ int transport_send_check_condition_and_
  {
        unsigned char *buffer = cmd->sense_buffer;
        unsigned long flags;
-       int offset;
        u8 asc = 0, ascq = 0;
  
        spin_lock_irqsave(&cmd->t_state_lock, flags);
  
        if (!from_transport)
                cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE;
-       /*
-        * Data Segment and SenseLength of the fabric response PDU.
-        *
-        * TRANSPORT_SENSE_BUFFER is now set to SCSI_SENSE_BUFFERSIZE
-        * from include/scsi/scsi_cmnd.h
-        */
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd,
-                               TRANSPORT_SENSE_BUFFER);
        /*
         * Actual SENSE DATA, see SPC-3 7.23.2  SPC_SENSE_KEY_OFFSET uses
         * SENSE KEY values from include/scsi/scsi.h
        switch (reason) {
        case TCM_NON_EXISTENT_LUN:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT NOT SUPPORTED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x25;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x25;
                break;
        case TCM_UNSUPPORTED_SCSI_OPCODE:
        case TCM_SECTOR_COUNT_TOO_MANY:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID COMMAND OPERATION CODE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x20;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x20;
                break;
        case TCM_UNKNOWN_MODE_PAGE:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x24;
                break;
        case TCM_CHECK_CONDITION_ABORT_CMD:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* BUS DEVICE RESET FUNCTION OCCURRED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x29;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x03;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x29;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
                break;
        case TCM_INCORRECT_AMOUNT_OF_DATA:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
                /* NOT ENOUGH UNSOLICITED DATA */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x0d;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x0d;
                break;
        case TCM_INVALID_CDB_FIELD:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN CDB */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x24;
                break;
        case TCM_INVALID_PARAMETER_LIST:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* INVALID FIELD IN PARAMETER LIST */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x26;
                break;
        case TCM_UNEXPECTED_UNSOLICITED_DATA:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* WRITE ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
                /* UNEXPECTED_UNSOLICITED_DATA */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x0c;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x0c;
                break;
        case TCM_SERVICE_CRC_ERROR:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* PROTOCOL SERVICE CRC ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x47;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x47;
                /* N/A */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x05;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x05;
                break;
        case TCM_SNACK_REJECTED:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ABORTED COMMAND */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+               buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
                /* READ ERROR */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x11;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x11;
                /* FAILED RETRANSMISSION REQUEST */
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = 0x13;
+               buffer[SPC_ASCQ_KEY_OFFSET] = 0x13;
                break;
        case TCM_WRITE_PROTECTED:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* DATA PROTECT */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
+               buffer[SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
                /* WRITE PROTECTED */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x27;
                break;
        case TCM_ADDRESS_OUT_OF_RANGE:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x21;
                break;
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* UNIT ATTENTION */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
+               buffer[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
                core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
-               buffer[offset+SPC_ASC_KEY_OFFSET] = asc;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = ascq;
+               buffer[SPC_ASC_KEY_OFFSET] = asc;
+               buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
                break;
        case TCM_CHECK_CONDITION_NOT_READY:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* Not Ready */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = NOT_READY;
+               buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
                transport_get_sense_codes(cmd, &asc, &ascq);
-               buffer[offset+SPC_ASC_KEY_OFFSET] = asc;
-               buffer[offset+SPC_ASCQ_KEY_OFFSET] = ascq;
+               buffer[SPC_ASC_KEY_OFFSET] = asc;
+               buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
                break;
        case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
        default:
                /* CURRENT ERROR */
-               buffer[offset] = 0x70;
-               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               buffer[0] = 0x70;
+               buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
                /* ILLEGAL REQUEST */
-               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
                /* LOGICAL UNIT COMMUNICATION FAILURE */
-               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x80;
+               buffer[SPC_ASC_KEY_OFFSET] = 0x80;
                break;
        }
        /*
         * Automatically padded, this value is encoded in the fabric's
         * data_length response PDU containing the SCSI defined sense data.
         */
-       cmd->scsi_sense_length  = TRANSPORT_SENSE_BUFFER + offset;
+       cmd->scsi_sense_length  = TRANSPORT_SENSE_BUFFER;
  
  after_reason:
        return cmd->se_tfo->queue_status(cmd);
index 823e6922249d07e3122973ebdb370cd4994704a0,4d44ad34e99e1c67a7f5f3f13efae0eec4b001a1..b406f178ff390663951ff4915824b67acdfe31b2
@@@ -19,7 -19,6 +19,6 @@@
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
- #include <generated/utsrelease.h>
  #include <linux/utsname.h>
  #include <linux/init.h>
  #include <linux/slab.h>
@@@ -48,7 -47,7 +47,7 @@@
  /*
   * Dump cmd state for debugging.
   */
 -void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
 +static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
  {
        struct fc_exch *ep;
        struct fc_seq *sp;
        }
  }
  
 +void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
 +{
 +      if (unlikely(ft_debug_logging))
 +              _ft_dump_cmd(cmd, caller);
 +}
 +
  static void ft_free_cmd(struct ft_cmd *cmd)
  {
        struct fc_frame *fp;
index 3c9e5b57caabea23567192e2d2f85843ca6bc70f,a0e3cee3f6c858b85a56f79082679f204bddf29a..9585010964ecad04727a4561d925ac55a9412c6b
@@@ -19,7 -19,6 +19,6 @@@
  
  #include <linux/module.h>
  #include <linux/moduleparam.h>
- #include <generated/utsrelease.h>
  #include <linux/utsname.h>
  #include <linux/init.h>
  #include <linux/slab.h>
@@@ -456,9 -455,7 +455,9 @@@ static void ft_prlo(struct fc_rport_pri
        struct ft_tport *tport;
  
        mutex_lock(&ft_lport_lock);
 -      tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]);
 +      tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP],
 +                                        lockdep_is_held(&ft_lport_lock));
 +
        if (!tport) {
                mutex_unlock(&ft_lport_lock);
                return;
index ed8e2e6c8df28715455c7ac09423ef447115e976,dce9c0ca8934a0a8539528fa2257d9207a646ec0..89dc99baca806bc36e2589da8cf263cf1a81e663
  #include "vhost.h"
  #include "tcm_vhost.h"
  
 +enum {
 +      VHOST_SCSI_VQ_CTL = 0,
 +      VHOST_SCSI_VQ_EVT = 1,
 +      VHOST_SCSI_VQ_IO = 2,
 +};
 +
  struct vhost_scsi {
 -      atomic_t vhost_ref_cnt;
 -      struct tcm_vhost_tpg *vs_tpg;
 +      struct tcm_vhost_tpg *vs_tpg;   /* Protected by vhost_scsi->dev.mutex */
        struct vhost_dev dev;
        struct vhost_virtqueue vqs[3];
  
@@@ -136,7 -131,8 +136,7 @@@ static u32 tcm_vhost_get_default_depth(
        return 1;
  }
  
 -static u32 tcm_vhost_get_pr_transport_id(
 -      struct se_portal_group *se_tpg,
 +static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg,
        struct se_node_acl *se_nacl,
        struct t10_pr_registration *pr_reg,
        int *format_code,
                        format_code, buf);
  }
  
 -static u32 tcm_vhost_get_pr_transport_id_len(
 -      struct se_portal_group *se_tpg,
 +static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg,
        struct se_node_acl *se_nacl,
        struct t10_pr_registration *pr_reg,
        int *format_code)
                        format_code);
  }
  
 -static char *tcm_vhost_parse_pr_out_transport_id(
 -      struct se_portal_group *se_tpg,
 +static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg,
        const char *buf,
        u32 *out_tid_len,
        char **port_nexus_ptr)
@@@ -238,7 -236,8 +238,7 @@@ static struct se_node_acl *tcm_vhost_al
        return &nacl->se_node_acl;
  }
  
 -static void tcm_vhost_release_fabric_acl(
 -      struct se_portal_group *se_tpg,
 +static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg,
        struct se_node_acl *se_nacl)
  {
        struct tcm_vhost_nacl *nacl = container_of(se_nacl,
@@@ -298,16 -297,7 +298,16 @@@ static int tcm_vhost_get_cmd_state(stru
        return 0;
  }
  
 -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *);
 +static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd)
 +{
 +      struct vhost_scsi *vs = tv_cmd->tvc_vhost;
 +
 +      spin_lock_bh(&vs->vs_completion_lock);
 +      list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list);
 +      spin_unlock_bh(&vs->vs_completion_lock);
 +
 +      vhost_work_queue(&vs->dev, &vs->vs_completion_work);
 +}
  
  static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd)
  {
@@@ -330,17 -320,6 +330,6 @@@ static int tcm_vhost_queue_tm_rsp(struc
        return 0;
  }
  
- static u16 tcm_vhost_set_fabric_sense_len(struct se_cmd *se_cmd,
-       u32 sense_length)
- {
-       return 0;
- }
- static u16 tcm_vhost_get_fabric_sense_len(void)
- {
-       return 0;
- }
  static void vhost_scsi_free_cmd(struct tcm_vhost_cmd *tv_cmd)
  {
        struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
@@@ -391,7 -370,7 +380,7 @@@ static void vhost_scsi_complete_cmd_wor
                                        vs_completion_work);
        struct tcm_vhost_cmd *tv_cmd;
  
 -      while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs)) != NULL) {
 +      while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) {
                struct virtio_scsi_cmd_resp v_rsp;
                struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd;
                int ret;
        vhost_signal(&vs->dev, &vs->vqs[2]);
  }
  
 -static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd)
 -{
 -      struct vhost_scsi *vs = tv_cmd->tvc_vhost;
 -
 -      pr_debug("%s tv_cmd %p\n", __func__, tv_cmd);
 -
 -      spin_lock_bh(&vs->vs_completion_lock);
 -      list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list);
 -      spin_unlock_bh(&vs->vs_completion_lock);
 -
 -      vhost_work_queue(&vs->dev, &vs->vs_completion_work);
 -}
 -
  static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
        struct tcm_vhost_tpg *tv_tpg,
        struct virtio_scsi_cmd_req *v_req,
@@@ -530,8 -522,8 +519,8 @@@ static int vhost_scsi_map_iov_to_sgl(st
        sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC);
        if (!sg)
                return -ENOMEM;
 -      pr_debug("%s sg %p sgl_count %u is_err %ld\n", __func__,
 -             sg, sgl_count, IS_ERR(sg));
 +      pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__,
 +             sg, sgl_count, !sg);
        sg_init_table(sg, sgl_count);
  
        tv_cmd->tvc_sgl = sg;
@@@ -784,12 -776,12 +773,12 @@@ static void vhost_scsi_handle_vq(struc
  
  static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
  {
 -      pr_err("%s: The handling func for control queue.\n", __func__);
 +      pr_debug("%s: The handling func for control queue.\n", __func__);
  }
  
  static void vhost_scsi_evt_handle_kick(struct vhost_work *work)
  {
 -      pr_err("%s: The handling func for event queue.\n", __func__);
 +      pr_debug("%s: The handling func for event queue.\n", __func__);
  }
  
  static void vhost_scsi_handle_kick(struct vhost_work *work)
@@@ -822,6 -814,11 +811,6 @@@ static int vhost_scsi_set_endpoint
                        return -EFAULT;
                }
        }
 -
 -      if (vs->vs_tpg) {
 -              mutex_unlock(&vs->dev.mutex);
 -              return -EEXIST;
 -      }
        mutex_unlock(&vs->dev.mutex);
  
        mutex_lock(&tcm_vhost_mutex);
                        mutex_unlock(&tv_tpg->tv_tpg_mutex);
                        continue;
                }
 -              if (atomic_read(&tv_tpg->tv_tpg_vhost_count)) {
 +              if (tv_tpg->tv_tpg_vhost_count != 0) {
                        mutex_unlock(&tv_tpg->tv_tpg_mutex);
                        continue;
                }
  
                if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) &&
                    (tv_tpg->tport_tpgt == t->vhost_tpgt)) {
 -                      atomic_inc(&tv_tpg->tv_tpg_vhost_count);
 -                      smp_mb__after_atomic_inc();
 +                      tv_tpg->tv_tpg_vhost_count++;
                        mutex_unlock(&tv_tpg->tv_tpg_mutex);
                        mutex_unlock(&tcm_vhost_mutex);
  
                        mutex_lock(&vs->dev.mutex);
 +                      if (vs->vs_tpg) {
 +                              mutex_unlock(&vs->dev.mutex);
 +                              mutex_lock(&tv_tpg->tv_tpg_mutex);
 +                              tv_tpg->tv_tpg_vhost_count--;
 +                              mutex_unlock(&tv_tpg->tv_tpg_mutex);
 +                              return -EEXIST;
 +                      }
 +
                        vs->vs_tpg = tv_tpg;
 -                      atomic_inc(&vs->vhost_ref_cnt);
                        smp_mb__after_atomic_inc();
                        mutex_unlock(&vs->dev.mutex);
                        return 0;
@@@ -869,42 -860,38 +858,42 @@@ static int vhost_scsi_clear_endpoint
  {
        struct tcm_vhost_tport *tv_tport;
        struct tcm_vhost_tpg *tv_tpg;
 -      int index;
 +      int index, ret;
  
        mutex_lock(&vs->dev.mutex);
        /* Verify that ring has been setup correctly. */
        for (index = 0; index < vs->dev.nvqs; ++index) {
                if (!vhost_vq_access_ok(&vs->vqs[index])) {
 -                      mutex_unlock(&vs->dev.mutex);
 -                      return -EFAULT;
 +                      ret = -EFAULT;
 +                      goto err;
                }
        }
  
        if (!vs->vs_tpg) {
 -              mutex_unlock(&vs->dev.mutex);
 -              return -ENODEV;
 +              ret = -ENODEV;
 +              goto err;
        }
        tv_tpg = vs->vs_tpg;
        tv_tport = tv_tpg->tport;
  
        if (strcmp(tv_tport->tport_name, t->vhost_wwpn) ||
            (tv_tpg->tport_tpgt != t->vhost_tpgt)) {
 -              mutex_unlock(&vs->dev.mutex);
                pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu"
                        " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n",
                        tv_tport->tport_name, tv_tpg->tport_tpgt,
                        t->vhost_wwpn, t->vhost_tpgt);
 -              return -EINVAL;
 +              ret = -EINVAL;
 +              goto err;
        }
 -      atomic_dec(&tv_tpg->tv_tpg_vhost_count);
 +      tv_tpg->tv_tpg_vhost_count--;
        vs->vs_tpg = NULL;
        mutex_unlock(&vs->dev.mutex);
  
        return 0;
 +
 +err:
 +      mutex_unlock(&vs->dev.mutex);
 +      return ret;
  }
  
  static int vhost_scsi_open(struct inode *inode, struct file *f)
        INIT_LIST_HEAD(&s->vs_completion_list);
        spin_lock_init(&s->vs_completion_lock);
  
 -      s->vqs[0].handle_kick = vhost_scsi_ctl_handle_kick;
 -      s->vqs[1].handle_kick = vhost_scsi_evt_handle_kick;
 -      s->vqs[2].handle_kick = vhost_scsi_handle_kick;
 +      s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick;
 +      s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick;
 +      s->vqs[VHOST_SCSI_VQ_IO].handle_kick = vhost_scsi_handle_kick;
        r = vhost_dev_init(&s->dev, s->vqs, 3);
        if (r < 0) {
                kfree(s);
@@@ -951,18 -938,6 +940,18 @@@ static int vhost_scsi_release(struct in
        return 0;
  }
  
 +static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
 +{
 +      vhost_poll_flush(&vs->dev.vqs[index].poll);
 +}
 +
 +static void vhost_scsi_flush(struct vhost_scsi *vs)
 +{
 +      vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_CTL);
 +      vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_EVT);
 +      vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_IO);
 +}
 +
  static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
  {
        if (features & ~VHOST_FEATURES)
                return -EFAULT;
        }
        vs->dev.acked_features = features;
 -      /* TODO possibly smp_wmb() and flush vqs */
 +      smp_wmb();
 +      vhost_scsi_flush(vs);
        mutex_unlock(&vs->dev.mutex);
        return 0;
  }
@@@ -989,25 -963,26 +978,25 @@@ static long vhost_scsi_ioctl(struct fil
        void __user *argp = (void __user *)arg;
        u64 __user *featurep = argp;
        u64 features;
 -      int r;
 +      int r, abi_version = VHOST_SCSI_ABI_VERSION;
  
        switch (ioctl) {
        case VHOST_SCSI_SET_ENDPOINT:
                if (copy_from_user(&backend, argp, sizeof backend))
                        return -EFAULT;
 +              if (backend.reserved != 0)
 +                      return -EOPNOTSUPP;
  
                return vhost_scsi_set_endpoint(vs, &backend);
        case VHOST_SCSI_CLEAR_ENDPOINT:
                if (copy_from_user(&backend, argp, sizeof backend))
                        return -EFAULT;
 +              if (backend.reserved != 0)
 +                      return -EOPNOTSUPP;
  
                return vhost_scsi_clear_endpoint(vs, &backend);
        case VHOST_SCSI_GET_ABI_VERSION:
 -              if (copy_from_user(&backend, argp, sizeof backend))
 -                      return -EFAULT;
 -
 -              backend.abi_version = VHOST_SCSI_ABI_VERSION;
 -
 -              if (copy_to_user(argp, &backend, sizeof backend))
 +              if (copy_to_user(argp, &abi_version, sizeof abi_version))
                        return -EFAULT;
                return 0;
        case VHOST_GET_FEATURES:
        }
  }
  
 +#ifdef CONFIG_COMPAT
 +static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl,
 +                              unsigned long arg)
 +{
 +      return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
 +}
 +#endif
 +
  static const struct file_operations vhost_scsi_fops = {
        .owner          = THIS_MODULE,
        .release        = vhost_scsi_release,
        .unlocked_ioctl = vhost_scsi_ioctl,
 -      /* TODO compat ioctl? */
 +#ifdef CONFIG_COMPAT
 +      .compat_ioctl   = vhost_scsi_compat_ioctl,
 +#endif
        .open           = vhost_scsi_open,
        .llseek         = noop_llseek,
  };
@@@ -1078,28 -1043,28 +1067,28 @@@ static char *tcm_vhost_dump_proto_id(st
        return "Unknown";
  }
  
 -static int tcm_vhost_port_link(
 -      struct se_portal_group *se_tpg,
 +static int tcm_vhost_port_link(struct se_portal_group *se_tpg,
        struct se_lun *lun)
  {
        struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
                                struct tcm_vhost_tpg, se_tpg);
  
 -      atomic_inc(&tv_tpg->tv_tpg_port_count);
 -      smp_mb__after_atomic_inc();
 +      mutex_lock(&tv_tpg->tv_tpg_mutex);
 +      tv_tpg->tv_tpg_port_count++;
 +      mutex_unlock(&tv_tpg->tv_tpg_mutex);
  
        return 0;
  }
  
 -static void tcm_vhost_port_unlink(
 -      struct se_portal_group *se_tpg,
 +static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg,
        struct se_lun *se_lun)
  {
        struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
                                struct tcm_vhost_tpg, se_tpg);
  
 -      atomic_dec(&tv_tpg->tv_tpg_port_count);
 -      smp_mb__after_atomic_dec();
 +      mutex_lock(&tv_tpg->tv_tpg_mutex);
 +      tv_tpg->tv_tpg_port_count--;
 +      mutex_unlock(&tv_tpg->tv_tpg_mutex);
  }
  
  static struct se_node_acl *tcm_vhost_make_nodeacl(
@@@ -1146,7 -1111,8 +1135,7 @@@ static void tcm_vhost_drop_nodeacl(stru
        kfree(nacl);
  }
  
 -static int tcm_vhost_make_nexus(
 -      struct tcm_vhost_tpg *tv_tpg,
 +static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg,
        const char *name)
  {
        struct se_portal_group *se_tpg;
                return -ENOMEM;
        }
        /*
 -       * Now register the TCM vHost virtual I_T Nexus as active with the
 +       * Now register the TCM vhost virtual I_T Nexus as active with the
         * call to __transport_register_session()
         */
        __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
        return 0;
  }
  
 -static int tcm_vhost_drop_nexus(
 -      struct tcm_vhost_tpg *tpg)
 +static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg)
  {
        struct se_session *se_sess;
        struct tcm_vhost_nexus *tv_nexus;
                return -ENODEV;
        }
  
 -      if (atomic_read(&tpg->tv_tpg_port_count)) {
 +      if (tpg->tv_tpg_port_count != 0) {
                mutex_unlock(&tpg->tv_tpg_mutex);
 -              pr_err("Unable to remove TCM_vHost I_T Nexus with"
 +              pr_err("Unable to remove TCM_vhost I_T Nexus with"
                        " active TPG port count: %d\n",
 -                      atomic_read(&tpg->tv_tpg_port_count));
 -              return -EPERM;
 +                      tpg->tv_tpg_port_count);
 +              return -EBUSY;
        }
  
 -      if (atomic_read(&tpg->tv_tpg_vhost_count)) {
 +      if (tpg->tv_tpg_vhost_count != 0) {
                mutex_unlock(&tpg->tv_tpg_mutex);
 -              pr_err("Unable to remove TCM_vHost I_T Nexus with"
 +              pr_err("Unable to remove TCM_vhost I_T Nexus with"
                        " active TPG vhost count: %d\n",
 -                      atomic_read(&tpg->tv_tpg_vhost_count));
 -              return -EPERM;
 +                      tpg->tv_tpg_vhost_count);
 +              return -EBUSY;
        }
  
 -      pr_debug("TCM_vHost_ConfigFS: Removing I_T Nexus to emulated"
 +      pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated"
                " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport),
                tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
        /*
 -       * Release the SCSI I_T Nexus to the emulated vHost Target Port
 +       * Release the SCSI I_T Nexus to the emulated vhost Target Port
         */
        transport_deregister_session(tv_nexus->tvn_se_sess);
        tpg->tpg_nexus = NULL;
        return 0;
  }
  
 -static ssize_t tcm_vhost_tpg_show_nexus(
 -      struct se_portal_group *se_tpg,
 +static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg,
        char *page)
  {
        struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
        return ret;
  }
  
 -static ssize_t tcm_vhost_tpg_store_nexus(
 -      struct se_portal_group *se_tpg,
 +static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg,
        const char *page,
        size_t count)
  {
@@@ -1356,7 -1325,8 +1345,7 @@@ static struct configfs_attribute *tcm_v
        NULL,
  };
  
 -static struct se_portal_group *tcm_vhost_make_tpg(
 -      struct se_wwn *wwn,
 +static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn,
        struct config_group *group,
        const char *name)
  {
@@@ -1404,7 -1374,7 +1393,7 @@@ static void tcm_vhost_drop_tpg(struct s
        list_del(&tpg->tv_tpg_list);
        mutex_unlock(&tcm_vhost_mutex);
        /*
 -       * Release the virtual I_T Nexus for this vHost TPG
 +       * Release the virtual I_T Nexus for this vhost TPG
         */
        tcm_vhost_drop_nexus(tpg);
        /*
        kfree(tpg);
  }
  
 -static struct se_wwn *tcm_vhost_make_tport(
 -      struct target_fabric_configfs *tf,
 +static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf,
        struct config_group *group,
        const char *name)
  {
@@@ -1531,8 -1502,6 +1520,6 @@@ static struct target_core_fabric_ops tc
        .queue_data_in                  = tcm_vhost_queue_data_in,
        .queue_status                   = tcm_vhost_queue_status,
        .queue_tm_rsp                   = tcm_vhost_queue_tm_rsp,
-       .get_fabric_sense_len           = tcm_vhost_get_fabric_sense_len,
-       .set_fabric_sense_len           = tcm_vhost_set_fabric_sense_len,
        /*
         * Setup callers for generic logic in target_core_fabric_configfs.c
         */
@@@ -1610,10 -1579,7 +1597,10 @@@ static void tcm_vhost_deregister_config
  static int __init tcm_vhost_init(void)
  {
        int ret = -ENOMEM;
 -
 +      /*
 +       * Use our own dedicated workqueue for submitting I/O into
 +       * target core to avoid contention within system_wq.
 +       */
        tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0);
        if (!tcm_vhost_workqueue)
                goto out;