]> Git Repo - linux.git/commitdiff
Merge branch 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <[email protected]>
Wed, 21 Dec 2016 18:16:05 +0000 (10:16 -0800)
committerLinus Torvalds <[email protected]>
Wed, 21 Dec 2016 18:16:05 +0000 (10:16 -0800)
Pull scsi target cleanups from Bart Van Assche:
 "The changes here are:

   - a few small bug fixes for the iSCSI and user space target drivers.

   - minimize the target build time by about 30% by rearranging #include
     directives

   - fix the second argument passed to percpu_ida_alloc()

   - reduce the number of false positive warnings reported by sparse

  These patches pass Wu Fengguang's build bot tests and also the
  linux-next tests"

* 'scsi-target-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/bvanassche/linux:
  iscsi-target: Return error if unable to add network portal
  target: Fix spelling mistake and unwrap multi-line text
  target/iscsi: Fix double free in lio_target_tiqn_addtpg()
  target/user: Fix use-after-free of tcmu_cmds if they are expired
  target: Minimize #include directives
  target/user: Add an #include directive
  cxgbit: Add an #include directive
  ibmvscsi_tgt: Add two #include directives
  sbp-target: Add an #include directive
  qla2xxx: Add an #include directive
  configfs: Minimize #include directives
  usb: gadget: Fix second argument of percpu_ida_alloc()
  sbp-target: Fix second argument of percpu_ida_alloc()
  target/user: Fix a data type in tcmu_queue_cmd()
  target: Use NULL instead of 0 to represent a pointer

1  2 
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
drivers/scsi/qla2xxx/qla_isr.c
drivers/target/target_core_configfs.c
drivers/target/target_core_user.c
include/linux/configfs.h
include/target/target_core_base.h

index c9fa3565c671e9f1b0f4e16e847c713cd6165078,e9321a5e3f97ef000dfb2a92104da0d4f230564e..2583e8b50b21c2cfa6ec3d10e624adb8141d5c9d
@@@ -22,7 -22,7 +22,7 @@@
   *
   ****************************************************************************/
  
 -#define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
 +#define pr_fmt(fmt)   KBUILD_MODNAME ": " fmt
  
  #include <linux/module.h>
  #include <linux/kernel.h>
@@@ -30,6 -30,7 +30,7 @@@
  #include <linux/types.h>
  #include <linux/list.h>
  #include <linux/string.h>
+ #include <linux/delay.h>
  
  #include <target/target_core_base.h>
  #include <target/target_core_fabric.h>
@@@ -81,7 -82,7 +82,7 @@@ static void ibmvscsis_determine_resid(s
                }
        } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
                if (se_cmd->data_direction == DMA_TO_DEVICE) {
 -                      /*  residual data from an overflow write */
 +                      /* residual data from an overflow write */
                        rsp->flags = SRP_RSP_FLAG_DOOVER;
                        rsp->data_out_res_cnt = cpu_to_be32(residual_count);
                } else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
   * and the function returns TRUE.
   *
   * EXECUTION ENVIRONMENT:
 - *      Interrupt or Process environment
 + *    Interrupt or Process environment
   */
  static bool connection_broken(struct scsi_info *vscsi)
  {
@@@ -324,7 -325,7 +325,7 @@@ static struct viosrp_crq *ibmvscsis_cmd
  }
  
  /**
 - * ibmvscsis_send_init_message() -  send initialize message to the client
 + * ibmvscsis_send_init_message() - send initialize message to the client
   * @vscsi:    Pointer to our adapter structure
   * @format:   Which Init Message format to send
   *
@@@ -382,13 -383,13 +383,13 @@@ static long ibmvscsis_check_init_msg(st
                                              vscsi->cmd_q.base_addr);
                if (crq) {
                        *format = (uint)(crq->format);
 -                      rc =  ERROR;
 +                      rc = ERROR;
                        crq->valid = INVALIDATE_CMD_RESP_EL;
                        dma_rmb();
                }
        } else {
                *format = (uint)(crq->format);
 -              rc =  ERROR;
 +              rc = ERROR;
                crq->valid = INVALIDATE_CMD_RESP_EL;
                dma_rmb();
        }
        return rc;
  }
  
 -/**
 - * ibmvscsis_establish_new_q() - Establish new CRQ queue
 - * @vscsi:    Pointer to our adapter structure
 - * @new_state:        New state being established after resetting the queue
 - *
 - * Must be called with interrupt lock held.
 - */
 -static long ibmvscsis_establish_new_q(struct scsi_info *vscsi,  uint new_state)
 -{
 -      long rc = ADAPT_SUCCESS;
 -      uint format;
 -
 -      vscsi->flags &= PRESERVE_FLAG_FIELDS;
 -      vscsi->rsp_q_timer.timer_pops = 0;
 -      vscsi->debit = 0;
 -      vscsi->credit = 0;
 -
 -      rc = vio_enable_interrupts(vscsi->dma_dev);
 -      if (rc) {
 -              pr_warn("reset_queue: failed to enable interrupts, rc %ld\n",
 -                      rc);
 -              return rc;
 -      }
 -
 -      rc = ibmvscsis_check_init_msg(vscsi, &format);
 -      if (rc) {
 -              dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n",
 -                      rc);
 -              return rc;
 -      }
 -
 -      if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) {
 -              rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
 -              switch (rc) {
 -              case H_SUCCESS:
 -              case H_DROPPED:
 -              case H_CLOSED:
 -                      rc = ADAPT_SUCCESS;
 -                      break;
 -
 -              case H_PARAMETER:
 -              case H_HARDWARE:
 -                      break;
 -
 -              default:
 -                      vscsi->state = UNDEFINED;
 -                      rc = H_HARDWARE;
 -                      break;
 -              }
 -      }
 -
 -      return rc;
 -}
 -
 -/**
 - * ibmvscsis_reset_queue() - Reset CRQ Queue
 - * @vscsi:    Pointer to our adapter structure
 - * @new_state:        New state to establish after resetting the queue
 - *
 - * This function calls h_free_q and then calls h_reg_q and does all
 - * of the bookkeeping to get us back to where we can communicate.
 - *
 - * Actually, we don't always call h_free_crq.  A problem was discovered
 - * where one partition would close and reopen his queue, which would
 - * cause his partner to get a transport event, which would cause him to
 - * close and reopen his queue, which would cause the original partition
 - * to get a transport event, etc., etc.  To prevent this, we don't
 - * actually close our queue if the client initiated the reset, (i.e.
 - * either we got a transport event or we have detected that the client's
 - * queue is gone)
 - *
 - * EXECUTION ENVIRONMENT:
 - *    Process environment, called with interrupt lock held
 - */
 -static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state)
 -{
 -      int bytes;
 -      long rc = ADAPT_SUCCESS;
 -
 -      pr_debug("reset_queue: flags 0x%x\n", vscsi->flags);
 -
 -      /* don't reset, the client did it for us */
 -      if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) {
 -              vscsi->flags &=  PRESERVE_FLAG_FIELDS;
 -              vscsi->rsp_q_timer.timer_pops = 0;
 -              vscsi->debit = 0;
 -              vscsi->credit = 0;
 -              vscsi->state = new_state;
 -              vio_enable_interrupts(vscsi->dma_dev);
 -      } else {
 -              rc = ibmvscsis_free_command_q(vscsi);
 -              if (rc == ADAPT_SUCCESS) {
 -                      vscsi->state = new_state;
 -
 -                      bytes = vscsi->cmd_q.size * PAGE_SIZE;
 -                      rc = h_reg_crq(vscsi->dds.unit_id,
 -                                     vscsi->cmd_q.crq_token, bytes);
 -                      if (rc == H_CLOSED || rc == H_SUCCESS) {
 -                              rc = ibmvscsis_establish_new_q(vscsi,
 -                                                             new_state);
 -                      }
 -
 -                      if (rc != ADAPT_SUCCESS) {
 -                              pr_debug("reset_queue: reg_crq rc %ld\n", rc);
 -
 -                              vscsi->state = ERR_DISCONNECTED;
 -                              vscsi->flags |=  RESPONSE_Q_DOWN;
 -                              ibmvscsis_free_command_q(vscsi);
 -                      }
 -              } else {
 -                      vscsi->state = ERR_DISCONNECTED;
 -                      vscsi->flags |= RESPONSE_Q_DOWN;
 -              }
 -      }
 -}
 -
 -/**
 - * ibmvscsis_free_cmd_resources() - Free command resources
 - * @vscsi:    Pointer to our adapter structure
 - * @cmd:      Command which is not longer in use
 - *
 - * Must be called with interrupt lock held.
 - */
 -static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
 -                                       struct ibmvscsis_cmd *cmd)
 -{
 -      struct iu_entry *iue = cmd->iue;
 -
 -      switch (cmd->type) {
 -      case TASK_MANAGEMENT:
 -      case SCSI_CDB:
 -              /*
 -               * When the queue goes down this value is cleared, so it
 -               * cannot be cleared in this general purpose function.
 -               */
 -              if (vscsi->debit)
 -                      vscsi->debit -= 1;
 -              break;
 -      case ADAPTER_MAD:
 -              vscsi->flags &= ~PROCESSING_MAD;
 -              break;
 -      case UNSET_TYPE:
 -              break;
 -      default:
 -              dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n",
 -                      cmd->type);
 -              break;
 -      }
 -
 -      cmd->iue = NULL;
 -      list_add_tail(&cmd->list, &vscsi->free_cmd);
 -      srp_iu_put(iue);
 -
 -      if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) &&
 -          list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) {
 -              vscsi->flags &= ~WAIT_FOR_IDLE;
 -              complete(&vscsi->wait_idle);
 -      }
 -}
 -
  /**
   * ibmvscsis_disconnect() - Helper function to disconnect
   * @work:     Pointer to work_struct, gives access to our adapter structure
@@@ -415,6 -576,7 +416,6 @@@ static void ibmvscsis_disconnect(struc
                                               proc_work);
        u16 new_state;
        bool wait_idle = false;
 -      long rc = ADAPT_SUCCESS;
  
        spin_lock_bh(&vscsi->intr_lock);
        new_state = vscsi->new_state;
         * should transitition to the new state
         */
        switch (vscsi->state) {
 -      /*  Should never be called while in this state. */
 +      /* Should never be called while in this state. */
        case NO_QUEUE:
        /*
         * Can never transition from this state;
                        vscsi->state = new_state;
                break;
  
 -      /*
 -       * If this is a transition into an error state.
 -       * a client is attempting to establish a connection
 -       * and has violated the RPA protocol.
 -       * There can be nothing pending on the adapter although
 -       * there can be requests in the command queue.
 -       */
        case WAIT_ENABLED:
 -      case PART_UP_WAIT_ENAB:
                switch (new_state) {
 -              case ERR_DISCONNECT:
 -                      vscsi->flags |= RESPONSE_Q_DOWN;
 +              case UNCONFIGURING:
                        vscsi->state = new_state;
 +                      vscsi->flags |= RESPONSE_Q_DOWN;
                        vscsi->flags &= ~(SCHEDULE_DISCONNECT |
                                          DISCONNECT_SCHEDULED);
 -                      ibmvscsis_free_command_q(vscsi);
 -                      break;
 -              case ERR_DISCONNECT_RECONNECT:
 -                      ibmvscsis_reset_queue(vscsi, WAIT_ENABLED);
 +                      dma_rmb();
 +                      if (vscsi->flags & CFG_SLEEPING) {
 +                              vscsi->flags &= ~CFG_SLEEPING;
 +                              complete(&vscsi->unconfig);
 +                      }
                        break;
  
                /* should never happen */
 +              case ERR_DISCONNECT:
 +              case ERR_DISCONNECT_RECONNECT:
                case WAIT_IDLE:
 -                      rc = ERROR;
                        dev_err(&vscsi->dev, "disconnect: invalid state %d for WAIT_IDLE\n",
                                vscsi->state);
                        break;
  
        case WAIT_IDLE:
                switch (new_state) {
 +              case UNCONFIGURING:
 +                      vscsi->flags |= RESPONSE_Q_DOWN;
 +                      vscsi->state = new_state;
 +                      vscsi->flags &= ~(SCHEDULE_DISCONNECT |
 +                                        DISCONNECT_SCHEDULED);
 +                      ibmvscsis_free_command_q(vscsi);
 +                      break;
                case ERR_DISCONNECT:
                case ERR_DISCONNECT_RECONNECT:
                        vscsi->state = new_state;
@@@ -604,348 -765,45 +605,348 @@@ static void ibmvscsis_post_disconnect(s
                else
                        state = vscsi->state;
  
 -              switch (state) {
 -              case NO_QUEUE:
 -              case UNCONFIGURING:
 -                      break;
 +              switch (state) {
 +              case NO_QUEUE:
 +              case UNCONFIGURING:
 +                      break;
 +
 +              case ERR_DISCONNECTED:
 +              case ERR_DISCONNECT:
 +              case UNDEFINED:
 +                      if (new_state == UNCONFIGURING)
 +                              vscsi->new_state = new_state;
 +                      break;
 +
 +              case ERR_DISCONNECT_RECONNECT:
 +                      switch (new_state) {
 +                      case UNCONFIGURING:
 +                      case ERR_DISCONNECT:
 +                              vscsi->new_state = new_state;
 +                              break;
 +                      default:
 +                              break;
 +                      }
 +                      break;
 +
 +              case WAIT_ENABLED:
 +              case WAIT_IDLE:
 +              case WAIT_CONNECTION:
 +              case CONNECTED:
 +              case SRP_PROCESSING:
 +                      vscsi->new_state = new_state;
 +                      break;
 +
 +              default:
 +                      break;
 +              }
 +      }
 +
 +      pr_debug("Leaving post_disconnect: flags 0x%x, new_state 0x%x\n",
 +               vscsi->flags, vscsi->new_state);
 +}
 +
 +/**
 + * ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message
 + * @vscsi:    Pointer to our adapter structure
 + *
 + * Must be called with interrupt lock held.
 + */
 +static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi)
 +{
 +      long rc = ADAPT_SUCCESS;
 +
 +      switch (vscsi->state) {
 +      case NO_QUEUE:
 +      case ERR_DISCONNECT:
 +      case ERR_DISCONNECT_RECONNECT:
 +      case ERR_DISCONNECTED:
 +      case UNCONFIGURING:
 +      case UNDEFINED:
 +              rc = ERROR;
 +              break;
 +
 +      case WAIT_CONNECTION:
 +              vscsi->state = CONNECTED;
 +              break;
 +
 +      case WAIT_IDLE:
 +      case SRP_PROCESSING:
 +      case CONNECTED:
 +      case WAIT_ENABLED:
 +      default:
 +              rc = ERROR;
 +              dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n",
 +                      vscsi->state);
 +              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 +              break;
 +      }
 +
 +      return rc;
 +}
 +
 +/**
 + * ibmvscsis_handle_init_msg() - Respond to an Init Message
 + * @vscsi:    Pointer to our adapter structure
 + *
 + * Must be called with interrupt lock held.
 + */
 +static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi)
 +{
 +      long rc = ADAPT_SUCCESS;
 +
 +      switch (vscsi->state) {
 +      case WAIT_CONNECTION:
 +              rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
 +              switch (rc) {
 +              case H_SUCCESS:
 +                      vscsi->state = CONNECTED;
 +                      break;
 +
 +              case H_PARAMETER:
 +                      dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
 +                              rc);
 +                      ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
 +                      break;
 +
 +              case H_DROPPED:
 +                      dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
 +                              rc);
 +                      rc = ERROR;
 +                      ibmvscsis_post_disconnect(vscsi,
 +                                                ERR_DISCONNECT_RECONNECT, 0);
 +                      break;
 +
 +              case H_CLOSED:
 +                      pr_warn("init_msg: failed to send, rc %ld\n", rc);
 +                      rc = 0;
 +                      break;
 +              }
 +              break;
 +
 +      case UNDEFINED:
 +              rc = ERROR;
 +              break;
 +
 +      case UNCONFIGURING:
 +              break;
 +
 +      case WAIT_ENABLED:
 +      case CONNECTED:
 +      case SRP_PROCESSING:
 +      case WAIT_IDLE:
 +      case NO_QUEUE:
 +      case ERR_DISCONNECT:
 +      case ERR_DISCONNECT_RECONNECT:
 +      case ERR_DISCONNECTED:
 +      default:
 +              rc = ERROR;
 +              dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n",
 +                      vscsi->state);
 +              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 +              break;
 +      }
 +
 +      return rc;
 +}
 +
 +/**
 + * ibmvscsis_init_msg() - Respond to an init message
 + * @vscsi:    Pointer to our adapter structure
 + * @crq:      Pointer to CRQ element containing the Init Message
 + *
 + * EXECUTION ENVIRONMENT:
 + *    Interrupt, interrupt lock held
 + */
 +static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq)
 +{
 +      long rc = ADAPT_SUCCESS;
 +
 +      pr_debug("init_msg: state 0x%hx\n", vscsi->state);
 +
 +      rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
 +                    (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
 +                    0);
 +      if (rc == H_SUCCESS) {
 +              vscsi->client_data.partition_number =
 +                      be64_to_cpu(*(u64 *)vscsi->map_buf);
 +              pr_debug("init_msg, part num %d\n",
 +                       vscsi->client_data.partition_number);
 +      } else {
 +              pr_debug("init_msg h_vioctl rc %ld\n", rc);
 +              rc = ADAPT_SUCCESS;
 +      }
 +
 +      if (crq->format == INIT_MSG) {
 +              rc = ibmvscsis_handle_init_msg(vscsi);
 +      } else if (crq->format == INIT_COMPLETE_MSG) {
 +              rc = ibmvscsis_handle_init_compl_msg(vscsi);
 +      } else {
 +              rc = ERROR;
 +              dev_err(&vscsi->dev, "init_msg: invalid format %d\n",
 +                      (uint)crq->format);
 +              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 +      }
 +
 +      return rc;
 +}
 +
 +/**
 + * ibmvscsis_establish_new_q() - Establish new CRQ queue
 + * @vscsi:    Pointer to our adapter structure
 + *
 + * Must be called with interrupt lock held.
 + */
 +static long ibmvscsis_establish_new_q(struct scsi_info *vscsi)
 +{
 +      long rc = ADAPT_SUCCESS;
 +      uint format;
 +
 +      vscsi->flags &= PRESERVE_FLAG_FIELDS;
 +      vscsi->rsp_q_timer.timer_pops = 0;
 +      vscsi->debit = 0;
 +      vscsi->credit = 0;
 +
 +      rc = vio_enable_interrupts(vscsi->dma_dev);
 +      if (rc) {
 +              pr_warn("establish_new_q: failed to enable interrupts, rc %ld\n",
 +                      rc);
 +              return rc;
 +      }
 +
 +      rc = ibmvscsis_check_init_msg(vscsi, &format);
 +      if (rc) {
 +              dev_err(&vscsi->dev, "establish_new_q: check_init_msg failed, rc %ld\n",
 +                      rc);
 +              return rc;
 +      }
 +
 +      if (format == UNUSED_FORMAT) {
 +              rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
 +              switch (rc) {
 +              case H_SUCCESS:
 +              case H_DROPPED:
 +              case H_CLOSED:
 +                      rc = ADAPT_SUCCESS;
 +                      break;
 +
 +              case H_PARAMETER:
 +              case H_HARDWARE:
 +                      break;
 +
 +              default:
 +                      vscsi->state = UNDEFINED;
 +                      rc = H_HARDWARE;
 +                      break;
 +              }
 +      } else if (format == INIT_MSG) {
 +              rc = ibmvscsis_handle_init_msg(vscsi);
 +      }
 +
 +      return rc;
 +}
 +
 +/**
 + * ibmvscsis_reset_queue() - Reset CRQ Queue
 + * @vscsi:    Pointer to our adapter structure
 + *
 + * This function calls h_free_q and then calls h_reg_q and does all
 + * of the bookkeeping to get us back to where we can communicate.
 + *
 + * Actually, we don't always call h_free_crq.  A problem was discovered
 + * where one partition would close and reopen his queue, which would
 + * cause his partner to get a transport event, which would cause him to
 + * close and reopen his queue, which would cause the original partition
 + * to get a transport event, etc., etc.  To prevent this, we don't
 + * actually close our queue if the client initiated the reset, (i.e.
 + * either we got a transport event or we have detected that the client's
 + * queue is gone)
 + *
 + * EXECUTION ENVIRONMENT:
 + *    Process environment, called with interrupt lock held
 + */
 +static void ibmvscsis_reset_queue(struct scsi_info *vscsi)
 +{
 +      int bytes;
 +      long rc = ADAPT_SUCCESS;
 +
 +      pr_debug("reset_queue: flags 0x%x\n", vscsi->flags);
 +
 +      /* don't reset, the client did it for us */
 +      if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) {
 +              vscsi->flags &= PRESERVE_FLAG_FIELDS;
 +              vscsi->rsp_q_timer.timer_pops = 0;
 +              vscsi->debit = 0;
 +              vscsi->credit = 0;
 +              vscsi->state = WAIT_CONNECTION;
 +              vio_enable_interrupts(vscsi->dma_dev);
 +      } else {
 +              rc = ibmvscsis_free_command_q(vscsi);
 +              if (rc == ADAPT_SUCCESS) {
 +                      vscsi->state = WAIT_CONNECTION;
 +
 +                      bytes = vscsi->cmd_q.size * PAGE_SIZE;
 +                      rc = h_reg_crq(vscsi->dds.unit_id,
 +                                     vscsi->cmd_q.crq_token, bytes);
 +                      if (rc == H_CLOSED || rc == H_SUCCESS) {
 +                              rc = ibmvscsis_establish_new_q(vscsi);
 +                      }
  
 -              case ERR_DISCONNECTED:
 -              case ERR_DISCONNECT:
 -              case UNDEFINED:
 -                      if (new_state == UNCONFIGURING)
 -                              vscsi->new_state = new_state;
 -                      break;
 +                      if (rc != ADAPT_SUCCESS) {
 +                              pr_debug("reset_queue: reg_crq rc %ld\n", rc);
  
 -              case ERR_DISCONNECT_RECONNECT:
 -                      switch (new_state) {
 -                      case UNCONFIGURING:
 -                      case ERR_DISCONNECT:
 -                              vscsi->new_state = new_state;
 -                              break;
 -                      default:
 -                              break;
 +                              vscsi->state = ERR_DISCONNECTED;
 +                              vscsi->flags |= RESPONSE_Q_DOWN;
 +                              ibmvscsis_free_command_q(vscsi);
                        }
 -                      break;
 +              } else {
 +                      vscsi->state = ERR_DISCONNECTED;
 +                      vscsi->flags |= RESPONSE_Q_DOWN;
 +              }
 +      }
 +}
  
 -              case WAIT_ENABLED:
 -              case PART_UP_WAIT_ENAB:
 -              case WAIT_IDLE:
 -              case WAIT_CONNECTION:
 -              case CONNECTED:
 -              case SRP_PROCESSING:
 -                      vscsi->new_state = new_state;
 -                      break;
 +/**
 + * ibmvscsis_free_cmd_resources() - Free command resources
 + * @vscsi:    Pointer to our adapter structure
 + * @cmd:      Command which is not longer in use
 + *
 + * Must be called with interrupt lock held.
 + */
 +static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
 +                                       struct ibmvscsis_cmd *cmd)
 +{
 +      struct iu_entry *iue = cmd->iue;
  
 -              default:
 -                      break;
 -              }
 +      switch (cmd->type) {
 +      case TASK_MANAGEMENT:
 +      case SCSI_CDB:
 +              /*
 +               * When the queue goes down this value is cleared, so it
 +               * cannot be cleared in this general purpose function.
 +               */
 +              if (vscsi->debit)
 +                      vscsi->debit -= 1;
 +              break;
 +      case ADAPTER_MAD:
 +              vscsi->flags &= ~PROCESSING_MAD;
 +              break;
 +      case UNSET_TYPE:
 +              break;
 +      default:
 +              dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n",
 +                      cmd->type);
 +              break;
        }
  
 -      pr_debug("Leaving post_disconnect: flags 0x%x, new_state 0x%x\n",
 -               vscsi->flags, vscsi->new_state);
 +      cmd->iue = NULL;
 +      list_add_tail(&cmd->list, &vscsi->free_cmd);
 +      srp_iu_put(iue);
 +
 +      if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) &&
 +          list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) {
 +              vscsi->flags &= ~WAIT_FOR_IDLE;
 +              complete(&vscsi->wait_idle);
 +      }
  }
  
  /**
@@@ -1006,6 -864,10 +1007,6 @@@ static long ibmvscsis_trans_event(struc
                                                   TRANS_EVENT));
                        break;
  
 -              case PART_UP_WAIT_ENAB:
 -                      vscsi->state = WAIT_ENABLED;
 -                      break;
 -
                case SRP_PROCESSING:
                        if ((vscsi->debit > 0) ||
                            !list_empty(&vscsi->schedule_q) ||
                }
        }
  
 -      rc =  vscsi->flags & SCHEDULE_DISCONNECT;
 +      rc = vscsi->flags & SCHEDULE_DISCONNECT;
  
        pr_debug("Leaving trans_event: flags 0x%x, state 0x%hx, rc %ld\n",
                 vscsi->flags, vscsi->state, rc);
@@@ -1205,28 -1067,16 +1206,28 @@@ static void ibmvscsis_adapter_idle(stru
                free_qs = true;
  
        switch (vscsi->state) {
 +      case UNCONFIGURING:
 +              ibmvscsis_free_command_q(vscsi);
 +              dma_rmb();
 +              isync();
 +              if (vscsi->flags & CFG_SLEEPING) {
 +                      vscsi->flags &= ~CFG_SLEEPING;
 +                      complete(&vscsi->unconfig);
 +              }
 +              break;
        case ERR_DISCONNECT_RECONNECT:
 -              ibmvscsis_reset_queue(vscsi, WAIT_CONNECTION);
 +              ibmvscsis_reset_queue(vscsi);
                pr_debug("adapter_idle, disc_rec: flags 0x%x\n", vscsi->flags);
                break;
  
        case ERR_DISCONNECT:
                ibmvscsis_free_command_q(vscsi);
 -              vscsi->flags &= ~DISCONNECT_SCHEDULED;
 +              vscsi->flags &= ~(SCHEDULE_DISCONNECT | DISCONNECT_SCHEDULED);
                vscsi->flags |= RESPONSE_Q_DOWN;
 -              vscsi->state = ERR_DISCONNECTED;
 +              if (vscsi->tport.enabled)
 +                      vscsi->state = ERR_DISCONNECTED;
 +              else
 +                      vscsi->state = WAIT_ENABLED;
                pr_debug("adapter_idle, disc: flags 0x%x, state 0x%hx\n",
                         vscsi->flags, vscsi->state);
                break;
@@@ -1371,7 -1221,7 +1372,7 @@@ static long ibmvscsis_copy_crq_packet(s
   * @iue:      Information Unit containing the Adapter Info MAD request
   *
   * EXECUTION ENVIRONMENT:
 - *    Interrupt adpater lock is held
 + *    Interrupt adapter lock is held
   */
  static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
                                   struct iu_entry *iue)
@@@ -1771,8 -1621,8 +1772,8 @@@ static void ibmvscsis_send_messages(str
                                        be64_to_cpu(msg_hi),
                                        be64_to_cpu(cmd->rsp.tag));
  
 -                      pr_debug("send_messages: tag 0x%llx, rc %ld\n",
 -                               be64_to_cpu(cmd->rsp.tag), rc);
 +                      pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n",
 +                               cmd, be64_to_cpu(cmd->rsp.tag), rc);
  
                        /* if all ok free up the command element resources */
                        if (rc == H_SUCCESS) {
@@@ -1842,7 -1692,7 +1843,7 @@@ static void ibmvscsis_send_mad_resp(str
   * @crq:      Pointer to the CRQ entry containing the MAD request
   *
   * EXECUTION ENVIRONMENT:
 - *    Interrupt  called with adapter lock held
 + *    Interrupt, called with adapter lock held
   */
  static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq)
  {
  
                pr_debug("mad: type %d\n", be32_to_cpu(mad->type));
  
 -              if (be16_to_cpu(mad->length) < 0) {
 -                      dev_err(&vscsi->dev, "mad: length is < 0\n");
 -                      ibmvscsis_post_disconnect(vscsi,
 -                                                ERR_DISCONNECT_RECONNECT, 0);
 -                      rc = SRP_VIOLATION;
 -              } else {
 -                      rc = ibmvscsis_process_mad(vscsi, iue);
 -              }
 +              rc = ibmvscsis_process_mad(vscsi, iue);
  
                pr_debug("mad: status %hd, rc %ld\n", be16_to_cpu(mad->status),
                         rc);
@@@ -2008,7 -1865,7 +2009,7 @@@ static long ibmvscsis_srp_login_rej(str
                break;
        case H_PERMISSION:
                if (connection_broken(vscsi))
 -                      flag_bits =  RESPONSE_Q_DOWN | CLIENT_FAILED;
 +                      flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED;
                dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n",
                        rc);
                ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
@@@ -2233,98 -2090,248 +2234,98 @@@ static void ibmvscsis_srp_cmd(struct sc
                        break;
  
                case SRP_TSK_MGMT:
 -                      tsk = &vio_iu(iue)->srp.tsk_mgmt;
 -                      pr_debug("tsk_mgmt tag: %llu (0x%llx)\n", tsk->tag,
 -                               tsk->tag);
 -                      cmd->rsp.tag = tsk->tag;
 -                      vscsi->debit += 1;
 -                      cmd->type = TASK_MANAGEMENT;
 -                      list_add_tail(&cmd->list, &vscsi->schedule_q);
 -                      queue_work(vscsi->work_q, &cmd->work);
 -                      break;
 -
 -              case SRP_CMD:
 -                      pr_debug("srp_cmd tag: %llu (0x%llx)\n", srp->tag,
 -                               srp->tag);
 -                      cmd->rsp.tag = srp->tag;
 -                      vscsi->debit += 1;
 -                      cmd->type = SCSI_CDB;
 -                      /*
 -                       * We want to keep track of work waiting for
 -                       * the workqueue.
 -                       */
 -                      list_add_tail(&cmd->list, &vscsi->schedule_q);
 -                      queue_work(vscsi->work_q, &cmd->work);
 -                      break;
 -
 -              case SRP_I_LOGOUT:
 -                      rc = ibmvscsis_srp_i_logout(vscsi, cmd, crq);
 -                      break;
 -
 -              case SRP_CRED_RSP:
 -              case SRP_AER_RSP:
 -              default:
 -                      ibmvscsis_free_cmd_resources(vscsi, cmd);
 -                      dev_err(&vscsi->dev, "invalid srp cmd, opcode %d\n",
 -                              (uint)srp->opcode);
 -                      ibmvscsis_post_disconnect(vscsi,
 -                                                ERR_DISCONNECT_RECONNECT, 0);
 -                      break;
 -              }
 -      } else if (srp->opcode == SRP_LOGIN_REQ && vscsi->state == CONNECTED) {
 -              rc = ibmvscsis_srp_login(vscsi, cmd, crq);
 -      } else {
 -              ibmvscsis_free_cmd_resources(vscsi, cmd);
 -              dev_err(&vscsi->dev, "Invalid state %d to handle srp cmd\n",
 -                      vscsi->state);
 -              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 -      }
 -}
 -
 -/**
 - * ibmvscsis_ping_response() - Respond to a ping request
 - * @vscsi:    Pointer to our adapter structure
 - *
 - * Let the client know that the server is alive and waiting on
 - * its native I/O stack.
 - * If any type of error occurs from the call to queue a ping
 - * response then the client is either not accepting or receiving
 - * interrupts.  Disconnect with an error.
 - *
 - * EXECUTION ENVIRONMENT:
 - *    Interrupt, interrupt lock held
 - */
 -static long ibmvscsis_ping_response(struct scsi_info *vscsi)
 -{
 -      struct viosrp_crq *crq;
 -      u64 buffer[2] = { 0, 0 };
 -      long rc;
 -
 -      crq = (struct viosrp_crq *)&buffer;
 -      crq->valid = VALID_CMD_RESP_EL;
 -      crq->format = (u8)MESSAGE_IN_CRQ;
 -      crq->status = PING_RESPONSE;
 -
 -      rc = h_send_crq(vscsi->dds.unit_id, cpu_to_be64(buffer[MSG_HI]),
 -                      cpu_to_be64(buffer[MSG_LOW]));
 -
 -      switch (rc) {
 -      case H_SUCCESS:
 -              break;
 -      case H_CLOSED:
 -              vscsi->flags |= CLIENT_FAILED;
 -      case H_DROPPED:
 -              vscsi->flags |= RESPONSE_Q_DOWN;
 -      case H_REMOTE_PARM:
 -              dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n",
 -                      rc);
 -              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 -              break;
 -      default:
 -              dev_err(&vscsi->dev, "ping_response: h_send_crq returned unknown rc %ld\n",
 -                      rc);
 -              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
 -              break;
 -      }
 -
 -      return rc;
 -}
 -
 -/**
 - * ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message
 - * @vscsi:    Pointer to our adapter structure
 - *
 - * Must be called with interrupt lock held.
 - */
 -static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi)
 -{
 -      long rc = ADAPT_SUCCESS;
 -
 -      switch (vscsi->state) {
 -      case NO_QUEUE:
 -      case ERR_DISCONNECT:
 -      case ERR_DISCONNECT_RECONNECT:
 -      case ERR_DISCONNECTED:
 -      case UNCONFIGURING:
 -      case UNDEFINED:
 -              rc = ERROR;
 -              break;
 -
 -      case WAIT_CONNECTION:
 -              vscsi->state = CONNECTED;
 -              break;
 -
 -      case WAIT_IDLE:
 -      case SRP_PROCESSING:
 -      case CONNECTED:
 -      case WAIT_ENABLED:
 -      case PART_UP_WAIT_ENAB:
 -      default:
 -              rc = ERROR;
 -              dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n",
 -                      vscsi->state);
 -              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 -              break;
 -      }
 -
 -      return rc;
 -}
 -
 -/**
 - * ibmvscsis_handle_init_msg() - Respond to an Init Message
 - * @vscsi:    Pointer to our adapter structure
 - *
 - * Must be called with interrupt lock held.
 - */
 -static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi)
 -{
 -      long rc = ADAPT_SUCCESS;
 -
 -      switch (vscsi->state) {
 -      case WAIT_ENABLED:
 -              vscsi->state = PART_UP_WAIT_ENAB;
 -              break;
 +                      tsk = &vio_iu(iue)->srp.tsk_mgmt;
 +                      pr_debug("tsk_mgmt tag: %llu (0x%llx)\n", tsk->tag,
 +                               tsk->tag);
 +                      cmd->rsp.tag = tsk->tag;
 +                      vscsi->debit += 1;
 +                      cmd->type = TASK_MANAGEMENT;
 +                      list_add_tail(&cmd->list, &vscsi->schedule_q);
 +                      queue_work(vscsi->work_q, &cmd->work);
 +                      break;
  
 -      case WAIT_CONNECTION:
 -              rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
 -              switch (rc) {
 -              case H_SUCCESS:
 -                      vscsi->state = CONNECTED;
 +              case SRP_CMD:
 +                      pr_debug("srp_cmd tag: %llu (0x%llx)\n", srp->tag,
 +                               srp->tag);
 +                      cmd->rsp.tag = srp->tag;
 +                      vscsi->debit += 1;
 +                      cmd->type = SCSI_CDB;
 +                      /*
 +                       * We want to keep track of work waiting for
 +                       * the workqueue.
 +                       */
 +                      list_add_tail(&cmd->list, &vscsi->schedule_q);
 +                      queue_work(vscsi->work_q, &cmd->work);
                        break;
  
 -              case H_PARAMETER:
 -                      dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
 -                              rc);
 -                      ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
 +              case SRP_I_LOGOUT:
 +                      rc = ibmvscsis_srp_i_logout(vscsi, cmd, crq);
                        break;
  
 -              case H_DROPPED:
 -                      dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
 -                              rc);
 -                      rc = ERROR;
 +              case SRP_CRED_RSP:
 +              case SRP_AER_RSP:
 +              default:
 +                      ibmvscsis_free_cmd_resources(vscsi, cmd);
 +                      dev_err(&vscsi->dev, "invalid srp cmd, opcode %d\n",
 +                              (uint)srp->opcode);
                        ibmvscsis_post_disconnect(vscsi,
                                                  ERR_DISCONNECT_RECONNECT, 0);
                        break;
 -
 -              case H_CLOSED:
 -                      pr_warn("init_msg: failed to send, rc %ld\n", rc);
 -                      rc = 0;
 -                      break;
                }
 -              break;
 -
 -      case UNDEFINED:
 -              rc = ERROR;
 -              break;
 -
 -      case UNCONFIGURING:
 -              break;
 -
 -      case PART_UP_WAIT_ENAB:
 -      case CONNECTED:
 -      case SRP_PROCESSING:
 -      case WAIT_IDLE:
 -      case NO_QUEUE:
 -      case ERR_DISCONNECT:
 -      case ERR_DISCONNECT_RECONNECT:
 -      case ERR_DISCONNECTED:
 -      default:
 -              rc = ERROR;
 -              dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n",
 +      } else if (srp->opcode == SRP_LOGIN_REQ && vscsi->state == CONNECTED) {
 +              rc = ibmvscsis_srp_login(vscsi, cmd, crq);
 +      } else {
 +              ibmvscsis_free_cmd_resources(vscsi, cmd);
 +              dev_err(&vscsi->dev, "Invalid state %d to handle srp cmd\n",
                        vscsi->state);
                ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 -              break;
        }
 -
 -      return rc;
  }
  
  /**
 - * ibmvscsis_init_msg() - Respond to an init message
 + * ibmvscsis_ping_response() - Respond to a ping request
   * @vscsi:    Pointer to our adapter structure
 - * @crq:      Pointer to CRQ element containing the Init Message
 + *
 + * Let the client know that the server is alive and waiting on
 + * its native I/O stack.
 + * If any type of error occurs from the call to queue a ping
 + * response then the client is either not accepting or receiving
 + * interrupts.  Disconnect with an error.
   *
   * EXECUTION ENVIRONMENT:
   *    Interrupt, interrupt lock held
   */
 -static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq)
 +static long ibmvscsis_ping_response(struct scsi_info *vscsi)
  {
 -      long rc = ADAPT_SUCCESS;
 +      struct viosrp_crq *crq;
 +      u64 buffer[2] = { 0, 0 };
 +      long rc;
  
 -      pr_debug("init_msg: state 0x%hx\n", vscsi->state);
 +      crq = (struct viosrp_crq *)&buffer;
 +      crq->valid = VALID_CMD_RESP_EL;
 +      crq->format = (u8)MESSAGE_IN_CRQ;
 +      crq->status = PING_RESPONSE;
  
 -      rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
 -                    (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
 -                    0);
 -      if (rc == H_SUCCESS) {
 -              vscsi->client_data.partition_number =
 -                      be64_to_cpu(*(u64 *)vscsi->map_buf);
 -              pr_debug("init_msg, part num %d\n",
 -                       vscsi->client_data.partition_number);
 -      } else {
 -              pr_debug("init_msg h_vioctl rc %ld\n", rc);
 -              rc = ADAPT_SUCCESS;
 -      }
 +      rc = h_send_crq(vscsi->dds.unit_id, cpu_to_be64(buffer[MSG_HI]),
 +                      cpu_to_be64(buffer[MSG_LOW]));
  
 -      if (crq->format == INIT_MSG) {
 -              rc = ibmvscsis_handle_init_msg(vscsi);
 -      } else if (crq->format == INIT_COMPLETE_MSG) {
 -              rc = ibmvscsis_handle_init_compl_msg(vscsi);
 -      } else {
 -              rc = ERROR;
 -              dev_err(&vscsi->dev, "init_msg: invalid format %d\n",
 -                      (uint)crq->format);
 +      switch (rc) {
 +      case H_SUCCESS:
 +              break;
 +      case H_CLOSED:
 +              vscsi->flags |= CLIENT_FAILED;
 +      case H_DROPPED:
 +              vscsi->flags |= RESPONSE_Q_DOWN;
 +      case H_REMOTE_PARM:
 +              dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n",
 +                      rc);
                ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 +              break;
 +      default:
 +              dev_err(&vscsi->dev, "ping_response: h_send_crq returned unknown rc %ld\n",
 +                      rc);
 +              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
 +              break;
        }
  
        return rc;
@@@ -2385,7 -2392,7 +2386,7 @@@ static long ibmvscsis_parse_command(str
                break;
  
        case VALID_TRANS_EVENT:
 -              rc =  ibmvscsis_trans_event(vscsi, crq);
 +              rc = ibmvscsis_trans_event(vscsi, crq);
                break;
  
        case VALID_INIT_MSG:
@@@ -2516,6 -2523,7 +2517,6 @@@ static void ibmvscsis_parse_cmd(struct 
                dev_err(&vscsi->dev, "0x%llx: parsing SRP descriptor table failed.\n",
                        srp->tag);
                goto fail;
 -              return;
        }
  
        cmd->rsp.sol_not = srp->sol_not;
                               data_len, attr, dir, 0);
        if (rc) {
                dev_err(&vscsi->dev, "target_submit_cmd failed, rc %d\n", rc);
 +              spin_lock_bh(&vscsi->intr_lock);
 +              list_del(&cmd->list);
 +              ibmvscsis_free_cmd_resources(vscsi, cmd);
 +              spin_unlock_bh(&vscsi->intr_lock);
                goto fail;
        }
        return;
@@@ -2635,9 -2639,6 +2636,9 @@@ static void ibmvscsis_parse_task(struc
                if (rc) {
                        dev_err(&vscsi->dev, "target_submit_tmr failed, rc %d\n",
                                rc);
 +                      spin_lock_bh(&vscsi->intr_lock);
 +                      list_del(&cmd->list);
 +                      spin_unlock_bh(&vscsi->intr_lock);
                        cmd->se_cmd.se_tmr_req->response =
                                TMR_FUNCTION_REJECTED;
                }
@@@ -2785,6 -2786,36 +2786,6 @@@ static irqreturn_t ibmvscsis_interrupt(
        return IRQ_HANDLED;
  }
  
 -/**
 - * ibmvscsis_check_q() - Helper function to Check Init Message Valid
 - * @vscsi:    Pointer to our adapter structure
 - *
 - * Checks if a initialize message was queued by the initiatior
 - * while the timing window was open.  This function is called from
 - * probe after the CRQ is created and interrupts are enabled.
 - * It would only be used by adapters who wait for some event before
 - * completing the init handshake with the client.  For ibmvscsi, this
 - * event is waiting for the port to be enabled.
 - *
 - * EXECUTION ENVIRONMENT:
 - *    Process level only, interrupt lock held
 - */
 -static long ibmvscsis_check_q(struct scsi_info *vscsi)
 -{
 -      uint format;
 -      long rc;
 -
 -      rc = ibmvscsis_check_init_msg(vscsi, &format);
 -      if (rc)
 -              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
 -      else if (format == UNUSED_FORMAT)
 -              vscsi->state = WAIT_ENABLED;
 -      else
 -              vscsi->state = PART_UP_WAIT_ENAB;
 -
 -      return rc;
 -}
 -
  /**
   * ibmvscsis_enable_change_state() - Set new state based on enabled status
   * @vscsi:    Pointer to our adapter structure
   */
  static long ibmvscsis_enable_change_state(struct scsi_info *vscsi)
  {
 +      int bytes;
        long rc = ADAPT_SUCCESS;
  
 -handle_state_change:
 -      switch (vscsi->state) {
 -      case WAIT_ENABLED:
 -              rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
 -              switch (rc) {
 -              case H_SUCCESS:
 -              case H_DROPPED:
 -              case H_CLOSED:
 -                      vscsi->state =  WAIT_CONNECTION;
 -                      rc = ADAPT_SUCCESS;
 -                      break;
 -
 -              case H_PARAMETER:
 -                      break;
 -
 -              case H_HARDWARE:
 -                      break;
 -
 -              default:
 -                      vscsi->state = UNDEFINED;
 -                      rc = H_HARDWARE;
 -                      break;
 -              }
 -              break;
 -      case PART_UP_WAIT_ENAB:
 -              rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
 -              switch (rc) {
 -              case H_SUCCESS:
 -                      vscsi->state = CONNECTED;
 -                      rc = ADAPT_SUCCESS;
 -                      break;
 -
 -              case H_DROPPED:
 -              case H_CLOSED:
 -                      vscsi->state = WAIT_ENABLED;
 -                      goto handle_state_change;
 -
 -              case H_PARAMETER:
 -                      break;
 -
 -              case H_HARDWARE:
 -                      break;
 -
 -              default:
 -                      rc = H_HARDWARE;
 -                      break;
 -              }
 -              break;
 -
 -      case WAIT_CONNECTION:
 -      case WAIT_IDLE:
 -      case SRP_PROCESSING:
 -      case CONNECTED:
 -              rc = ADAPT_SUCCESS;
 -              break;
 -              /* should not be able to get here */
 -      case UNCONFIGURING:
 -              rc = ERROR;
 -              vscsi->state = UNDEFINED;
 -              break;
 +      bytes = vscsi->cmd_q.size * PAGE_SIZE;
 +      rc = h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, bytes);
 +      if (rc == H_CLOSED || rc == H_SUCCESS) {
 +              vscsi->state = WAIT_CONNECTION;
 +              rc = ibmvscsis_establish_new_q(vscsi);
 +      }
  
 -              /* driver should never allow this to happen */
 -      case ERR_DISCONNECT:
 -      case ERR_DISCONNECT_RECONNECT:
 -      default:
 -              dev_err(&vscsi->dev, "in invalid state %d during enable_change_state\n",
 -                      vscsi->state);
 -              rc = ADAPT_SUCCESS;
 -              break;
 +      if (rc != ADAPT_SUCCESS) {
 +              vscsi->state = ERR_DISCONNECTED;
 +              vscsi->flags |= RESPONSE_Q_DOWN;
        }
  
        return rc;
   */
  static long ibmvscsis_create_command_q(struct scsi_info *vscsi, int num_cmds)
  {
 -      long rc = 0;
        int pages;
        struct vio_dev *vdev = vscsi->dma_dev;
  
                return -ENOMEM;
        }
  
 -      rc =  h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, PAGE_SIZE);
 -      if (rc) {
 -              if (rc == H_CLOSED) {
 -                      vscsi->state = WAIT_ENABLED;
 -                      rc = 0;
 -              } else {
 -                      dma_unmap_single(&vdev->dev, vscsi->cmd_q.crq_token,
 -                                       PAGE_SIZE, DMA_BIDIRECTIONAL);
 -                      free_page((unsigned long)vscsi->cmd_q.base_addr);
 -                      rc = -ENODEV;
 -              }
 -      } else {
 -              vscsi->state = WAIT_ENABLED;
 -      }
 -
 -      return rc;
 +      return 0;
  }
  
  /**
@@@ -3166,7 -3271,7 +3167,7 @@@ static void ibmvscsis_handle_crq(unsign
        /*
         * if we are in a path where we are waiting for all pending commands
         * to complete because we received a transport event and anything in
 -       * the command queue is for a new connection,  do nothing
 +       * the command queue is for a new connection, do nothing
         */
        if (TARGET_STOP(vscsi)) {
                vio_enable_interrupts(vscsi->dma_dev);
@@@ -3210,7 -3315,7 +3211,7 @@@ cmd_work
                                 * everything but transport events on the queue
                                 *
                                 * need to decrement the queue index so we can
 -                               * look at the elment again
 +                               * look at the element again
                                 */
                                if (vscsi->cmd_q.index)
                                        vscsi->cmd_q.index -= 1;
@@@ -3274,8 -3379,7 +3275,8 @@@ static int ibmvscsis_probe(struct vio_d
        INIT_LIST_HEAD(&vscsi->waiting_rsp);
        INIT_LIST_HEAD(&vscsi->active_q);
  
 -      snprintf(vscsi->tport.tport_name, 256, "%s", dev_name(&vdev->dev));
 +      snprintf(vscsi->tport.tport_name, IBMVSCSIS_NAMELEN, "%s",
 +               dev_name(&vdev->dev));
  
        pr_debug("probe tport_name: %s\n", vscsi->tport.tport_name);
  
        strncat(vscsi->eye, vdev->name, MAX_EYE);
  
        vscsi->dds.unit_id = vdev->unit_address;
 +      strncpy(vscsi->dds.partition_name, partition_name,
 +              sizeof(vscsi->dds.partition_name));
 +      vscsi->dds.partition_num = partition_number;
  
        spin_lock_bh(&ibmvscsis_dev_lock);
        list_add_tail(&vscsi->list, &ibmvscsis_dev_list);
                     (unsigned long)vscsi);
  
        init_completion(&vscsi->wait_idle);
 +      init_completion(&vscsi->unconfig);
  
        snprintf(wq_name, 24, "ibmvscsis%s", dev_name(&vdev->dev));
        vscsi->work_q = create_workqueue(wq_name);
                goto destroy_WQ;
        }
  
 -      spin_lock_bh(&vscsi->intr_lock);
 -      vio_enable_interrupts(vdev);
 -      if (rc) {
 -              dev_err(&vscsi->dev, "enabling interrupts failed, rc %d\n", rc);
 -              rc = -ENODEV;
 -              spin_unlock_bh(&vscsi->intr_lock);
 -              goto free_irq;
 -      }
 -
 -      if (ibmvscsis_check_q(vscsi)) {
 -              rc = ERROR;
 -              dev_err(&vscsi->dev, "probe: check_q failed, rc %d\n", rc);
 -              spin_unlock_bh(&vscsi->intr_lock);
 -              goto disable_interrupt;
 -      }
 -      spin_unlock_bh(&vscsi->intr_lock);
 +      vscsi->state = WAIT_ENABLED;
  
        dev_set_drvdata(&vdev->dev, vscsi);
  
        return 0;
  
 -disable_interrupt:
 -      vio_disable_interrupts(vdev);
 -free_irq:
 -      free_irq(vdev->irq, vscsi);
  destroy_WQ:
        destroy_workqueue(vscsi->work_q);
  unmap_buf:
@@@ -3425,11 -3544,10 +3426,11 @@@ static int ibmvscsis_remove(struct vio_
  
        pr_debug("remove (%s)\n", dev_name(&vscsi->dma_dev->dev));
  
 -      /*
 -       * TBD: Need to handle if there are commands on the waiting_rsp q
 -       *      Actually, can there still be cmds outstanding to tcm?
 -       */
 +      spin_lock_bh(&vscsi->intr_lock);
 +      ibmvscsis_post_disconnect(vscsi, UNCONFIGURING, 0);
 +      vscsi->flags |= CFG_SLEEPING;
 +      spin_unlock_bh(&vscsi->intr_lock);
 +      wait_for_completion(&vscsi->unconfig);
  
        vio_disable_interrupts(vdev);
        free_irq(vdev->irq, vscsi);
                         DMA_BIDIRECTIONAL);
        kfree(vscsi->map_buf);
        tasklet_kill(&vscsi->work_task);
 -      ibmvscsis_unregister_command_q(vscsi);
        ibmvscsis_destroy_command_q(vscsi);
        ibmvscsis_freetimer(vscsi);
        ibmvscsis_free_cmds(vscsi);
@@@ -3491,7 -3610,7 +3492,7 @@@ static int ibmvscsis_get_system_info(vo
  
        num = of_get_property(rootdn, "ibm,partition-no", NULL);
        if (num)
 -              partition_number = *num;
 +              partition_number = of_read_number(num, 1);
  
        of_node_put(rootdn);
  
@@@ -3785,22 -3904,18 +3786,22 @@@ static ssize_t ibmvscsis_tpg_enable_sto
        }
  
        if (tmp) {
 -              tport->enabled = true;
                spin_lock_bh(&vscsi->intr_lock);
 +              tport->enabled = true;
                lrc = ibmvscsis_enable_change_state(vscsi);
                if (lrc)
                        pr_err("enable_change_state failed, rc %ld state %d\n",
                               lrc, vscsi->state);
                spin_unlock_bh(&vscsi->intr_lock);
        } else {
 +              spin_lock_bh(&vscsi->intr_lock);
                tport->enabled = false;
 +              /* This simulates the server going down */
 +              ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
 +              spin_unlock_bh(&vscsi->intr_lock);
        }
  
 -      pr_debug("tpg_enable_store, state %d\n", vscsi->state);
 +      pr_debug("tpg_enable_store, tmp %ld, state %d\n", tmp, vscsi->state);
  
        return count;
  }
@@@ -3869,10 -3984,10 +3870,10 @@@ static struct attribute *ibmvscsis_dev_
  ATTRIBUTE_GROUPS(ibmvscsis_dev);
  
  static struct class ibmvscsis_class = {
 -      .name           = "ibmvscsis",
 -      .dev_release    = ibmvscsis_dev_release,
 -      .class_attrs    = ibmvscsis_class_attrs,
 -      .dev_groups     = ibmvscsis_dev_groups,
 +      .name           = "ibmvscsis",
 +      .dev_release    = ibmvscsis_dev_release,
 +      .class_attrs    = ibmvscsis_class_attrs,
 +      .dev_groups     = ibmvscsis_dev_groups,
  };
  
  static struct vio_device_id ibmvscsis_device_table[] = {
index 98b0ca79a5c5e2e04c526ca741c504377c75ca9e,3fb32fa2658450d0ba202d92cfa05707460ec3fc..65c6189885ab08f24212bce5f008c1973539a0f7
@@@ -26,6 -26,7 +26,7 @@@
  #ifndef __H_IBMVSCSI_TGT
  #define __H_IBMVSCSI_TGT
  
+ #include <linux/interrupt.h>
  #include "libsrp.h"
  
  #define SYS_ID_NAME_LEN               64
@@@ -204,6 -205,8 +205,6 @@@ struct scsi_info 
        struct list_head waiting_rsp;
  #define NO_QUEUE                    0x00
  #define WAIT_ENABLED                0X01
 -      /* driver has received an initialize command */
 -#define PART_UP_WAIT_ENAB           0x02
  #define WAIT_CONNECTION             0x04
        /* have established a connection */
  #define CONNECTED                   0x08
  #define SCHEDULE_DISCONNECT           0x00400
        /* disconnect handler is scheduled */
  #define DISCONNECT_SCHEDULED          0x00800
 +      /* remove function is sleeping */
 +#define CFG_SLEEPING                  0x01000
        u32 flags;
        /* adapter lock */
        spinlock_t intr_lock;
  
        struct workqueue_struct *work_q;
        struct completion wait_idle;
 +      struct completion unconfig;
        struct device dev;
        struct vio_dev *dma_dev;
        struct srp_target target;
index 19f18485a854ff1dbe8a4db1105fca4b75009931,df083cc4d1d69d6e5d01db221170efab9d06e333..d8efddf6f312e9df82c81d2edeefa731a7c4cac8
@@@ -9,6 -9,7 +9,7 @@@
  
  #include <linux/delay.h>
  #include <linux/slab.h>
+ #include <linux/t10-pi.h>
  #include <scsi/scsi_tcq.h>
  #include <scsi/scsi_bsg_fc.h>
  #include <scsi/scsi_eh.h>
@@@ -1356,8 -1357,7 +1357,8 @@@ qla2x00_ct_entry(scsi_qla_host_t *vha, 
        const char func[] = "CT_IOCB";
        const char *type;
        srb_t *sp;
 -      struct fc_bsg_job *bsg_job;
 +      struct bsg_job *bsg_job;
 +      struct fc_bsg_reply *bsg_reply;
        uint16_t comp_status;
        int res;
  
                return;
  
        bsg_job = sp->u.bsg_job;
 +      bsg_reply = bsg_job->reply;
  
        type = "ct pass-through";
  
        /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
         * fc payload  to the caller
         */
 -      bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 +      bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
  
        if (comp_status != CS_COMPLETE) {
                if (comp_status == CS_DATA_UNDERRUN) {
                        res = DID_OK << 16;
 -                      bsg_job->reply->reply_payload_rcv_len =
 +                      bsg_reply->reply_payload_rcv_len =
                            le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
  
                        ql_log(ql_log_warn, vha, 0x5048,
                            "CT pass-through-%s error "
                            "comp_status-status=0x%x total_byte = 0x%x.\n",
                            type, comp_status,
 -                          bsg_job->reply->reply_payload_rcv_len);
 +                          bsg_reply->reply_payload_rcv_len);
                } else {
                        ql_log(ql_log_warn, vha, 0x5049,
                            "CT pass-through-%s error "
                            "comp_status-status=0x%x.\n", type, comp_status);
                        res = DID_ERROR << 16;
 -                      bsg_job->reply->reply_payload_rcv_len = 0;
 +                      bsg_reply->reply_payload_rcv_len = 0;
                }
                ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
                    (uint8_t *)pkt, sizeof(*pkt));
        } else {
                res = DID_OK << 16;
 -              bsg_job->reply->reply_payload_rcv_len =
 +              bsg_reply->reply_payload_rcv_len =
                    bsg_job->reply_payload.payload_len;
                bsg_job->reply_len = 0;
        }
@@@ -1415,8 -1414,7 +1416,8 @@@ qla24xx_els_ct_entry(scsi_qla_host_t *v
        const char func[] = "ELS_CT_IOCB";
        const char *type;
        srb_t *sp;
 -      struct fc_bsg_job *bsg_job;
 +      struct bsg_job *bsg_job;
 +      struct fc_bsg_reply *bsg_reply;
        uint16_t comp_status;
        uint32_t fw_status[3];
        uint8_t* fw_sts_ptr;
        if (!sp)
                return;
        bsg_job = sp->u.bsg_job;
 +      bsg_reply = bsg_job->reply;
  
        type = NULL;
        switch (sp->type) {
        /* return FC_CTELS_STATUS_OK and leave the decoding of the ELS/CT
         * fc payload  to the caller
         */
 -      bsg_job->reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
 +      bsg_reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK;
        bsg_job->reply_len = sizeof(struct fc_bsg_reply) + sizeof(fw_status);
  
        if (comp_status != CS_COMPLETE) {
                if (comp_status == CS_DATA_UNDERRUN) {
                        res = DID_OK << 16;
 -                      bsg_job->reply->reply_payload_rcv_len =
 +                      bsg_reply->reply_payload_rcv_len =
                            le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->total_byte_count);
  
                        ql_dbg(ql_dbg_user, vha, 0x503f,
                            le16_to_cpu(((struct els_sts_entry_24xx *)
                                    pkt)->error_subcode_2));
                        res = DID_ERROR << 16;
 -                      bsg_job->reply->reply_payload_rcv_len = 0;
 +                      bsg_reply->reply_payload_rcv_len = 0;
                        fw_sts_ptr = ((uint8_t*)bsg_job->req->sense) + sizeof(struct fc_bsg_reply);
                        memcpy( fw_sts_ptr, fw_status, sizeof(fw_status));
                }
        }
        else {
                res =  DID_OK << 16;
 -              bsg_job->reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
 +              bsg_reply->reply_payload_rcv_len = bsg_job->reply_payload.payload_len;
                bsg_job->reply_len = 0;
        }
  
@@@ -1908,9 -1905,7 +1909,9 @@@ qla25xx_process_bidir_status_iocb(scsi_
        uint16_t        scsi_status;
        uint16_t thread_id;
        uint32_t rval = EXT_STATUS_OK;
 -      struct fc_bsg_job *bsg_job = NULL;
 +      struct bsg_job *bsg_job = NULL;
 +      struct fc_bsg_request *bsg_request;
 +      struct fc_bsg_reply *bsg_reply;
        sts_entry_t *sts;
        struct sts_entry_24xx *sts24;
        sts = (sts_entry_t *) pkt;
        }
  
        sp = req->outstanding_cmds[index];
 -      if (sp) {
 -              /* Free outstanding command slot. */
 -              req->outstanding_cmds[index] = NULL;
 -              bsg_job = sp->u.bsg_job;
 -      } else {
 +      if (!sp) {
                ql_log(ql_log_warn, vha, 0x70b0,
                    "Req:%d: Invalid ISP SCSI completion handle(0x%x)\n",
                    req->id, index);
                return;
        }
  
 +      /* Free outstanding command slot. */
 +      req->outstanding_cmds[index] = NULL;
 +      bsg_job = sp->u.bsg_job;
 +      bsg_request = bsg_job->request;
 +      bsg_reply = bsg_job->reply;
 +
        if (IS_FWI2_CAPABLE(ha)) {
                comp_status = le16_to_cpu(sts24->comp_status);
                scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
                scsi_status = le16_to_cpu(sts->scsi_status) & SS_MASK;
        }
  
 -      thread_id = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
 +      thread_id = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
        switch (comp_status) {
        case CS_COMPLETE:
                if (scsi_status == 0) {
 -                      bsg_job->reply->reply_payload_rcv_len =
 +                      bsg_reply->reply_payload_rcv_len =
                                        bsg_job->reply_payload.payload_len;
                        vha->qla_stats.input_bytes +=
 -                              bsg_job->reply->reply_payload_rcv_len;
 +                              bsg_reply->reply_payload_rcv_len;
                        vha->qla_stats.input_requests++;
                        rval = EXT_STATUS_OK;
                }
                rval = EXT_STATUS_ERR;
                break;
        }
 -      bsg_job->reply->reply_payload_rcv_len = 0;
 +      bsg_reply->reply_payload_rcv_len = 0;
  
  done:
        /* Return the vendor specific reply to API */
 -      bsg_job->reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
 +      bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
        /* Always return DID_OK, bsg will send the vendor specific response
         * in this case only */
index a35a347ec357ad48626cc4083eca16588c29eb8b,3bf6384c0f96ad8f477609d4569497bb82a9d614..54b36c9835be3ae2127cb1f447321eba73b824ac
@@@ -143,13 -143,13 +143,13 @@@ static ssize_t target_core_item_dbroot_
                pr_err("db_root: cannot open: %s\n", db_root_stage);
                return -EINVAL;
        }
 -      if (!S_ISDIR(fp->f_inode->i_mode)) {
 +      if (!S_ISDIR(file_inode(fp)->i_mode)) {
-               filp_close(fp, 0);
+               filp_close(fp, NULL);
                mutex_unlock(&g_tf_lock);
                pr_err("db_root: not a directory: %s\n", db_root_stage);
                return -EINVAL;
        }
-       filp_close(fp, 0);
+       filp_close(fp, NULL);
  
        strncpy(db_root, db_root_stage, read_bytes);
  
index 2b3c8564ace8154548349c6a71872f0b1aceeadb,2e331008d30b2cba37dea2afa11084ebacd99ec3..8041710b697298ec7073c4e5910849bd1a154703
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/uio_driver.h>
  #include <linux/stringify.h>
  #include <linux/bitops.h>
+ #include <linux/highmem.h>
  #include <net/genetlink.h>
  #include <scsi/scsi_common.h>
  #include <scsi/scsi_proto.h>
@@@ -147,8 -148,8 +148,8 @@@ static const struct genl_multicast_grou
  };
  
  /* Our generic netlink family */
 -static struct genl_family tcmu_genl_family = {
 -      .id = GENL_ID_GENERATE,
 +static struct genl_family tcmu_genl_family __ro_after_init = {
 +      .module = THIS_MODULE,
        .hdrsize = 0,
        .name = "TCM-USER",
        .version = 1,
@@@ -537,7 -538,7 +538,7 @@@ tcmu_queue_cmd(struct se_cmd *se_cmd
        struct se_device *se_dev = se_cmd->se_dev;
        struct tcmu_dev *udev = TCMU_DEV(se_dev);
        struct tcmu_cmd *tcmu_cmd;
-       int ret;
+       sense_reason_t ret;
  
        tcmu_cmd = tcmu_alloc_cmd(se_cmd);
        if (!tcmu_cmd)
@@@ -685,8 -686,6 +686,6 @@@ static int tcmu_check_expired_cmd(int i
        target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
        cmd->se_cmd = NULL;
  
-       kmem_cache_free(tcmu_cmd_cache, cmd);
        return 0;
  }
  
diff --combined include/linux/configfs.h
index 9a30b921f7401487cb6238b9bcb6e9f096e9a39f,9fc9843c0300990578eec28724db2d7f01e0d090..2319b8c108e87b9e87c11cc4c9aa314d24eb0364
  #ifndef _CONFIGFS_H_
  #define _CONFIGFS_H_
  
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <linux/list.h>
- #include <linux/kref.h>
- #include <linux/mutex.h>
- #include <linux/err.h>
- #include <linux/atomic.h>
+ #include <linux/stat.h>   /* S_IRUGO */
+ #include <linux/types.h>  /* ssize_t */
+ #include <linux/list.h>   /* struct list_head */
+ #include <linux/kref.h>   /* struct kref */
+ #include <linux/mutex.h>  /* struct mutex */
  
  #define CONFIGFS_ITEM_NAME_LEN        20
  
@@@ -228,7 -225,7 +225,7 @@@ static struct configfs_bin_attribute _p
  struct configfs_item_operations {
        void (*release)(struct config_item *);
        int (*allow_link)(struct config_item *src, struct config_item *target);
 -      int (*drop_link)(struct config_item *src, struct config_item *target);
 +      void (*drop_link)(struct config_item *src, struct config_item *target);
  };
  
  struct configfs_group_operations {
index 00558287936d9a0bcc2e386e8fa0b2bcb9af4f97,ca8ec7218f39825d21eaae11348972127c615a3a..29e6858bb1648b636dcce48072f9fe43e5a8a884
@@@ -1,14 -1,10 +1,10 @@@
  #ifndef TARGET_CORE_BASE_H
  #define TARGET_CORE_BASE_H
  
- #include <linux/in.h>
- #include <linux/configfs.h>
- #include <linux/dma-mapping.h>
- #include <linux/blkdev.h>
- #include <linux/percpu_ida.h>
- #include <linux/t10-pi.h>
- #include <net/sock.h>
- #include <net/tcp.h>
+ #include <linux/configfs.h>      /* struct config_group */
+ #include <linux/dma-direction.h> /* enum dma_data_direction */
+ #include <linux/percpu_ida.h>    /* struct percpu_ida */
+ #include <linux/semaphore.h>     /* struct semaphore */
  
  #define TARGET_CORE_VERSION           "v5.0"
  
@@@ -149,7 -145,7 +145,7 @@@ enum se_cmd_flags_table 
   * Used by transport_send_check_condition_and_sense()
   * to signal which ASC/ASCQ sense payload should be built.
   */
 -typedef unsigned __bitwise__ sense_reason_t;
 +typedef unsigned __bitwise sense_reason_t;
  
  enum tcm_sense_reason_table {
  #define R(x)  (__force sense_reason_t )(x)
This page took 0.170355 seconds and 4 git commands to generate.