Print this page
    
NEX-3414 CLONE - Port 3339 iscsi/fs:5 causes panic on initiator
NEX-3419 CLONE - Run multi initiator sessions to a single target test can panic the initiator
Reviewed by: Steve Peng <steve.peng@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
          +++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_io.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2000 by Cisco Systems, Inc.  All rights reserved.
  23   23   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
       24 + * Copyright 2011, 2015 Nexenta Systems, Inc. All rights reserved.
  25   25   *
  26   26   * iSCSI Pseudo HBA Driver
  27   27   */
  28   28  
  29   29  #include <sys/socket.h>         /* networking stuff */
  30   30  #include <sys/t_kuser.h>        /* networking stuff */
  31   31  #include <sys/tihdr.h>          /* networking stuff */
  32   32  #include <sys/strsubr.h>        /* networking stuff */
  33   33  #include <netinet/tcp.h>        /* TCP_NODELAY */
  34   34  #include <sys/socketvar.h>      /* _ALLOC_SLEEP */
  35   35  #include <sys/strsun.h>         /* DB_TYPE() */
  36   36  #include <sys/scsi/generic/sense.h>
  37   37  
  38   38  #include "iscsi.h"              /* iscsi driver */
  39   39  #include <sys/iscsi_protocol.h> /* iscsi protocol */
  40   40  
  41   41  #define ISCSI_INI_TASK_TTT      0xffffffff
  42   42  #define ISCSI_CONN_TIEMOUT_DETECT       20
  43   43  
  44   44  boolean_t iscsi_io_logging = B_FALSE;
  45   45  
  46   46  #define ISCSI_CHECK_SCSI_READ(ICHK_CMD, ICHK_HDR, ICHK_LEN, ICHK_TYPE)  \
  47   47          if (idm_pattern_checking)  {                                    \
  48   48                  struct scsi_pkt *pkt = (ICHK_CMD)->cmd_un.scsi.pkt;     \
  49   49                  if (((ICHK_HDR)->response == 0) &&                      \
  50   50                      ((ICHK_HDR)->cmd_status == 0) &&                    \
  51   51                      ((pkt->pkt_cdbp[0] == SCMD_READ_G1) ||              \
  52   52                      (pkt->pkt_cdbp[0] == SCMD_READ_G4) ||               \
  53   53                      (pkt->pkt_cdbp[0] == SCMD_READ) ||                  \
  54   54                      (pkt->pkt_cdbp[0] == SCMD_READ_G5))) {              \
  55   55                          idm_buf_t *idb = (ICHK_CMD)->cmd_un.scsi.ibp_ibuf; \
  56   56                          IDM_BUFPAT_CHECK(idb, ICHK_LEN, ICHK_TYPE); \
  57   57                  }                                               \
  58   58          }
  59   59  
  60   60  /* Size of structure scsi_arq_status without sense data. */
  61   61  #define ISCSI_ARQ_STATUS_NOSENSE_LEN    (sizeof (struct scsi_arq_status) - \
  62   62      sizeof (struct scsi_extended_sense))
  63   63  
  64   64  /* generic io helpers */
  65   65  static uint32_t n2h24(uchar_t *ptr);
  66   66  static int iscsi_sna_lt(uint32_t n1, uint32_t n2);
  67   67  void iscsi_update_flow_control(iscsi_sess_t *isp,
  68   68      uint32_t max, uint32_t exp);
  69   69  static iscsi_status_t iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp,
  70   70      idm_conn_t *ic, iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp);
  71   71  static iscsi_status_t iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp,
  72   72      iscsi_hdr_t *ihp, iscsi_cmd_t **icmdp);
  73   73  static void iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
  74   74      idm_status_t status);
  75   75  static void iscsi_drop_conn_cleanup(iscsi_conn_t *icp);
  76   76  static boolean_t iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp);
  77   77  /* callbacks from idm */
  78   78  static idm_pdu_cb_t iscsi_tx_done;
  79   79  
  80   80  /* receivers */
  81   81  static idm_status_t iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu);
  82   82  static idm_status_t iscsi_rx_process_data_rsp(idm_conn_t *ic,
  83   83      idm_pdu_t *pdu);
  84   84  static idm_status_t iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu);
  85   85  static idm_status_t iscsi_rx_process_reject_rsp(idm_conn_t *ic,
  86   86      idm_pdu_t *pdu);
  87   87  
  88   88  static idm_status_t iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic,
  89   89      iscsi_hdr_t *old_ihp);
  90   90  static idm_status_t iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic,
  91   91      idm_pdu_t *pdu);
  92   92  static idm_status_t iscsi_rx_process_logout_rsp(idm_conn_t *ic,
  93   93      idm_pdu_t *pdu);
  94   94  static idm_status_t iscsi_rx_process_async_rsp(idm_conn_t *ic,
  95   95      idm_pdu_t *pdu);
  96   96  static idm_status_t iscsi_rx_process_text_rsp(idm_conn_t *ic,
  97   97      idm_pdu_t *pdu);
  98   98  
  99   99  /* senders */
 100  100  static iscsi_status_t iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 101  101  static iscsi_status_t iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 102  102  static iscsi_status_t iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 103  103  static iscsi_status_t iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 104  104  static iscsi_status_t iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 105  105  static iscsi_status_t iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
 106  106  
 107  107  
 108  108  /* helpers */
 109  109  static void iscsi_logout_start(void *arg);
 110  110  static void iscsi_handle_passthru_callback(struct scsi_pkt *pkt);
 111  111  static void iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt);
 112  112  
 113  113  static void iscsi_timeout_checks(iscsi_sess_t *isp);
 114  114  static void iscsi_nop_checks(iscsi_sess_t *isp);
 115  115  static boolean_t iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp);
 116  116  static void iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
 117  117      iscsi_conn_t *icp);
 118  118  
 119  119  /*
 120  120   * This file contains the main guts of the iSCSI protocol layer.
 121  121   * It's broken into 5 sections; Basic helper functions, RX IO path,
 122  122   * TX IO path, Completion (IC) IO path, and watchdog (WD) routines.
 123  123   *
 124  124   * The IO flow model is similiar to the below diagram.  The
 125  125   * iscsi session, connection and command state machines are used
 126  126   * to drive IO through this flow diagram.  Reference those files
 127  127   * to get a detailed description of their respective state models
 128  128   * prior to their xxx_state_machine_function().
 129  129   *
 130  130   * tran_start() -> CMD_E1     TX_THREAD                   RX_THREAD
 131  131   *                   |            T                           T
 132  132   *                   V            T                           T
 133  133   *                PENDING_Q  --CMD_E2--> ACTIVE_Q -      --CMD_E3--+
 134  134   *                                T                \ C        T    |
 135  135   *                                T                 \M        T    |
 136  136   *                                                   D        T    |
 137  137   *                                       WD_THREAD TT|TT      T    |
 138  138   *                                                  /E        T    |
 139  139   *                                                 / 6        T    |
 140  140   *                                     ABORTING_Q<-      --CMD_E3--+
 141  141   *                                                            T    |
 142  142   *                                T                           T    |
 143  143   *                                T                                |
 144  144   *               callback()  <--CMD_E#-- COMPLETION_Q <------------+
 145  145   *                                T
 146  146   *                                T
 147  147   *                            IC_THREAD
 148  148   *
 149  149   * External and internal command are ran thru this same state
 150  150   * machine.  All commands enter the state machine by receiving an
 151  151   * ISCSI_CMD_EVENT_E1.  This event places the command into the
 152  152   * PENDING_Q.  Next when resources are available the TX_THREAD
 153  153   * issues a E2 event on the command.  This sends the command
 154  154   * to the TCP stack and places the command on the ACTIVE_Q.  While
 155  155   * on the PENDIING_Q and ACTIVE_Q, the command is monitored via the
 156  156   * WD_THREAD to ensure the pkt_time has not elapsed.  If elapsed the
 157  157   * command is issued an E6(timeout) event which moves either (if pending)
 158  158   * completed the command or (if active) moves the command to the
 159  159   * aborting queue and issues a SCSI TASK MANAGEMENT ABORT command
 160  160   * to cancel the IO request.  If the original command is completed
 161  161   * or the TASK MANAGEMENT command completes the command is moved
 162  162   * to the COMPLETION_Q via a E3 event.  The IC_THREAD then processes
 163  163   * the COMPLETION_Q and issues the scsi_pkt callback.  This
 164  164   * callback can not be processed directly from the RX_THREAD
 165  165   * because the callback might call back into the iscsi driver
 166  166   * causing a deadlock condition.
 167  167   *
 168  168   * For more details on the complete CMD state machine reference
 169  169   * the state machine diagram in iscsi_cmd.c.  The connection state
 170  170   * machine is driven via IO events in this file.  Then session
 171  171   * events are driven by the connection events.  For complete
 172  172   * details on these state machines reference iscsi_sess.c and
 173  173   * iscsi_conn.c
 174  174   */
 175  175  
 176  176  
 177  177  /*
 178  178   * +--------------------------------------------------------------------+
 179  179   * | io helper routines                                                 |
 180  180   * +--------------------------------------------------------------------+
 181  181   */
 182  182  
 183  183  /*
 184  184   * n2h24 - native to host 24 bit integer translation.
 185  185   */
 186  186  static uint32_t
 187  187  n2h24(uchar_t *ptr)
 188  188  {
 189  189          uint32_t idx;
 190  190          bcopy(ptr, &idx, 3);
 191  191          return (ntohl(idx) >> 8);
 192  192  }
 193  193  
 194  194  /*
 195  195   * iscsi_sna_lt - Serial Number Arithmetic, 32 bits, less than, RFC1982
 196  196   */
 197  197  static int
 198  198  iscsi_sna_lt(uint32_t n1, uint32_t n2)
 199  199  {
 200  200          return ((n1 != n2) &&
 201  201              (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
 202  202              ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
 203  203  }
 204  204  
 205  205  /*
 206  206   * iscsi_sna_lte - Serial Number Arithmetic, 32 bits, less than or equal,
 207  207   * RFC1982
 208  208   */
 209  209  int
 210  210  iscsi_sna_lte(uint32_t n1, uint32_t n2)
 211  211  {
 212  212          return ((n1 == n2) ||
 213  213              (((n1 < n2) && ((n2 - n1) < ISCSI_SNA32_CHECK)) ||
 214  214              ((n1 > n2) && ((n1 - n2) > ISCSI_SNA32_CHECK))));
 215  215  }
 216  216  
 217  217  /*
 218  218   * iscsi_update_flow_control - Update expcmdsn and maxcmdsn iSCSI
 219  219   * flow control information for a session
 220  220   */
 221  221  void
 222  222  iscsi_update_flow_control(iscsi_sess_t *isp, uint32_t max, uint32_t exp)
 223  223  {
 224  224          ASSERT(isp != NULL);
 225  225          ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
 226  226  
 227  227          if (!iscsi_sna_lt(max, (exp - 1))) {
 228  228  
 229  229                  if (!iscsi_sna_lte(exp, isp->sess_expcmdsn)) {
 230  230                          isp->sess_expcmdsn = exp;
 231  231                  }
 232  232  
 233  233                  if (!iscsi_sna_lte(max, isp->sess_maxcmdsn)) {
 234  234                          isp->sess_maxcmdsn = max;
 235  235                          if (iscsi_sna_lte(isp->sess_cmdsn,
 236  236                              isp->sess_maxcmdsn)) {
 237  237                                  /*
 238  238                                   * the window is open again - schedule
 239  239                                   * to send any held tasks soon
 240  240                                   */
 241  241                                  iscsi_sess_redrive_io(isp);
 242  242                          }
 243  243                  }
 244  244          }
 245  245  }
 246  246  
 247  247  
 248  248  /*
 249  249   * +--------------------------------------------------------------------+
 250  250   * | io receive and processing routines                                 |
 251  251   * +--------------------------------------------------------------------+
 252  252   */
 253  253  
 254  254  /*
 255  255   * iscsi_rx_scsi_rsp - called from idm
 256  256   * For each opcode type fan out the processing.
 257  257   */
 258  258  void
 259  259  iscsi_rx_scsi_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
 260  260  {
 261  261          iscsi_conn_t    *icp;
 262  262          iscsi_sess_t    *isp;
 263  263          iscsi_hdr_t     *ihp;
 264  264          idm_status_t    status;
 265  265  
 266  266          ASSERT(ic != NULL);
 267  267          ASSERT(pdu != NULL);
 268  268          icp             = ic->ic_handle;
 269  269          ASSERT(icp != NULL);
 270  270          ihp             = (iscsi_hdr_t *)pdu->isp_hdr;
 271  271          ASSERT(ihp != NULL);
 272  272          isp             = icp->conn_sess;
 273  273          ASSERT(isp != NULL);
 274  274  
 275  275          /* reset the session timer when we receive the response */
 276  276          isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
 277  277  
 278  278          /* fan out the hdr processing */
 279  279          switch (ihp->opcode & ISCSI_OPCODE_MASK) {
 280  280          case ISCSI_OP_SCSI_DATA_RSP:
 281  281                  status = iscsi_rx_process_data_rsp(ic, pdu);
 282  282                  break;
 283  283          case ISCSI_OP_SCSI_RSP:
 284  284                  status = iscsi_rx_process_cmd_rsp(ic, pdu);
 285  285                  idm_pdu_complete(pdu, status);
 286  286                  break;
 287  287          default:
 288  288                  cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
 289  289                      "received pdu with unsupported opcode 0x%02x",
 290  290                      icp->conn_oid, ihp->opcode);
 291  291                  status = IDM_STATUS_PROTOCOL_ERROR;
 292  292          }
 293  293          iscsi_process_rsp_status(isp, icp, status);
 294  294  }
 295  295  
 296  296  void
 297  297  iscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp)
 298  298  {
 299  299          struct buf      *bp;
 300  300          idm_buf_t       *ibp, *obp;
 301  301          idm_task_t      *itp;
 302  302  
 303  303          itp = icmdp->cmd_itp;
 304  304          ASSERT(itp != NULL);
 305  305          ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
 306  306              (opcode == ISCSI_OP_SCSI_RSP));
 307  307  
 308  308          bp = icmdp->cmd_un.scsi.bp;
 309  309          ibp = icmdp->cmd_un.scsi.ibp_ibuf;
 310  310          obp = icmdp->cmd_un.scsi.ibp_obuf;
 311  311          ISCSI_IO_LOG(CE_NOTE, "DEBUG: task_cleanup: itp: %p opcode: %d "
 312  312              "icmdp: %p bp: %p ibp: %p", (void *)itp, opcode,
 313  313              (void *)icmdp, (void *)bp, (void *)ibp);
 314  314          if (bp && bp->b_bcount) {
 315  315                  if (ibp != NULL && bp->b_flags & B_READ) {
 316  316                          idm_buf_unbind_in(itp, ibp);
 317  317                          idm_buf_free(ibp);
 318  318                          icmdp->cmd_un.scsi.ibp_ibuf = NULL;
 319  319                  } else if (obp != NULL && !(bp->b_flags & B_READ)) {
 320  320                          idm_buf_unbind_out(itp, obp);
 321  321                          idm_buf_free(obp);
 322  322                          icmdp->cmd_un.scsi.ibp_obuf = NULL;
 323  323                  }
 324  324          }
 325  325  
 326  326          idm_task_done(itp);
 327  327  }
 328  328  
 329  329  idm_status_t
 330  330  iscsi_rx_chk(iscsi_conn_t *icp, iscsi_sess_t *isp,
 331  331      iscsi_scsi_rsp_hdr_t *irhp, iscsi_cmd_t **icmdp)
 332  332  {
 333  333          iscsi_status_t rval;
 334  334  
 335  335          mutex_enter(&isp->sess_cmdsn_mutex);
 336  336  
 337  337          if (icp->conn_expstatsn == ntohl(irhp->statsn)) {
 338  338                  icp->conn_expstatsn++;
 339  339          } else {
 340  340                  cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
 341  341                      "received status out of order itt:0x%x statsn:0x%x "
 342  342                      "expstatsn:0x%x", icp->conn_oid, irhp->opcode,
 343  343                      irhp->itt, ntohl(irhp->statsn), icp->conn_expstatsn);
 344  344                  mutex_exit(&isp->sess_cmdsn_mutex);
 345  345                  return (IDM_STATUS_PROTOCOL_ERROR);
 346  346          }
 347  347  
 348  348          /* get icmdp so we can cleanup on error */
 349  349          if ((irhp->opcode == ISCSI_OP_SCSI_DATA_RSP) ||
 350  350              (irhp->opcode == ISCSI_OP_SCSI_RSP)) {
 351  351                  rval = iscsi_rx_process_scsi_itt_to_icmdp(isp, icp->conn_ic,
 352  352                      irhp, icmdp);
 353  353          } else {
 354  354                  rval = iscsi_rx_process_itt_to_icmdp(isp,
 355  355                      (iscsi_hdr_t *)irhp, icmdp);
 356  356          }
 357  357  
 358  358          if (!ISCSI_SUCCESS(rval)) {
 359  359                  mutex_exit(&isp->sess_cmdsn_mutex);
 360  360                  return (IDM_STATUS_PROTOCOL_ERROR);
 361  361          }
 362  362  
 363  363          /* update expcmdsn and maxcmdsn */
 364  364          iscsi_update_flow_control(isp, ntohl(irhp->maxcmdsn),
 365  365              ntohl(irhp->expcmdsn));
 366  366          mutex_exit(&isp->sess_cmdsn_mutex);
 367  367          return (IDM_STATUS_SUCCESS);
 368  368  }
 369  369  
 370  370  static void
 371  371  iscsi_cmd_rsp_chk(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp)
 372  372  {
 373  373          struct scsi_pkt *pkt;
 374  374          size_t data_transferred;
 375  375  
 376  376          pkt = icmdp->cmd_un.scsi.pkt;
 377  377          pkt->pkt_resid = 0;
 378  378          data_transferred = icmdp->cmd_un.scsi.data_transferred;
 379  379          /* Check the residual count */
 380  380          if ((icmdp->cmd_un.scsi.bp) &&
 381  381              (data_transferred != icmdp->cmd_un.scsi.bp->b_bcount)) {
 382  382                  /*
 383  383                   * We didn't xfer the expected amount of data -
 384  384                   * the residual_count in the header is only
 385  385                   * valid if the underflow flag is set.
 386  386                   */
 387  387                  if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
 388  388                          pkt->pkt_resid = ntohl(issrhp->residual_count);
 389  389                  } else {
 390  390                          if (icmdp->cmd_un.scsi.bp->b_bcount >
 391  391                              data_transferred) {
 392  392                                  /*
 393  393                                   * Some data fell on the floor
 394  394                                   * somehow - probably a CRC error
 395  395                                   */
 396  396                                  pkt->pkt_resid =
 397  397                                      icmdp->cmd_un.scsi.bp->b_bcount -
 398  398                                      data_transferred;
 399  399                          }
 400  400                  }
 401  401                  ISCSI_IO_LOG(CE_NOTE,
 402  402                      "DEBUG: iscsi_rx_cmd_rsp_chk: itt: %u"
 403  403                      "data_trans != b_count data_transferred: %lu "
 404  404                      "b_count: %lu cmd_status: %d flags: %d resid: %lu",
 405  405                      issrhp->itt, data_transferred,
 406  406                      icmdp->cmd_un.scsi.bp->b_bcount,
 407  407                      issrhp->cmd_status & STATUS_MASK,
 408  408                      issrhp->flags, pkt->pkt_resid);
 409  409          }
 410  410          /* set flags that tell SCSA that the command is complete */
 411  411          if (icmdp->cmd_crc_error_seen == B_FALSE) {
 412  412                  /* Set successful completion */
 413  413                  pkt->pkt_reason = CMD_CMPLT;
 414  414                  if (icmdp->cmd_un.scsi.bp) {
 415  415                          pkt->pkt_state |= (STATE_XFERRED_DATA |
 416  416                              STATE_GOT_STATUS);
 417  417                  } else {
 418  418                          pkt->pkt_state |= STATE_GOT_STATUS;
 419  419                  }
 420  420          } else {
 421  421                  /*
 422  422                   * Some of the data was found to have an incorrect
 423  423                   * error at the protocol error.
 424  424                   */
 425  425                  pkt->pkt_reason = CMD_PER_FAIL;
 426  426                  pkt->pkt_statistics |= STAT_PERR;
 427  427                  if (icmdp->cmd_un.scsi.bp) {
 428  428                          pkt->pkt_resid =
 429  429                              icmdp->cmd_un.scsi.bp->b_bcount;
 430  430                  } else {
 431  431                          pkt->pkt_resid = 0;
 432  432                  }
 433  433          }
 434  434  }
 435  435  
 436  436  static boolean_t
 437  437  iscsi_cmd_rsp_cmd_status(iscsi_cmd_t *icmdp, iscsi_scsi_rsp_hdr_t *issrhp,
 438  438      uint8_t *data)
 439  439  {
 440  440          int32_t                 dlength;
 441  441          struct scsi_arq_status  *arqstat;
 442  442          size_t                  senselen;
 443  443          int32_t                 statuslen;
 444  444          int32_t                 sensebuf_len;
 445  445          struct scsi_pkt         *pkt;
 446  446          boolean_t               affect = B_FALSE;
 447  447          int32_t                 senselen_to_copy;
 448  448  
 449  449          pkt = icmdp->cmd_un.scsi.pkt;
 450  450          dlength = n2h24(issrhp->dlength);
 451  451  
 452  452          /*
 453  453           * Process iSCSI Cmd Response Status
 454  454           * RFC 3720 Sectionn 10.4.2.
 455  455           */
 456  456          switch (issrhp->cmd_status & STATUS_MASK) {
 457  457          case STATUS_GOOD:
 458  458                  /* pass SCSI status up stack */
 459  459                  if (pkt->pkt_scbp) {
 460  460                          pkt->pkt_scbp[0] = issrhp->cmd_status;
 461  461                  }
 462  462                  break;
 463  463          case STATUS_CHECK:
 464  464                  /*
 465  465                   * Verify we received a sense buffer and
 466  466                   * that there is the correct amount of
 467  467                   * request sense space to copy it to.
 468  468                   */
 469  469                  if ((dlength > 1) &&
 470  470                      (pkt->pkt_scbp != NULL) &&
 471  471                      (icmdp->cmd_un.scsi.statuslen >=
 472  472                      sizeof (struct scsi_arq_status))) {
 473  473                          /*
 474  474                           * If a bad command status is received we
 475  475                           * need to reset the pkt_resid to zero.
 476  476                           * The target driver compares its value
 477  477                           * before checking other error flags.
 478  478                           * (ex. check conditions)
 479  479                           */
 480  480                          pkt->pkt_resid = 0;
 481  481  
 482  482                          /* get sense length from first 2 bytes */
 483  483                          senselen = ((data[0] << 8) | data[1]) &
 484  484                              (size_t)0xFFFF;
 485  485                          ISCSI_IO_LOG(CE_NOTE,
 486  486                              "DEBUG: iscsi_rx_cmd_rsp_cmd_status status_check: "
 487  487                              "dlen: %d scbp: %p statuslen: %d arq: %d senselen:"
 488  488                              " %lu", dlength, (void *)pkt->pkt_scbp,
 489  489                              icmdp->cmd_un.scsi.statuslen,
 490  490                              (int)sizeof (struct scsi_arq_status),
 491  491                              senselen);
 492  492  
 493  493                          /* Sanity-check on the sense length */
 494  494                          if ((senselen + 2) > dlength) {
 495  495                                  senselen = dlength - 2;
 496  496                          }
 497  497  
 498  498                          /*
 499  499                           * If there was a Data Digest error then
 500  500                           * the sense data cannot be trusted.
 501  501                           */
 502  502                          if (icmdp->cmd_crc_error_seen) {
 503  503                                  senselen = 0;
 504  504                          }
 505  505  
 506  506                          /* automatic request sense */
 507  507                          arqstat =
 508  508                              (struct scsi_arq_status *)pkt->pkt_scbp;
 509  509  
 510  510                          /* pass SCSI status up stack */
 511  511                          *((uchar_t *)&arqstat->sts_status) =
 512  512                              issrhp->cmd_status;
 513  513  
 514  514                          /*
 515  515                           * Set the status for the automatic
 516  516                           * request sense command
 517  517                           */
 518  518                          arqstat->sts_rqpkt_state = (STATE_GOT_BUS |
 519  519                              STATE_GOT_TARGET | STATE_SENT_CMD |
 520  520                              STATE_XFERRED_DATA | STATE_GOT_STATUS |
 521  521                              STATE_ARQ_DONE);
 522  522  
 523  523                          *((uchar_t *)&arqstat->sts_rqpkt_status) =
 524  524                              STATUS_GOOD;
 525  525  
 526  526                          arqstat->sts_rqpkt_reason = CMD_CMPLT;
 527  527                          statuslen = icmdp->cmd_un.scsi.statuslen;
 528  528  
 529  529                          if (senselen == 0) {
 530  530                                  /* auto request sense failed */
 531  531                                  arqstat->sts_rqpkt_status.sts_chk = 1;
 532  532                                  arqstat->sts_rqpkt_resid = statuslen;
 533  533                          } else if (senselen < statuslen) {
 534  534                                  /* auto request sense short */
 535  535                                  arqstat->sts_rqpkt_resid = statuslen - senselen;
 536  536                          } else {
 537  537                                  /* auto request sense complete */
 538  538                                  arqstat->sts_rqpkt_resid = 0;
 539  539                          }
 540  540                          arqstat->sts_rqpkt_statistics = 0;
 541  541                          pkt->pkt_state |= STATE_ARQ_DONE;
 542  542  
 543  543                          if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_XARQ) {
 544  544                                  pkt->pkt_state |= STATE_XARQ_DONE;
 545  545                          }
 546  546  
 547  547                          /*
 548  548                           * Calculate size of space reserved for sense data in
 549  549                           * pkt->pkt_scbp.
 550  550                           */
 551  551                          sensebuf_len = statuslen - ISCSI_ARQ_STATUS_NOSENSE_LEN;
 552  552  
 553  553                          /* copy auto request sense */
 554  554                          senselen_to_copy = min(senselen, sensebuf_len);
 555  555                          if (senselen_to_copy > 0) {
 556  556                                  bcopy(&data[2], (uchar_t *)&arqstat->
 557  557                                      sts_sensedata, senselen_to_copy);
 558  558  
 559  559                                  affect = iscsi_decode_sense(
 560  560                                      (uint8_t *)&arqstat->sts_sensedata, icmdp);
 561  561                          }
 562  562                          arqstat->sts_rqpkt_resid = sensebuf_len -
 563  563                              senselen_to_copy;
 564  564                          ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_cmd_rsp_cmd_status:"
 565  565                              " sts_rqpkt_resid: %d pkt_scblen: %d senselen: %lu"
 566  566                              " sensebuf_len: %d senselen_to_copy: %d affect: %d",
 567  567                              arqstat->sts_rqpkt_resid, pkt->pkt_scblen, senselen,
 568  568                              sensebuf_len, senselen_to_copy, affect);
 569  569                          break;
 570  570                  }
 571  571                  /* FALLTHRU */
 572  572          case STATUS_BUSY:
 573  573          case STATUS_RESERVATION_CONFLICT:
 574  574          case STATUS_QFULL:
 575  575          case STATUS_ACA_ACTIVE:
 576  576          default:
 577  577                  /*
 578  578                   * If a bad command status is received we need to
 579  579                   * reset the pkt_resid to zero.  The target driver
 580  580                   * compares its value before checking other error
 581  581                   * flags. (ex. check conditions)
 582  582                   */
 583  583                  ISCSI_IO_LOG(CE_NOTE,
 584  584                      "DEBUG: iscsi_rx_cmd_rsp_cmd_status: status: "
 585  585                      "%d cmd_status: %d dlen: %u scbp: %p statuslen: %d "
 586  586                      "arg_len: %d", issrhp->cmd_status & STATUS_MASK,
 587  587                      issrhp->cmd_status, dlength, (void *)pkt->pkt_scbp,
 588  588                      icmdp->cmd_un.scsi.statuslen,
 589  589                      (int)sizeof (struct scsi_arq_status));
 590  590                  pkt->pkt_resid = 0;
 591  591                  /* pass SCSI status up stack */
 592  592                  if (pkt->pkt_scbp) {
 593  593                          pkt->pkt_scbp[0] = issrhp->cmd_status;
 594  594                  }
 595  595          }
 596  596  
 597  597          return (affect);
 598  598  }
 599  599  
 600  600  /*
 601  601   * iscsi_rx_process_login_pdup - Process login response PDU.  This function
 602  602   * copies the data into the connection context so that the login code can
 603  603   * interpret it.
 604  604   */
 605  605  
 606  606  idm_status_t
 607  607  iscsi_rx_process_login_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
 608  608  {
 609  609          iscsi_conn_t            *icp;
 610  610  
 611  611          icp = ic->ic_handle;
 612  612  
 613  613          /*
 614  614           * Copy header and data into connection structure so iscsi_login()
 615  615           * can process it.
 616  616           */
 617  617          mutex_enter(&icp->conn_login_mutex);
 618  618          /*
 619  619           * If conn_login_state != LOGIN_TX then we are not ready to handle
 620  620           * this login response and we should just  drop it.
 621  621           */
 622  622          if (icp->conn_login_state == LOGIN_TX) {
 623  623                  icp->conn_login_datalen = pdu->isp_datalen;
 624  624                  bcopy(pdu->isp_hdr, &icp->conn_login_resp_hdr,
 625  625                      sizeof (iscsi_hdr_t));
 626  626                  /*
 627  627                   * Login code is sloppy with it's NULL handling so make sure
 628  628                   * we don't leave any stale data in there.
 629  629                   */
 630  630                  bzero(icp->conn_login_data, icp->conn_login_max_data_length);
 631  631                  bcopy(pdu->isp_data, icp->conn_login_data,
 632  632                      MIN(pdu->isp_datalen, icp->conn_login_max_data_length));
 633  633                  iscsi_login_update_state_locked(icp, LOGIN_RX);
 634  634          }
 635  635          mutex_exit(&icp->conn_login_mutex);
 636  636  
 637  637          return (IDM_STATUS_SUCCESS);
 638  638  }
 639  639  
 640  640  /*
 641  641   * iscsi_rx_process_cmd_rsp - Process received scsi command response.  This
 642  642   * will contain sense data if the command was not successful.  This data needs
 643  643   * to be copied into the scsi_pkt.  Otherwise we just complete the IO.
 644  644   */
 645  645  static idm_status_t
 646  646  iscsi_rx_process_cmd_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
 647  647  {
 648  648          iscsi_conn_t            *icp    = ic->ic_handle;
 649  649          iscsi_sess_t            *isp    = icp->conn_sess;
 650  650          iscsi_scsi_rsp_hdr_t    *issrhp = (iscsi_scsi_rsp_hdr_t *)pdu->isp_hdr;
 651  651          uint8_t                 *data   = pdu->isp_data;
 652  652          iscsi_cmd_t             *icmdp  = NULL;
 653  653          struct scsi_pkt         *pkt    = NULL;
 654  654          idm_status_t            rval;
 655  655          struct buf              *bp;
 656  656          boolean_t               flush   = B_FALSE;
 657  657          uint32_t                cmd_sn  = 0;
 658  658          uint16_t                lun_num = 0;
 659  659  
 660  660          /* make sure we get status in order */
 661  661          mutex_enter(&icp->conn_queue_active.mutex);
 662  662  
 663  663          if ((rval = iscsi_rx_chk(icp, isp, issrhp,
 664  664              &icmdp)) != IDM_STATUS_SUCCESS) {
 665  665                  if (icmdp != NULL) {
 666  666                          iscsi_task_cleanup(issrhp->opcode, icmdp);
 667  667                  }
 668  668                  mutex_exit(&icp->conn_queue_active.mutex);
 669  669                  return (rval);
 670  670          }
 671  671  
 672  672          /*
 673  673           * If we are in "idm aborting" state then we shouldn't continue
 674  674           * to process this command.  By definition this command is no longer
 675  675           * on the active queue so we shouldn't try to remove it either.
 676  676           */
 677  677          mutex_enter(&icmdp->cmd_mutex);
 678  678          if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
 679  679                  mutex_exit(&icmdp->cmd_mutex);
 680  680                  mutex_exit(&icp->conn_queue_active.mutex);
 681  681                  return (IDM_STATUS_SUCCESS);
 682  682          }
 683  683          mutex_exit(&icmdp->cmd_mutex);
 684  684  
 685  685          /* Get the IDM buffer and bytes transferred */
 686  686          bp = icmdp->cmd_un.scsi.bp;
 687  687          if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
 688  688                  /* Transport tracks bytes transferred so use those counts */
 689  689                  if (bp && (bp->b_flags & B_READ)) {
 690  690                          icmdp->cmd_un.scsi.data_transferred +=
 691  691                              icmdp->cmd_itp->idt_rx_bytes;
 692  692                  } else {
 693  693                          icmdp->cmd_un.scsi.data_transferred +=
 694  694                              icmdp->cmd_itp->idt_tx_bytes;
 695  695                  }
 696  696          } else {
 697  697                  /*
 698  698                   * Some transports cannot track the bytes transferred on
 699  699                   * the initiator side (like iSER) so we have to use the
 700  700                   * status info.  If the response field indicates that
 701  701                   * the command actually completed then we will assume
 702  702                   * the data_transferred value represents the entire buffer
 703  703                   * unless the resid field says otherwise.  This is a bit
 704  704                   * unintuitive but it's really impossible to know what
 705  705                   * has been transferred without detailed consideration
 706  706                   * of the SCSI status and sense key and that is outside
 707  707                   * the scope of the transport.  Instead the target/class driver
 708  708                   * can consider these values along with the resid and figure
 709  709                   * it out.  The data_transferred concept is just belt and
 710  710                   * suspenders anyway -- RFC 3720 actually explicitly rejects
 711  711                   * scoreboarding ("Initiators SHOULD NOT keep track of the
 712  712                   * data transferred to or from the target (scoreboarding)")
 713  713                   * perhaps for this very reason.
 714  714                   */
 715  715                  if (issrhp->response != 0) {
 716  716                          icmdp->cmd_un.scsi.data_transferred = 0;
 717  717                  } else {
 718  718                          icmdp->cmd_un.scsi.data_transferred =
 719  719                              (bp == NULL) ? 0 : bp->b_bcount;
 720  720                          if (issrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
 721  721                                  icmdp->cmd_un.scsi.data_transferred -=
 722  722                                      ntohl(issrhp->residual_count);
 723  723                          }
 724  724                  }
 725  725          }
 726  726  
 727  727          ISCSI_CHECK_SCSI_READ(icmdp, issrhp,
 728  728              icmdp->cmd_un.scsi.data_transferred,
 729  729              BP_CHECK_THOROUGH);
 730  730  
 731  731          ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu: %p itt:"
 732  732              " %x expcmdsn: %x sess_cmd: %x sess_expcmdsn: %x data_transfered:"
 733  733              " %lu ibp: %p obp: %p", (void *)ic, (void *)pdu, issrhp->itt,
 734  734              issrhp->expcmdsn, isp->sess_cmdsn, isp->sess_expcmdsn,
 735  735              icmdp->cmd_un.scsi.data_transferred,
 736  736              (void *)icmdp->cmd_un.scsi.ibp_ibuf,
 737  737              (void *)icmdp->cmd_un.scsi.ibp_obuf);
 738  738  
 739  739          iscsi_task_cleanup(issrhp->opcode, icmdp);
 740  740  
 741  741          if (issrhp->response) {
 742  742                  /* The target failed the command. */
 743  743                  ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_cmd_rsp: ic: %p pdu:"
 744  744                      " %p response: %d bcount: %lu", (void *)ic, (void *)pdu,
 745  745                      issrhp->response, icmdp->cmd_un.scsi.bp->b_bcount);
 746  746                  pkt = icmdp->cmd_un.scsi.pkt;
 747  747                  pkt->pkt_reason = CMD_TRAN_ERR;
 748  748                  if (icmdp->cmd_un.scsi.bp) {
 749  749                          pkt->pkt_resid = icmdp->cmd_un.scsi.bp->b_bcount;
 750  750                  } else {
 751  751                          pkt->pkt_resid = 0;
 752  752                  }
 753  753          } else {
 754  754                  /* success */
 755  755                  iscsi_cmd_rsp_chk(icmdp, issrhp);
 756  756                  flush = iscsi_cmd_rsp_cmd_status(icmdp, issrhp, data);
 757  757  
 758  758                  ASSERT(icmdp->cmd_lun == NULL || icmdp->cmd_lun->lun_num ==
 759  759                      (icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK));
 760  760  
 761  761                  if (flush == B_TRUE) {
 762  762                          cmd_sn = icmdp->cmd_sn;
 763  763                          lun_num = icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK;
 764  764                  }
 765  765          }
 766  766  
 767  767          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
 768  768          if (flush == B_TRUE) {
 769  769                  iscsi_flush_cmd_after_reset(cmd_sn, lun_num, icp);
 770  770          }
 771  771          mutex_exit(&icp->conn_queue_active.mutex);
 772  772          return (IDM_STATUS_SUCCESS);
 773  773  }
 774  774  
 775  775  static void
 776  776  iscsi_data_rsp_pkt(iscsi_cmd_t *icmdp, iscsi_data_rsp_hdr_t *idrhp)
 777  777  {
 778  778          struct buf              *bp     = NULL;
 779  779          size_t                  data_transferred;
 780  780          struct scsi_pkt         *pkt;
 781  781  
 782  782          bp = icmdp->cmd_un.scsi.bp;
 783  783          pkt = icmdp->cmd_un.scsi.pkt;
 784  784          data_transferred = icmdp->cmd_un.scsi.data_transferred;
 785  785          /*
 786  786           * The command* must be completed now, since we won't get a command
 787  787           * response PDU. The cmd_status and residual_count are
 788  788           * not meaningful unless status_present is set.
 789  789           */
 790  790          pkt->pkt_resid = 0;
 791  791          /* Check the residual count */
 792  792          if (bp && (data_transferred != bp->b_bcount)) {
 793  793                  /*
 794  794                   * We didn't xfer the expected amount of data -
 795  795                   * the residual_count in the header is only valid
 796  796                   * if the underflow flag is set.
 797  797                   */
 798  798                  if (idrhp->flags & ISCSI_FLAG_DATA_UNDERFLOW) {
 799  799                          pkt->pkt_resid = ntohl(idrhp->residual_count);
 800  800                          ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
 801  801                              "underflow: itt: %d "
 802  802                              "transferred: %lu count: %lu", idrhp->itt,
 803  803                              data_transferred, bp->b_bcount);
 804  804                  } else {
 805  805                          if (bp->b_bcount > data_transferred) {
 806  806                                  /* Some data fell on the floor somehw */
 807  807                                  ISCSI_IO_LOG(CE_NOTE, "DEBUG: "
 808  808                                      "iscsi_data_rsp_pkt: data fell: itt: %d "
 809  809                                      "transferred: %lu count: %lu", idrhp->itt,
 810  810                                      data_transferred, bp->b_bcount);
 811  811                                  pkt->pkt_resid =
 812  812                                      bp->b_bcount - data_transferred;
 813  813                          }
 814  814                  }
 815  815          }
 816  816  
 817  817          pkt->pkt_reason = CMD_CMPLT;
 818  818          pkt->pkt_state |= (STATE_XFERRED_DATA | STATE_GOT_STATUS);
 819  819  
 820  820          if (((idrhp->cmd_status & STATUS_MASK) != STATUS_GOOD) &&
 821  821              (icmdp->cmd_un.scsi.statuslen >=
 822  822              sizeof (struct scsi_arq_status)) && pkt->pkt_scbp) {
 823  823  
 824  824                  /*
 825  825                   * Not supposed to get exception status here!
 826  826                   * We have no request sense data so just do the
 827  827                   * best we can
 828  828                   */
 829  829                  struct scsi_arq_status *arqstat =
 830  830                      (struct scsi_arq_status *)pkt->pkt_scbp;
 831  831  
 832  832  
 833  833                  bzero(arqstat, sizeof (struct scsi_arq_status));
 834  834  
 835  835                  *((uchar_t *)&arqstat->sts_status) =
 836  836                      idrhp->cmd_status;
 837  837  
 838  838                  /* sense residual is set to whole size of sense buffer */
 839  839                  arqstat->sts_rqpkt_resid = icmdp->cmd_un.scsi.statuslen -
 840  840                      ISCSI_ARQ_STATUS_NOSENSE_LEN;
 841  841                  ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_data_rsp_pkt: "
 842  842                      "exception status: itt: %d resid: %d",
 843  843                      idrhp->itt, arqstat->sts_rqpkt_resid);
 844  844  
 845  845          } else if (pkt->pkt_scbp) {
 846  846                  /* just pass along the status we got */
 847  847                  pkt->pkt_scbp[0] = idrhp->cmd_status;
 848  848          }
 849  849  }
 850  850  
 851  851  /*
 852  852   * iscsi_rx_process_data_rsp -
 853  853   * This currently processes the final data sequence denoted by the data response
 854  854   * PDU Status bit being set.  We will not receive the SCSI response.
 855  855   * This bit denotes that the PDU is the successful completion of the
 856  856   * command.
 857  857   */
 858  858  static idm_status_t
 859  859  iscsi_rx_process_data_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
 860  860  {
 861  861          iscsi_sess_t            *isp    = NULL;
 862  862          iscsi_data_rsp_hdr_t    *idrhp  = (iscsi_data_rsp_hdr_t *)pdu->isp_hdr;
 863  863          iscsi_cmd_t             *icmdp  = NULL;
 864  864          struct buf              *bp     = NULL;
 865  865          iscsi_conn_t            *icp    = ic->ic_handle;
 866  866          idm_buf_t               *ibp;
 867  867          idm_status_t            rval;
 868  868  
 869  869  
 870  870          /* should only call this when the data rsp contains final rsp */
 871  871          ASSERT(idrhp->flags & ISCSI_FLAG_DATA_STATUS);
 872  872          isp = icp->conn_sess;
 873  873  
 874  874          mutex_enter(&icp->conn_queue_active.mutex);
 875  875          if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)idrhp,
 876  876              &icmdp)) != IDM_STATUS_SUCCESS) {
 877  877                  if (icmdp != NULL) {
 878  878                          iscsi_task_cleanup(idrhp->opcode, icmdp);
 879  879                  }
 880  880                  mutex_exit(&icp->conn_queue_active.mutex);
 881  881                  return (rval);
 882  882          }
 883  883  
 884  884          /*
 885  885           * If we are in "idm aborting" state then we shouldn't continue
 886  886           * to process this command.  By definition this command is no longer
 887  887           * on the active queue so we shouldn't try to remove it either.
 888  888           */
 889  889          mutex_enter(&icmdp->cmd_mutex);
 890  890          if (icmdp->cmd_state == ISCSI_CMD_STATE_IDM_ABORTING) {
 891  891                  mutex_exit(&icmdp->cmd_mutex);
 892  892                  mutex_exit(&icp->conn_queue_active.mutex);
 893  893                  return (IDM_STATUS_SUCCESS);
 894  894          }
 895  895          mutex_exit(&icmdp->cmd_mutex);
 896  896  
 897  897          /*
 898  898           * Holding the pending/active queue locks across the
 899  899           * iscsi_rx_data call later in this function may cause
 900  900           * deadlock during fault injections.  Instead remove
 901  901           * the cmd from the active queue and release the locks.
 902  902           * Then before returning or completing the command
 903  903           * return the cmd to the active queue and reacquire
 904  904           * the locks.
 905  905           */
 906  906          iscsi_dequeue_active_cmd(icp, icmdp);
 907  907  
 908  908          mutex_exit(&icp->conn_queue_active.mutex);
 909  909  
 910  910          /* shorthand some values */
 911  911          bp = icmdp->cmd_un.scsi.bp;
 912  912  
 913  913          /*
 914  914           * some poorly behaved targets have been observed
 915  915           * sending data-in pdu's during a write operation
 916  916           */
 917  917          if (bp != NULL) {
 918  918                  if (!(bp->b_flags & B_READ)) {
 919  919                          cmn_err(CE_WARN,
 920  920                              "iscsi connection(%u) protocol error - "
 921  921                              "received data response during write operation "
 922  922                              "itt:0x%x",
 923  923                              icp->conn_oid, idrhp->itt);
 924  924                          mutex_enter(&icp->conn_queue_active.mutex);
 925  925                          iscsi_enqueue_active_cmd(icp, icmdp);
 926  926                          mutex_exit(&icp->conn_queue_active.mutex);
 927  927                          return (IDM_STATUS_PROTOCOL_ERROR);
 928  928                  }
 929  929          }
 930  930  
 931  931          ibp = icmdp->cmd_un.scsi.ibp_ibuf;
 932  932          if (ibp == NULL) {
 933  933                  /*
 934  934                   * After the check of bp above we *should* have a corresponding
 935  935                   * idm_buf_t (ibp).  It's possible that the original call
 936  936                   * to idm_buf_alloc failed due to a pending connection state
 937  937                   * transition in which case this value can be NULL.  It's
 938  938                   * highly unlikely that the connection would be shutting down
 939  939                   * *and* we manage to process a data response and get to this
 940  940                   * point in the code but just in case we should check for it.
 941  941                   * This isn't really a protocol error -- we are almost certainly
 942  942                   * closing the connection anyway so just return a generic error.
 943  943                   */
 944  944                  mutex_enter(&icp->conn_queue_active.mutex);
 945  945                  iscsi_enqueue_active_cmd(icp, icmdp);
 946  946                  mutex_exit(&icp->conn_queue_active.mutex);
 947  947                  return (IDM_STATUS_FAIL);
 948  948          }
 949  949  
 950  950          if (ic->ic_conn_flags & IDM_CONN_USE_SCOREBOARD) {
 951  951                  icmdp->cmd_un.scsi.data_transferred =
 952  952                      icmdp->cmd_itp->idt_rx_bytes;
 953  953          } else {
 954  954                  icmdp->cmd_un.scsi.data_transferred = bp->b_bcount;
 955  955                  if (idrhp->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
 956  956                          icmdp->cmd_un.scsi.data_transferred -=
 957  957                              ntohl(idrhp->residual_count);
 958  958                  }
 959  959          }
 960  960  
 961  961          ISCSI_IO_LOG(CE_NOTE, "DEBUG: rx_process_data_rsp: icp: %p pdu: %p "
 962  962              "itt: %d ibp: %p icmdp: %p xfer_len: %lu transferred: %lu dlen: %u",
 963  963              (void *)icp, (void *)pdu, idrhp->itt, (void *)bp, (void *)icmdp,
 964  964              (ibp == NULL) ? 0 : ibp->idb_xfer_len,
 965  965              icmdp->cmd_un.scsi.data_transferred,
 966  966              n2h24(idrhp->dlength));
 967  967  
 968  968          iscsi_task_cleanup(idrhp->opcode, icmdp);
 969  969  
 970  970          iscsi_data_rsp_pkt(icmdp, idrhp);
 971  971  
 972  972          mutex_enter(&icp->conn_queue_active.mutex);
 973  973          iscsi_enqueue_active_cmd(icp, icmdp);
 974  974          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
 975  975          mutex_exit(&icp->conn_queue_active.mutex);
 976  976  
 977  977          return (IDM_STATUS_SUCCESS);
 978  978  }
 979  979  
 980  980  /*
 981  981   * iscsi_rx_process_nop - Process a received nop.  If nop is in response
 982  982   * to a ping we sent update stats.  If initiated by the target we need
 983  983   * to response back to the target with a nop.  Schedule the response.
 984  984   */
 985  985  /* ARGSUSED */
 986  986  static idm_status_t
 987  987  iscsi_rx_process_nop(idm_conn_t *ic, idm_pdu_t *pdu)
 988  988  {
 989  989          iscsi_sess_t            *isp    = NULL;
 990  990          iscsi_nop_in_hdr_t      *inihp  = (iscsi_nop_in_hdr_t *)pdu->isp_hdr;
 991  991          iscsi_cmd_t             *icmdp  = NULL;
 992  992          iscsi_conn_t            *icp    = ic->ic_handle;
 993  993  
 994  994          if (icp->conn_expstatsn != ntohl(inihp->statsn)) {
 995  995                  cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
 996  996                      "received status out of order itt:0x%x statsn:0x%x "
 997  997                      "expstatsn:0x%x", icp->conn_oid, inihp->opcode, inihp->itt,
 998  998                      ntohl(inihp->statsn), icp->conn_expstatsn);
 999  999                  return (IDM_STATUS_PROTOCOL_ERROR);
1000 1000          }
1001 1001          isp = icp->conn_sess;
1002 1002          ASSERT(isp != NULL);
1003 1003          mutex_enter(&isp->sess_queue_pending.mutex);
1004 1004          mutex_enter(&icp->conn_queue_active.mutex);
1005 1005          mutex_enter(&isp->sess_cmdsn_mutex);
1006 1006          if (inihp->itt != ISCSI_RSVD_TASK_TAG) {
1007 1007                  if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1008 1008                      isp, (iscsi_hdr_t *)inihp, &icmdp))) {
1009 1009                          cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1010 1010                              "- can not find cmd for itt:0x%x",
1011 1011                              icp->conn_oid, inihp->itt);
1012 1012                          mutex_exit(&isp->sess_cmdsn_mutex);
1013 1013                          mutex_exit(&icp->conn_queue_active.mutex);
1014 1014                          mutex_exit(&isp->sess_queue_pending.mutex);
1015 1015                          return (IDM_STATUS_PROTOCOL_ERROR);
1016 1016                  }
1017 1017          }
1018 1018  
1019 1019          /* update expcmdsn and maxcmdsn */
1020 1020          iscsi_update_flow_control(isp, ntohl(inihp->maxcmdsn),
1021 1021              ntohl(inihp->expcmdsn));
1022 1022          mutex_exit(&isp->sess_cmdsn_mutex);
1023 1023  
1024 1024          if ((inihp->itt != ISCSI_RSVD_TASK_TAG) &&
1025 1025              (inihp->ttt == ISCSI_RSVD_TASK_TAG)) {
1026 1026                  /* This is the only type of nop that incs. the expstatsn */
1027 1027                  icp->conn_expstatsn++;
1028 1028  
1029 1029                  /*
1030 1030                   * This is a targets response to our nop
1031 1031                   */
1032 1032                  iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1033 1033          } else if (inihp->ttt != ISCSI_RSVD_TASK_TAG) {
1034 1034                  /*
1035 1035                   * Target requested a nop.  Send one.
1036 1036                   */
1037 1037                  iscsi_handle_nop(icp, ISCSI_RSVD_TASK_TAG, inihp->ttt);
1038 1038          } else {
1039 1039                  /*
1040 1040                   * This is a target-initiated ping that doesn't expect
1041 1041                   * a response; nothing to do except update our flow control
1042 1042                   * (which we do in all cases above).
1043 1043                   */
1044 1044                  /* EMPTY */
1045 1045          }
1046 1046          mutex_exit(&icp->conn_queue_active.mutex);
1047 1047          mutex_exit(&isp->sess_queue_pending.mutex);
1048 1048  
1049 1049          return (IDM_STATUS_SUCCESS);
1050 1050  }
1051 1051  
1052 1052  
1053 1053  /*
1054 1054   * iscsi_rx_process_reject_rsp - The server rejected a PDU
1055 1055   */
1056 1056  static idm_status_t
1057 1057  iscsi_rx_process_reject_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1058 1058  {
1059 1059          iscsi_reject_rsp_hdr_t  *irrhp = (iscsi_reject_rsp_hdr_t *)pdu->isp_hdr;
1060 1060          iscsi_sess_t            *isp            = NULL;
1061 1061          uint32_t                dlength         = 0;
1062 1062          iscsi_hdr_t             *old_ihp        = NULL;
1063 1063          iscsi_conn_t            *icp            = ic->ic_handle;
1064 1064          uint8_t                 *data           = pdu->isp_data;
1065 1065          idm_status_t            status          = IDM_STATUS_SUCCESS;
1066 1066          int                     i               = 0;
1067 1067  
1068 1068          ASSERT(data != NULL);
1069 1069          isp = icp->conn_sess;
1070 1070          ASSERT(isp != NULL);
1071 1071  
1072 1072          /*
1073 1073           * In RFC3720 section 10.17, this 4 bytes should be all 0xff.
1074 1074           */
1075 1075          for (i = 0; i < 4; i++) {
1076 1076                  if (irrhp->must_be_ff[i] != 0xff) {
1077 1077                          return (IDM_STATUS_PROTOCOL_ERROR);
1078 1078                  }
1079 1079          }
1080 1080          mutex_enter(&isp->sess_cmdsn_mutex);
1081 1081  
1082 1082          if (icp->conn_expstatsn == ntohl(irrhp->statsn)) {
1083 1083                  icp->conn_expstatsn++;
1084 1084          } else {
1085 1085                  cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1086 1086                      "received status out of order statsn:0x%x "
1087 1087                      "expstatsn:0x%x", icp->conn_oid, irrhp->opcode,
1088 1088                      ntohl(irrhp->statsn), icp->conn_expstatsn);
1089 1089                  mutex_exit(&isp->sess_cmdsn_mutex);
1090 1090                  return (IDM_STATUS_PROTOCOL_ERROR);
1091 1091          }
1092 1092          /* update expcmdsn and maxcmdsn */
1093 1093          iscsi_update_flow_control(isp, ntohl(irrhp->maxcmdsn),
1094 1094              ntohl(irrhp->expcmdsn));
1095 1095  
1096 1096          mutex_exit(&isp->sess_cmdsn_mutex);
1097 1097  
1098 1098          /* If we don't have the rejected header we can't do anything */
1099 1099          dlength = n2h24(irrhp->dlength);
1100 1100          if (dlength < sizeof (iscsi_hdr_t)) {
1101 1101                  return (IDM_STATUS_PROTOCOL_ERROR);
1102 1102          }
1103 1103  
1104 1104          /* map old ihp */
1105 1105          old_ihp = (iscsi_hdr_t *)data;
1106 1106  
1107 1107          switch (irrhp->reason) {
1108 1108          /*
1109 1109           * ISCSI_REJECT_IMM_CMD_REJECT - Immediate Command Reject
1110 1110           * too many immediate commands (original cmd can be resent)
1111 1111           */
1112 1112          case ISCSI_REJECT_IMM_CMD_REJECT:
1113 1113                  /*
1114 1114                   * We have exceeded the server's capacity for outstanding
1115 1115                   * immediate commands.   This must be a task management
1116 1116                   * command so try to find it in the abortingqueue and
1117 1117                   * complete it.
1118 1118                   */
1119 1119                  if (!(old_ihp->opcode & ISCSI_OP_IMMEDIATE)) {
1120 1120                          /* Rejecting IMM but old old_hdr wasn't IMM */
1121 1121                          return (IDM_STATUS_PROTOCOL_ERROR);
1122 1122                  }
1123 1123  
1124 1124                  /*
1125 1125                   * We only send NOP and TASK_MGT as IMM.  All other
1126 1126                   * cases should be considered as a protocol error.
1127 1127                   */
1128 1128                  switch (old_ihp->opcode & ISCSI_OPCODE_MASK) {
1129 1129                  case ISCSI_OP_NOOP_OUT:
1130 1130                          /*
1131 1131                           * A ping was rejected - treat this like
1132 1132                           * ping response.  The down side is we
1133 1133                           * didn't get an updated MaxCmdSn.
1134 1134                           */
1135 1135                          break;
1136 1136                  case ISCSI_OP_SCSI_TASK_MGT_MSG:
1137 1137                          status =
1138 1138                              iscsi_rx_process_rejected_tsk_mgt(ic, old_ihp);
1139 1139                          break;
1140 1140                  default:
1141 1141                          cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
1142 1142                              "- received a reject for a command(0x%02x) not "
1143 1143                              "sent as an immediate", icp->conn_oid,
1144 1144                              old_ihp->opcode);
1145 1145                          status = IDM_STATUS_PROTOCOL_ERROR;
1146 1146                          break;
1147 1147                  }
1148 1148                  break;
1149 1149  
1150 1150          /*
1151 1151           * For the rest of the reject cases just use the general
1152 1152           * hammer of dis/reconnecting.  This will resolve all
1153 1153           * noted issues although could be more graceful.
1154 1154           */
1155 1155          case ISCSI_REJECT_DATA_DIGEST_ERROR:
1156 1156          case ISCSI_REJECT_CMD_BEFORE_LOGIN:
1157 1157          case ISCSI_REJECT_SNACK_REJECT:
1158 1158          case ISCSI_REJECT_PROTOCOL_ERROR:
1159 1159          case ISCSI_REJECT_CMD_NOT_SUPPORTED:
1160 1160          case ISCSI_REJECT_TASK_IN_PROGRESS:
1161 1161          case ISCSI_REJECT_INVALID_DATA_ACK:
1162 1162          case ISCSI_REJECT_INVALID_PDU_FIELD:
1163 1163          case ISCSI_REJECT_LONG_OPERATION_REJECT:
1164 1164          case ISCSI_REJECT_NEGOTIATION_RESET:
1165 1165          default:
1166 1166                  cmn_err(CE_WARN, "iscsi connection(%u/%x) closing connection - "
1167 1167                      "target requested reason:0x%x",
1168 1168                      icp->conn_oid, irrhp->opcode, irrhp->reason);
1169 1169                  status = IDM_STATUS_PROTOCOL_ERROR;
1170 1170                  break;
1171 1171          }
1172 1172  
1173 1173          return (status);
1174 1174  }
1175 1175  
1176 1176  
1177 1177  /*
1178 1178   * iscsi_rx_process_rejected_tsk_mgt -
1179 1179   */
1180 1180  /* ARGSUSED */
1181 1181  static idm_status_t
1182 1182  iscsi_rx_process_rejected_tsk_mgt(idm_conn_t *ic, iscsi_hdr_t *old_ihp)
1183 1183  {
1184 1184          iscsi_sess_t            *isp    = NULL;
1185 1185          iscsi_cmd_t             *icmdp  = NULL;
1186 1186          iscsi_conn_t            *icp    = ic->ic_handle;
1187 1187  
1188 1188          isp = icp->conn_sess;
1189 1189          ASSERT(old_ihp != NULL);
1190 1190          ASSERT(isp != NULL);
1191 1191  
1192 1192          mutex_enter(&icp->conn_queue_active.mutex);
1193 1193          mutex_enter(&isp->sess_cmdsn_mutex);
1194 1194          if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1195 1195              isp, old_ihp, &icmdp))) {
1196 1196                  mutex_exit(&isp->sess_cmdsn_mutex);
1197 1197                  mutex_exit(&icp->conn_queue_active.mutex);
1198 1198                  return (IDM_STATUS_PROTOCOL_ERROR);
1199 1199          }
1200 1200          mutex_exit(&isp->sess_cmdsn_mutex);
1201 1201  
1202 1202          switch (icmdp->cmd_type) {
1203 1203          case ISCSI_CMD_TYPE_ABORT:
1204 1204          case ISCSI_CMD_TYPE_RESET:
1205 1205                  iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4,
1206 1206                      icp->conn_sess);
1207 1207                  break;
1208 1208          /* We don't send any other task mgr types */
1209 1209          default:
1210 1210                  ASSERT(B_FALSE);
1211 1211                  break;
1212 1212          }
1213 1213          mutex_exit(&icp->conn_queue_active.mutex);
1214 1214  
1215 1215          return (IDM_STATUS_SUCCESS);
1216 1216  }
1217 1217  
1218 1218  
1219 1219  /*
1220 1220   * iscsi_rx_process_task_mgt_rsp -
1221 1221   */
1222 1222  /* ARGSUSED */
1223 1223  static idm_status_t
1224 1224  iscsi_rx_process_task_mgt_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1225 1225  {
1226 1226          iscsi_sess_t                    *isp            = NULL;
1227 1227          iscsi_scsi_task_mgt_rsp_hdr_t   *istmrhp        = NULL;
1228 1228          iscsi_cmd_t                     *icmdp          = NULL;
1229 1229          iscsi_conn_t                    *icp            = ic->ic_handle;
1230 1230          idm_status_t                    status = IDM_STATUS_SUCCESS;
1231 1231  
1232 1232          isp = icp->conn_sess;
1233 1233          istmrhp = (iscsi_scsi_task_mgt_rsp_hdr_t *)pdu->isp_hdr;
1234 1234  
1235 1235          mutex_enter(&icp->conn_queue_active.mutex);
1236 1236          if ((status = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)istmrhp,
1237 1237              &icmdp)) != IDM_STATUS_SUCCESS) {
1238 1238                  mutex_exit(&icp->conn_queue_active.mutex);
1239 1239                  return (status);
1240 1240          }
1241 1241  
1242 1242          switch (icmdp->cmd_type) {
1243 1243          case ISCSI_CMD_TYPE_ABORT:
1244 1244          case ISCSI_CMD_TYPE_RESET:
1245 1245                  switch (istmrhp->response) {
1246 1246                  case SCSI_TCP_TM_RESP_COMPLETE:
1247 1247                          /* success */
1248 1248                          iscsi_cmd_state_machine(icmdp,
1249 1249                              ISCSI_CMD_EVENT_E3, isp);
1250 1250                          break;
1251 1251                  case SCSI_TCP_TM_RESP_NO_TASK:
1252 1252                          /*
1253 1253                           * If the array no longer knows about
1254 1254                           * an ABORT RTT and we no longer have
1255 1255                           * a parent SCSI command it was just
1256 1256                           * completed, free this ABORT resource.
1257 1257                           * Otherwise FALLTHRU this will flag a
1258 1258                           * protocol problem.
1259 1259                           */
1260 1260                          if ((icmdp->cmd_type == ISCSI_CMD_TYPE_ABORT) &&
1261 1261                              (icmdp->cmd_un.abort.icmdp == NULL)) {
1262 1262                                  iscsi_cmd_state_machine(icmdp,
1263 1263                                      ISCSI_CMD_EVENT_E4, isp);
1264 1264                                  break;
1265 1265                          }
1266 1266                          /* FALLTHRU */
1267 1267                  case SCSI_TCP_TM_RESP_REJECTED:
1268 1268                          /*
1269 1269                           * If the target rejects our reset task,
1270 1270                           * we should record the response and complete
1271 1271                           * this command with the result.
1272 1272                           */
1273 1273                          if (icmdp->cmd_type == ISCSI_CMD_TYPE_RESET) {
1274 1274                                  icmdp->cmd_un.reset.response =
1275 1275                                      istmrhp->response;
1276 1276                                  iscsi_cmd_state_machine(icmdp,
1277 1277                                      ISCSI_CMD_EVENT_E3, isp);
1278 1278                                  break;
1279 1279                          }
1280 1280                          /* FALLTHRU */
1281 1281                  case SCSI_TCP_TM_RESP_NO_LUN:
1282 1282                  case SCSI_TCP_TM_RESP_TASK_ALLEGIANT:
1283 1283                  case SCSI_TCP_TM_RESP_NO_FAILOVER:
1284 1284                  case SCSI_TCP_TM_RESP_IN_PRGRESS:
1285 1285                  default:
1286 1286                          /*
1287 1287                           * Something is out of sync.  Flush
1288 1288                           * active queues and resync the
1289 1289                           * the connection to try and recover
1290 1290                           * to a known state.
1291 1291                           */
1292 1292                          status = IDM_STATUS_PROTOCOL_ERROR;
1293 1293                  }
1294 1294                  break;
1295 1295  
1296 1296          default:
1297 1297                  cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1298 1298                      "received a task mgt response for a non-task mgt "
1299 1299                      "cmd itt:0x%x type:%d", icp->conn_oid, istmrhp->itt,
1300 1300                      icmdp->cmd_type);
1301 1301                  status = IDM_STATUS_PROTOCOL_ERROR;
1302 1302                  break;
1303 1303          }
1304 1304  
1305 1305          mutex_exit(&icp->conn_queue_active.mutex);
1306 1306          return (status);
1307 1307  }
1308 1308  
1309 1309  
1310 1310  /*
1311 1311   * iscsi_rx_process_logout_rsp -
1312 1312   *
1313 1313   */
1314 1314  /* ARGSUSED */
1315 1315  idm_status_t
1316 1316  iscsi_rx_process_logout_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1317 1317  {
1318 1318          iscsi_conn_t            *icp    = ic->ic_handle;
1319 1319          iscsi_logout_rsp_hdr_t  *ilrhp  =
1320 1320              (iscsi_logout_rsp_hdr_t *)pdu->isp_hdr;
1321 1321          iscsi_cmd_t             *icmdp  = NULL;
1322 1322          iscsi_sess_t            *isp;
1323 1323          idm_status_t            status = IDM_STATUS_SUCCESS;
1324 1324  
1325 1325          isp = icp->conn_sess;
1326 1326  
1327 1327          if (icp->conn_expstatsn != ntohl(ilrhp->statsn)) {
1328 1328                  cmn_err(CE_WARN, "iscsi connection(%u/%x) protocol error - "
1329 1329                      "received status out of order itt:0x%x statsn:0x%x "
1330 1330                      "expstatsn:0x%x", icp->conn_oid, ilrhp->opcode, ilrhp->itt,
1331 1331                      ntohl(ilrhp->statsn), icp->conn_expstatsn);
1332 1332                  return (IDM_STATUS_PROTOCOL_ERROR);
1333 1333          }
1334 1334  
1335 1335          mutex_enter(&icp->conn_queue_active.mutex);
1336 1336          mutex_enter(&isp->sess_cmdsn_mutex);
1337 1337          if (ilrhp->itt != ISCSI_RSVD_TASK_TAG) {
1338 1338                  if (!ISCSI_SUCCESS(iscsi_rx_process_itt_to_icmdp(
1339 1339                      isp, (iscsi_hdr_t *)ilrhp, &icmdp))) {
1340 1340                          mutex_exit(&isp->sess_cmdsn_mutex);
1341 1341                          mutex_exit(&icp->conn_queue_active.mutex);
1342 1342                          return (IDM_STATUS_PROTOCOL_ERROR);
1343 1343                  }
1344 1344          }
1345 1345  
1346 1346          /* update expcmdsn and maxcmdsn */
1347 1347          iscsi_update_flow_control(isp, ntohl(ilrhp->maxcmdsn),
1348 1348              ntohl(ilrhp->expcmdsn));
1349 1349          mutex_exit(&isp->sess_cmdsn_mutex);
1350 1350  
1351 1351          ISCSI_IO_LOG(CE_NOTE,
1352 1352              "DEBUG: iscsi_rx_process_logout_rsp: response: %d",
1353 1353              ilrhp->response);
1354 1354          switch (ilrhp->response) {
1355 1355          case ISCSI_LOGOUT_CID_NOT_FOUND:
1356 1356                  /*
1357 1357                   * If the target doesn't know about our connection
1358 1358                   * then we can consider our self disconnected.
1359 1359                   */
1360 1360                  /* FALLTHRU */
1361 1361          case ISCSI_LOGOUT_RECOVERY_UNSUPPORTED:
1362 1362                  /*
1363 1363                   * We don't support ErrorRecovery levels above 0
1364 1364                   * currently so consider this success.
1365 1365                   */
1366 1366                  /* FALLTHRU */
1367 1367          case ISCSI_LOGOUT_CLEANUP_FAILED:
1368 1368                  /*
1369 1369                   * per spec. "cleanup failed for various reasons."
1370 1370                   * Although those various reasons are undefined.
1371 1371                   * Not sure what to do here.  So fake success,
1372 1372                   * which will disconnect the connection.
1373 1373                   */
1374 1374                  /* FALLTHRU */
1375 1375          case ISCSI_LOGOUT_SUCCESS:
1376 1376                  iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1377 1377                  mutex_exit(&icp->conn_queue_active.mutex);
1378 1378                  iscsi_drop_conn_cleanup(icp);
1379 1379                  break;
1380 1380          default:
1381 1381                  mutex_exit(&icp->conn_queue_active.mutex);
1382 1382                  status = IDM_STATUS_PROTOCOL_ERROR;
1383 1383                  break;
1384 1384  
1385 1385          }
1386 1386          return (status);
1387 1387  }
1388 1388  
1389 1389  /*
1390 1390   * iscsi_rx_process_async_rsp
1391 1391   *
1392 1392   */
1393 1393  /* ARGSUSED */
1394 1394  static idm_status_t
1395 1395  iscsi_rx_process_async_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1396 1396  {
1397 1397          iscsi_conn_t            *icp    = ic->ic_handle;
1398 1398          iscsi_sess_t            *isp    = icp->conn_sess;
1399 1399          idm_status_t            rval    = IDM_STATUS_SUCCESS;
1400 1400          iscsi_task_t            *itp;
1401 1401          iscsi_async_evt_hdr_t   *iaehp  =
1402 1402              (iscsi_async_evt_hdr_t *)pdu->isp_hdr;
1403 1403  
1404 1404          ASSERT(icp != NULL);
1405 1405          ASSERT(pdu != NULL);
1406 1406          ASSERT(isp != NULL);
1407 1407  
1408 1408          mutex_enter(&isp->sess_cmdsn_mutex);
1409 1409          if (icp->conn_expstatsn == ntohl(iaehp->statsn)) {
1410 1410                  icp->conn_expstatsn++;
1411 1411          } else {
1412 1412                  cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1413 1413                      "received status out of order statsn:0x%x "
1414 1414                      "expstatsn:0x%x", icp->conn_oid,
1415 1415                      ntohl(iaehp->statsn), icp->conn_expstatsn);
1416 1416                  mutex_exit(&isp->sess_cmdsn_mutex);
1417 1417                  return (IDM_STATUS_PROTOCOL_ERROR);
1418 1418          }
1419 1419          mutex_exit(&isp->sess_cmdsn_mutex);
1420 1420  
1421 1421          switch (iaehp->async_event) {
1422 1422          case ISCSI_ASYNC_EVENT_SCSI_EVENT:
1423 1423                  /*
1424 1424                   * SCSI asynchronous event is reported in
1425 1425                   * the sense data.  Sense data that accompanies
1426 1426                   * the report in the data segment identifies the
1427 1427                   * condition.  If the target supports SCSI
1428 1428                   * asynchronous events reporting (see [SAM2])
1429 1429                   * as indicated in the stardard INQUIRY data
1430 1430                   * (see [SPC3]), its use may be enabled by
1431 1431                   * parameters in the SCSI control mode page
1432 1432                   * (see [SPC3]).
1433 1433                   *
1434 1434                   * T-10 has removed SCSI asunchronous events
1435 1435                   * from the standard.  Although we have seen
1436 1436                   * a couple targets still spending these requests.
1437 1437                   * Those targets were specifically sending them
1438 1438                   * for notification of a LUN/Volume change
1439 1439                   * (ex. LUN addition/removal). Fire the enumeration
1440 1440                   * to handle the change.
1441 1441                   */
1442 1442                  if (isp->sess_type == ISCSI_SESS_TYPE_NORMAL) {
1443 1443                          rw_enter(&isp->sess_state_rwlock, RW_READER);
1444 1444                          if (isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) {
1445 1445                                  (void) iscsi_sess_enum_request(isp, B_FALSE,
1446 1446                                      isp->sess_state_event_count);
1447 1447                          }
1448 1448                          rw_exit(&isp->sess_state_rwlock);
1449 1449                  }
1450 1450                  break;
1451 1451  
1452 1452          case ISCSI_ASYNC_EVENT_REQUEST_LOGOUT:
1453 1453                  /*
1454 1454                   * We've been asked to logout by the target --
1455 1455                   * we need to treat this differently from a normal logout
1456 1456                   * due to a discovery failure.  Normal logouts result in
1457 1457                   * an N3 event to the session state machine and an offline
1458 1458                   * of the lun.  In this case we want to put the connection
1459 1459                   * into "failed" state and generate N5 to the session state
1460 1460                   * machine since the initiator logged out at the target's
1461 1461                   * request.  To track this we set a flag indicating we
1462 1462                   * received this async logout request from the tharget
1463 1463                   */
1464 1464                  mutex_enter(&icp->conn_state_mutex);
1465 1465                  icp->conn_async_logout = B_TRUE;
1466 1466                  mutex_exit(&icp->conn_state_mutex);
1467 1467  
1468 1468                  /* Hold is released in iscsi_handle_logout. */
1469 1469                  idm_conn_hold(ic);
1470 1470  
1471 1471                  /* Target has requested this connection to logout. */
1472 1472                  itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1473 1473                  itp->t_arg = icp;
1474 1474                  itp->t_blocking = B_FALSE;
1475 1475                  if (ddi_taskq_dispatch(isp->sess_login_taskq,
1476 1476                      (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1477 1477                      DDI_SUCCESS) {
1478 1478                          idm_conn_rele(ic);
1479 1479                          /* Disconnect if we couldn't dispatch the task */
1480 1480                          idm_ini_conn_disconnect(ic);
1481 1481                  }
1482 1482                  break;
1483 1483  
1484 1484          case ISCSI_ASYNC_EVENT_DROPPING_CONNECTION:
1485 1485                  /*
1486 1486                   * Target is going to drop our connection.
1487 1487                   *      param1 - CID which will be dropped.
1488 1488                   *      param2 - Min time to reconnect.
1489 1489                   *      param3 - Max time to reconnect.
1490 1490                   *
1491 1491                   * For now just let fail as another disconnect.
1492 1492                   *
1493 1493                   * MC/S Once we support > 1 connections then
1494 1494                   * we need to check the CID and drop that
1495 1495                   * specific connection.
1496 1496                   */
1497 1497                  iscsi_conn_set_login_min_max(icp, iaehp->param2,
1498 1498                      iaehp->param3);
1499 1499                  idm_ini_conn_disconnect(ic);
1500 1500                  break;
1501 1501  
1502 1502          case ISCSI_ASYNC_EVENT_DROPPING_ALL_CONNECTIONS:
1503 1503                  /*
1504 1504                   * Target is going to drop ALL connections.
1505 1505                   *      param2 - Min time to reconnect.
1506 1506                   *      param3 - Max time to reconnect.
1507 1507                   *
1508 1508                   * For now just let fail as anyother disconnect.
1509 1509                   *
1510 1510                   * MC/S Once we support more than > 1 connections
1511 1511                   * then we need to drop all connections on the
1512 1512                   * session.
1513 1513                   */
1514 1514                  iscsi_conn_set_login_min_max(icp, iaehp->param2,
1515 1515                      iaehp->param3);
1516 1516                  idm_ini_conn_disconnect(ic);
1517 1517                  break;
1518 1518  
1519 1519          case ISCSI_ASYNC_EVENT_PARAM_NEGOTIATION:
1520 1520                  /*
1521 1521                   * Target requests parameter negotiation
1522 1522                   * on this connection.
1523 1523                   *
1524 1524                   * The initiator must honor this request.  For
1525 1525                   * now we will request a logout.  We can't
1526 1526                   * just ignore this or it might force corruption?
1527 1527                   */
1528 1528  
1529 1529                  /* Hold is released in iscsi_handle_logout */
1530 1530                  idm_conn_hold(ic);
1531 1531                  itp = kmem_zalloc(sizeof (iscsi_task_t), KM_SLEEP);
1532 1532                  itp->t_arg = icp;
1533 1533                  itp->t_blocking = B_FALSE;
1534 1534                  if (ddi_taskq_dispatch(isp->sess_login_taskq,
1535 1535                      (void(*)())iscsi_logout_start, itp, DDI_SLEEP) !=
1536 1536                      DDI_SUCCESS) {
1537 1537                          /* Disconnect if we couldn't dispatch the task */
1538 1538                          idm_conn_rele(ic);
1539 1539                          idm_ini_conn_disconnect(ic);
1540 1540                  }
1541 1541                  break;
1542 1542  
1543 1543          case ISCSI_ASYNC_EVENT_VENDOR_SPECIFIC:
1544 1544                  /*
1545 1545                   * We currently don't handle any vendor
1546 1546                   * specific async events.  So just ignore
1547 1547                   * the request.
1548 1548                   */
1549 1549                  idm_ini_conn_disconnect(ic);
1550 1550                  break;
1551 1551          default:
1552 1552                  rval = IDM_STATUS_PROTOCOL_ERROR;
1553 1553          }
1554 1554  
1555 1555          return (rval);
1556 1556  }
1557 1557  
1558 1558  /*
1559 1559   * iscsi_rx_process_text_rsp - processes iSCSI text response.  It sets
1560 1560   * the cmd_result field of the command data structure with the actual
1561 1561   * status value instead of returning the status value.  The return value
1562 1562   * is SUCCESS in order to let iscsi_handle_text control the operation of
1563 1563   * a text request.
1564 1564   * Text requests are a handled a little different than other types of
1565 1565   * iSCSI commands because the initiator sends additional empty text requests
1566 1566   * in order to obtain the remaining responses required to complete the
1567 1567   * request.  iscsi_handle_text controls the operation of text request, while
1568 1568   * iscsi_rx_process_text_rsp just process the current response.
1569 1569   */
1570 1570  static idm_status_t
1571 1571  iscsi_rx_process_text_rsp(idm_conn_t *ic, idm_pdu_t *pdu)
1572 1572  {
1573 1573          iscsi_sess_t            *isp    = NULL;
1574 1574          iscsi_text_rsp_hdr_t    *ithp   =
1575 1575              (iscsi_text_rsp_hdr_t *)pdu->isp_hdr;
1576 1576          iscsi_conn_t            *icp    = ic->ic_handle;
1577 1577          iscsi_cmd_t             *icmdp  = NULL;
1578 1578          boolean_t               final   = B_FALSE;
1579 1579          uint32_t                data_len;
1580 1580          uint8_t                 *data = pdu->isp_data;
1581 1581          idm_status_t            rval;
1582 1582  
1583 1583          isp = icp->conn_sess;
1584 1584  
1585 1585          mutex_enter(&icp->conn_queue_active.mutex);
1586 1586          if ((rval = iscsi_rx_chk(icp, isp, (iscsi_scsi_rsp_hdr_t *)ithp,
1587 1587              &icmdp)) != IDM_STATUS_SUCCESS) {
1588 1588                  mutex_exit(&icp->conn_queue_active.mutex);
1589 1589                  return (rval);
1590 1590          }
1591 1591  
1592 1592          /* update local final response flag */
1593 1593          if (ithp->flags & ISCSI_FLAG_FINAL) {
1594 1594                  final = B_TRUE;
1595 1595          }
1596 1596  
1597 1597          /*
1598 1598           * validate received TTT value.  RFC3720 specifies the following:
1599 1599           * - F bit set to 1 MUST have a reserved TTT value 0xffffffff
1600 1600           * - F bit set to 0 MUST have a non-reserved TTT value !0xffffffff
1601 1601           * In addition, the received TTT value must not change between
1602 1602           * responses of a long text response
1603 1603           */
1604 1604          if (((final == B_TRUE) && (ithp->ttt != ISCSI_RSVD_TASK_TAG)) ||
1605 1605              ((final == B_FALSE) && (ithp->ttt == ISCSI_RSVD_TASK_TAG))) {
1606 1606                  icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1607 1607                  icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1608 1608                  mutex_exit(&icp->conn_queue_active.mutex);
1609 1609                  cmn_err(CE_WARN, "iscsi connection(%u) protocol error - "
1610 1610                      "received text response with invalid flags:0x%x or "
1611 1611                      "ttt:0x%x", icp->conn_oid, ithp->flags, ithp->itt);
1612 1612                  return (IDM_STATUS_PROTOCOL_ERROR);
1613 1613          }
1614 1614  
1615 1615          if ((icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) &&
1616 1616              (ithp->ttt == ISCSI_RSVD_TASK_TAG) &&
1617 1617              (final == B_FALSE)) {
1618 1618                  /* TTT should have matched reserved value */
1619 1619                  icmdp->cmd_result = ISCSI_STATUS_PROTOCOL_ERROR;
1620 1620                  icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1621 1621                  mutex_exit(&icp->conn_queue_active.mutex);
1622 1622                  cmn_err(CE_WARN, "iscsi connection(%u) protocol "
1623 1623                      "error - received text response with invalid "
1624 1624                      "ttt:0x%x", icp->conn_oid, ithp->ttt);
1625 1625                  return (IDM_STATUS_PROTOCOL_ERROR);
1626 1626          }
1627 1627  
1628 1628          /*
1629 1629           * If this is first response, save away TTT value for later use
1630 1630           * in a long text request/response sequence
1631 1631           */
1632 1632          if (icmdp->cmd_un.text.stage == ISCSI_CMD_TEXT_INITIAL_REQ) {
1633 1633                  icmdp->cmd_un.text.ttt = ithp->ttt;
1634 1634          }
1635 1635  
1636 1636          data_len = ntoh24(ithp->dlength);
1637 1637  
1638 1638          /* check whether enough buffer available to copy data */
1639 1639          if ((icmdp->cmd_un.text.total_rx_len + data_len) >
1640 1640              icmdp->cmd_un.text.buf_len) {
1641 1641                  icmdp->cmd_un.text.total_rx_len += data_len;
1642 1642                  icmdp->cmd_result = ISCSI_STATUS_DATA_OVERFLOW;
1643 1643                  /*
1644 1644                   * DATA_OVERFLOW will result in a SUCCESS return so that
1645 1645                   * iscsi_handle_text can continue to obtain the remaining
1646 1646                   * text response if needed.
1647 1647                   */
1648 1648          } else {
1649 1649                  char *buf_data = (icmdp->cmd_un.text.buf +
1650 1650                      icmdp->cmd_un.text.offset);
1651 1651  
1652 1652                  bcopy(data, buf_data, data_len);
1653 1653                  icmdp->cmd_un.text.offset += data_len;
1654 1654                  icmdp->cmd_un.text.total_rx_len += data_len;
1655 1655                  icmdp->cmd_result = ISCSI_STATUS_SUCCESS;
1656 1656                  bcopy(ithp->rsvd4, icmdp->cmd_un.text.lun,
1657 1657                      sizeof (icmdp->cmd_un.text.lun));
1658 1658          }
1659 1659  
1660 1660          /* update stage  */
1661 1661          if (final == B_TRUE) {
1662 1662                  icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_FINAL_RSP;
1663 1663          } else {
1664 1664                  icmdp->cmd_un.text.stage = ISCSI_CMD_TEXT_CONTINUATION;
1665 1665          }
1666 1666  
1667 1667          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E3, isp);
1668 1668          mutex_exit(&icp->conn_queue_active.mutex);
1669 1669          return (IDM_STATUS_SUCCESS);
1670 1670  }
1671 1671  
1672 1672  /*
1673 1673   * iscsi_rx_process_scsi_itt_to_icmdp - Lookup itt using IDM to find matching
1674 1674   * icmdp.  Verify itt in hdr and icmdp are the same.
1675 1675   */
1676 1676  static iscsi_status_t
1677 1677  iscsi_rx_process_scsi_itt_to_icmdp(iscsi_sess_t *isp, idm_conn_t *ic,
1678 1678      iscsi_scsi_rsp_hdr_t *ihp, iscsi_cmd_t **icmdp)
1679 1679  {
1680 1680          idm_task_t *itp;
1681 1681  
1682 1682          ASSERT(isp != NULL);
1683 1683          ASSERT(ihp != NULL);
1684 1684          ASSERT(icmdp != NULL);
1685 1685          ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1686 1686          itp = idm_task_find_and_complete(ic, ihp->itt, ISCSI_INI_TASK_TTT);
1687 1687          if (itp == NULL) {
1688 1688                  cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1689 1689                      "received unknown itt:0x%x - protocol error",
1690 1690                      isp->sess_oid, ihp->itt);
1691 1691                  return (ISCSI_STATUS_INTERNAL_ERROR);
1692 1692          }
1693 1693          *icmdp = itp->idt_private;
1694 1694  
1695 1695          idm_task_rele(itp);
1696 1696  
1697 1697          return (ISCSI_STATUS_SUCCESS);
1698 1698  
1699 1699  }
1700 1700  
1701 1701  /*
1702 1702   * iscsi_rx_process_itt_to_icmdp - Lookup itt in the session's
1703 1703   * cmd table to find matching icmdp.  Verify itt in hdr and
1704 1704   * icmdp are the same.
1705 1705   */
1706 1706  static iscsi_status_t
1707 1707  iscsi_rx_process_itt_to_icmdp(iscsi_sess_t *isp, iscsi_hdr_t *ihp,
1708 1708      iscsi_cmd_t **icmdp)
1709 1709  {
1710 1710          int cmd_table_idx = 0;
1711 1711  
1712 1712          ASSERT(isp != NULL);
1713 1713          ASSERT(ihp != NULL);
1714 1714          ASSERT(icmdp != NULL);
1715 1715          ASSERT(mutex_owned(&isp->sess_cmdsn_mutex));
1716 1716  
1717 1717          /* try to find an associated iscsi_pkt */
1718 1718          cmd_table_idx = (ihp->itt - IDM_TASKIDS_MAX) % ISCSI_CMD_TABLE_SIZE;
1719 1719          if (isp->sess_cmd_table[cmd_table_idx] == NULL) {
1720 1720                  cmn_err(CE_WARN, "iscsi session(%u) protocol error - "
1721 1721                      "received unknown itt:0x%x - protocol error",
1722 1722                      isp->sess_oid, ihp->itt);
1723 1723                  return (ISCSI_STATUS_INTERNAL_ERROR);
1724 1724          }
1725 1725  
1726 1726          /* verify itt */
1727 1727          if (isp->sess_cmd_table[cmd_table_idx]->cmd_itt != ihp->itt) {
1728 1728                  cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1729 1729                      " which is out of sync with itt:0x%x", isp->sess_oid,
1730 1730                      ihp->itt, isp->sess_cmd_table[cmd_table_idx]->cmd_itt);
1731 1731                  return (ISCSI_STATUS_INTERNAL_ERROR);
1732 1732          }
1733 1733  
1734 1734          /* ensure that icmdp is still in Active state */
1735 1735          if (isp->sess_cmd_table[cmd_table_idx]->cmd_state !=
1736 1736              ISCSI_CMD_STATE_ACTIVE) {
1737 1737                  cmn_err(CE_WARN, "iscsi session(%u) received itt:0x%x "
1738 1738                      "but icmdp (%p) is not in active state",
1739 1739                      isp->sess_oid, ihp->itt,
1740 1740                      (void *)isp->sess_cmd_table[cmd_table_idx]);
1741 1741                  return (ISCSI_STATUS_INTERNAL_ERROR);
1742 1742          }
1743 1743  
1744 1744          /* make sure this is a SCSI cmd */
1745 1745          *icmdp = isp->sess_cmd_table[cmd_table_idx];
1746 1746  
1747 1747          return (ISCSI_STATUS_SUCCESS);
1748 1748  }
1749 1749  
1750 1750  /*
1751 1751   * +--------------------------------------------------------------------+
1752 1752   * | End of protocol receive routines                                   |
1753 1753   * +--------------------------------------------------------------------+
1754 1754   */
1755 1755  
1756 1756  /*
1757 1757   * +--------------------------------------------------------------------+
1758 1758   * | Beginning of protocol send routines                                |
1759 1759   * +--------------------------------------------------------------------+
1760 1760   */
1761 1761  
1762 1762  
1763 1763  /*
1764 1764   * iscsi_tx_thread - This thread is the driving point for all
1765 1765   * iSCSI PDUs after login.  No PDUs should call idm_pdu_tx()
1766 1766   * directly they should be funneled through iscsi_tx_thread.
1767 1767   */
1768 1768  void
1769 1769  iscsi_tx_thread(iscsi_thread_t *thread, void *arg)
1770 1770  {
1771 1771          iscsi_conn_t    *icp    = (iscsi_conn_t *)arg;
1772 1772          iscsi_sess_t    *isp    = NULL;
1773 1773          iscsi_cmd_t     *icmdp  = NULL;
1774 1774          clock_t         tout;
1775 1775          int             ret     = 1;
1776 1776  
1777 1777          ASSERT(icp != NULL);
1778 1778          isp = icp->conn_sess;
1779 1779          ASSERT(isp != NULL);
1780 1780          ASSERT(thread != NULL);
1781 1781          ASSERT(thread->signature == SIG_ISCSI_THREAD);
1782 1782  
1783 1783          tout = SEC_TO_TICK(1);
1784 1784          /*
1785 1785           * Transfer icmdps until shutdown by owning session.
1786 1786           */
1787 1787          while (ret != 0) {
1788 1788  
1789 1789                  isp->sess_window_open = B_TRUE;
1790 1790                  /*
1791 1791                   * While the window is open, there are commands available
1792 1792                   * to send and the session state allows those commands to
1793 1793                   * be sent try to transfer them.
1794 1794                   */
1795 1795                  mutex_enter(&isp->sess_queue_pending.mutex);
1796 1796                  while ((isp->sess_window_open == B_TRUE) &&
1797 1797                      ((icmdp = isp->sess_queue_pending.head) != NULL)) {
1798 1798                          if (((icmdp->cmd_type != ISCSI_CMD_TYPE_SCSI) &&
1799 1799                              (ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state))) ||
1800 1800                              (icp->conn_state == ISCSI_CONN_STATE_LOGGED_IN)) {
1801 1801  
1802 1802                                  /* update command with this connection info */
1803 1803                                  icmdp->cmd_conn = icp;
1804 1804                                  /* attempt to send this command */
1805 1805                                  iscsi_cmd_state_machine(icmdp,
1806 1806                                      ISCSI_CMD_EVENT_E2, isp);
1807 1807  
1808 1808                                  ASSERT(!mutex_owned(
1809 1809                                      &isp->sess_queue_pending.mutex));
1810 1810                                  mutex_enter(&isp->sess_queue_pending.mutex);
1811 1811                          } else {
1812 1812                                  while (icmdp != NULL) {
1813 1813                                          if ((icmdp->cmd_type !=
1814 1814                                              ISCSI_CMD_TYPE_SCSI) &&
1815 1815                                              (ISCSI_CONN_STATE_FULL_FEATURE
1816 1816                                              (icp->conn_state) != B_TRUE)) {
1817 1817                                                  icmdp->cmd_misc_flags |=
1818 1818                                                      ISCSI_CMD_MISCFLAG_STUCK;
1819 1819                                          } else if (icp->conn_state !=
1820 1820                                              ISCSI_CONN_STATE_LOGGED_IN) {
1821 1821                                                  icmdp->cmd_misc_flags |=
1822 1822                                                      ISCSI_CMD_MISCFLAG_STUCK;
1823 1823                                          }
1824 1824                                          icmdp = icmdp->cmd_next;
1825 1825                                  }
1826 1826                                  break;
1827 1827                          }
1828 1828                  }
1829 1829                  mutex_exit(&isp->sess_queue_pending.mutex);
1830 1830  
1831 1831                  /*
1832 1832                   * Go to sleep until there is something new
1833 1833                   * to process (awoken via cv_boardcast).
1834 1834                   * Or the timer goes off.
1835 1835                   */
1836 1836                  ret = iscsi_thread_wait(thread, tout);
1837 1837          }
1838 1838  
1839 1839  }
1840 1840  
1841 1841  
1842 1842  /*
1843 1843   * iscsi_tx_cmd - transfers icmdp across wire as iscsi pdu
1844 1844   *
1845 1845   * Just prior to sending the command to the networking layer the
1846 1846   * pending queue lock will be dropped.  At this point only local
1847 1847   * resources will be used, not the icmdp.  Holding the queue lock
1848 1848   * across the networking call can lead to a hang.  (This is due
1849 1849   * to the the target driver and networking layers competing use
1850 1850   * of the timeout() resources and the queue lock being held for
1851 1851   * both sides.)  Upon the completion of this command the lock
1852 1852   * will have been re-acquired.
1853 1853   */
1854 1854  iscsi_status_t
1855 1855  iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
1856 1856  {
1857 1857          iscsi_status_t  rval = ISCSI_STATUS_INTERNAL_ERROR;
1858 1858  
1859 1859          ASSERT(isp != NULL);
1860 1860          ASSERT(icmdp != NULL);
1861 1861  
1862 1862          /* transfer specific command type */
1863 1863          switch (icmdp->cmd_type) {
1864 1864          case ISCSI_CMD_TYPE_SCSI:
1865 1865                  rval = iscsi_tx_scsi(isp, icmdp);
1866 1866                  break;
1867 1867          case ISCSI_CMD_TYPE_NOP:
1868 1868                  rval = iscsi_tx_nop(isp, icmdp);
1869 1869                  break;
1870 1870          case ISCSI_CMD_TYPE_ABORT:
1871 1871                  rval = iscsi_tx_abort(isp, icmdp);
1872 1872                  break;
1873 1873          case ISCSI_CMD_TYPE_RESET:
1874 1874                  rval = iscsi_tx_reset(isp, icmdp);
1875 1875                  break;
1876 1876          case ISCSI_CMD_TYPE_LOGOUT:
1877 1877                  rval = iscsi_tx_logout(isp, icmdp);
1878 1878                  break;
1879 1879          case ISCSI_CMD_TYPE_TEXT:
1880 1880                  rval = iscsi_tx_text(isp, icmdp);
1881 1881                  break;
1882 1882          default:
1883 1883                  cmn_err(CE_WARN, "iscsi_tx_cmd: invalid cmdtype: %d",
1884 1884                      icmdp->cmd_type);
1885 1885                  ASSERT(FALSE);
1886 1886          }
1887 1887  
1888 1888          ASSERT(!mutex_owned(&isp->sess_queue_pending.mutex));
1889 1889          return (rval);
1890 1890  }
1891 1891  
1892 1892  /*
1893 1893   * a variable length cdb can be up to 16K, but we obviously don't want
1894 1894   * to put that on the stack; go with 200 bytes; if we get something
1895 1895   * bigger than that we will kmem_alloc a buffer
1896 1896   */
1897 1897  #define DEF_CDB_LEN     200
1898 1898  
1899 1899  /*
1900 1900   * given the size of the cdb, return how many bytes the header takes,
1901 1901   * which is the sizeof addl_hdr_t + the CDB size, minus the 16 bytes
1902 1902   * stored in the basic header, minus sizeof (ahs_extscb)
1903 1903   */
1904 1904  #define ADDLHDRSZ(x)            (sizeof (iscsi_addl_hdr_t) + (x) - \
1905 1905                                          16 - 4)
1906 1906  
1907 1907  static void
1908 1908  iscsi_tx_init_hdr(iscsi_sess_t *isp, iscsi_conn_t *icp,
1909 1909      iscsi_text_hdr_t *ihp, int opcode, iscsi_cmd_t *icmdp)
1910 1910  {
1911 1911          ihp->opcode             = opcode;
1912 1912          ihp->itt                = icmdp->cmd_itt;
1913 1913          mutex_enter(&isp->sess_cmdsn_mutex);
1914 1914          icmdp->cmd_sn           = isp->sess_cmdsn;
1915 1915          ihp->cmdsn              = htonl(isp->sess_cmdsn);
1916 1916          isp->sess_cmdsn++;
1917 1917          mutex_exit(&isp->sess_cmdsn_mutex);
1918 1918          ihp->expstatsn          = htonl(icp->conn_expstatsn);
1919 1919          icp->conn_laststatsn = icp->conn_expstatsn;
1920 1920  }
1921 1921  
1922 1922  
1923 1923  static void
1924 1924  iscsi_tx_scsi_data(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp,
1925 1925      iscsi_conn_t *icp, idm_pdu_t *pdu)
1926 1926  {
1927 1927          struct buf              *bp             = NULL;
1928 1928          size_t                  buflen          = 0;
1929 1929          uint32_t                first_burst_length = 0;
1930 1930          struct scsi_pkt         *pkt;
1931 1931  
1932 1932          pkt = icmdp->cmd_un.scsi.pkt;
1933 1933          bp = icmdp->cmd_un.scsi.bp;
1934 1934          if ((bp != NULL) && bp->b_bcount) {
1935 1935                  buflen = bp->b_bcount;
1936 1936                  first_burst_length =
1937 1937                      icp->conn_params.first_burst_length;
1938 1938  
1939 1939                  if (bp->b_flags & B_READ) {
1940 1940                          ihp->flags = ISCSI_FLAG_FINAL;
1941 1941                          /*
1942 1942                           * fix problem where OS sends bp (B_READ &
1943 1943                           * b_bcount!=0) for a TUR or START_STOP.
1944 1944                           * (comment came from cisco code.)
1945 1945                           */
1946 1946                          if ((pkt->pkt_cdbp[0] != SCMD_TEST_UNIT_READY) &&
1947 1947                              (pkt->pkt_cdbp[0] != SCMD_START_STOP)) {
1948 1948                                  ihp->flags |= ISCSI_FLAG_CMD_READ;
1949 1949                                  ihp->data_length = htonl(buflen);
1950 1950                          }
1951 1951                  } else {
1952 1952                          ihp->flags = ISCSI_FLAG_CMD_WRITE;
1953 1953                          /*
1954 1954                           * FinalBit on the the iSCSI PDU denotes this
1955 1955                           * is the last PDU in the sequence.
1956 1956                           *
1957 1957                           * initial_r2t = true means R2T is required
1958 1958                           * for additional PDU, so there will be no more
1959 1959                           * unsolicited PDUs following
1960 1960                           */
1961 1961                          if (icp->conn_params.initial_r2t) {
1962 1962                                  ihp->flags |= ISCSI_FLAG_FINAL;
1963 1963                          }
1964 1964  
1965 1965                          /* Check if we should send ImmediateData */
1966 1966                          if (icp->conn_params.immediate_data) {
1967 1967                                  pdu->isp_data =
1968 1968                                      (uint8_t *)icmdp->
1969 1969                                      cmd_un.scsi.bp->b_un.b_addr;
1970 1970  
1971 1971                                  pdu->isp_datalen = MIN(MIN(buflen,
1972 1972                                      first_burst_length),
1973 1973                                      icmdp->cmd_conn->conn_params.
1974 1974                                      max_xmit_data_seg_len);
1975 1975  
1976 1976                                  /*
1977 1977                                   * if everything fits immediate, or
1978 1978                                   * we can send all burst data immediate
1979 1979                                   * (not unsol), set F
1980 1980                                   */
1981 1981                                  /*
1982 1982                                   * XXX This doesn't look right -- it's not
1983 1983                                   * clear how we can handle transmitting
1984 1984                                   * any unsolicited data.  It looks like
1985 1985                                   * we only support immediate data.  So what
1986 1986                                   * happens if we don't set ISCSI_FLAG_FINAL?
1987 1987                                   *
1988 1988                                   * Unless there's magic code somewhere that
1989 1989                                   * is sending the remaining PDU's we should
1990 1990                                   * simply set ISCSI_FLAG_FINAL and forget
1991 1991                                   * about sending unsolicited data.  The big
1992 1992                                   * win is the immediate data anyway for small
1993 1993                                   * PDU's.
1994 1994                                   */
1995 1995                                  if ((pdu->isp_datalen == buflen) ||
1996 1996                                      (pdu->isp_datalen == first_burst_length)) {
1997 1997                                          ihp->flags |= ISCSI_FLAG_FINAL;
1998 1998                                  }
1999 1999  
2000 2000                                  hton24(ihp->dlength, pdu->isp_datalen);
2001 2001                          }
2002 2002                          /* total data transfer length */
2003 2003                          ihp->data_length = htonl(buflen);
2004 2004                  }
2005 2005          } else {
2006 2006                  ihp->flags = ISCSI_FLAG_FINAL;
2007 2007          }
2008 2008          icmdp->cmd_un.scsi.data_transferred += pdu->isp_datalen;
2009 2009          /* XXX How is this different from the code above? */
2010 2010          /* will idm send the next data command up to burst length? */
2011 2011          /* send the burstlen if we haven't sent immediate data */
2012 2012          /* CRM: should idm send difference min(buflen, first_burst) and  imm? */
2013 2013          /*    (MIN(first_burst_length, buflen) - imdata > 0) */
2014 2014          /* CRM_LATER: change this to generate unsolicited pdu */
2015 2015          if ((buflen > 0) &&
2016 2016              ((bp->b_flags & B_READ) == 0) &&
2017 2017              (icp->conn_params.initial_r2t == 0) &&
2018 2018              pdu->isp_datalen == 0) {
2019 2019  
2020 2020                  pdu->isp_datalen = MIN(first_burst_length, buflen);
2021 2021                  if ((pdu->isp_datalen == buflen) ||
2022 2022                      (pdu->isp_datalen == first_burst_length)) {
2023 2023                          ihp->flags |= ISCSI_FLAG_FINAL;
2024 2024                  }
2025 2025                  pdu->isp_data = (uint8_t *)icmdp->cmd_un.scsi.bp->b_un.b_addr;
2026 2026                  hton24(ihp->dlength, pdu->isp_datalen);
2027 2027          }
2028 2028  }
2029 2029  
2030 2030  static void
2031 2031  iscsi_tx_scsi_init_pkt(iscsi_cmd_t *icmdp, iscsi_scsi_cmd_hdr_t *ihp)
2032 2032  {
2033 2033          struct scsi_pkt *pkt;
2034 2034  
2035 2035          pkt = icmdp->cmd_un.scsi.pkt;
2036 2036          pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET);
2037 2037          pkt->pkt_reason = CMD_INCOMPLETE;
2038 2038  
2039 2039          /* tagged queuing */
2040 2040          if (pkt->pkt_flags & FLAG_HTAG) {
2041 2041                  ihp->flags |= ISCSI_ATTR_HEAD_OF_QUEUE;
2042 2042          } else if (pkt->pkt_flags & FLAG_OTAG) {
2043 2043                  ihp->flags |= ISCSI_ATTR_ORDERED;
2044 2044          } else if (pkt->pkt_flags & FLAG_STAG) {
2045 2045                  ihp->flags |= ISCSI_ATTR_SIMPLE;
2046 2046          } else {
2047 2047                  /* ihp->flags |= ISCSI_ATTR_UNTAGGED; */
2048 2048                  /* EMPTY */
2049 2049          }
2050 2050  
2051 2051          /* iscsi states lun is based on spc.2 */
2052 2052          ISCSI_LUN_BYTE_COPY(ihp->lun, icmdp->cmd_un.scsi.lun);
2053 2053  
2054 2054          if (icmdp->cmd_un.scsi.cmdlen <= 16) {
2055 2055                  /* copy the SCSI Command Block into the PDU */
2056 2056                  bcopy(pkt->pkt_cdbp, ihp->scb,
2057 2057                      icmdp->cmd_un.scsi.cmdlen);
2058 2058          } else {
2059 2059                  iscsi_addl_hdr_t *iahp;
2060 2060  
2061 2061                  iahp = (iscsi_addl_hdr_t *)ihp;
2062 2062  
2063 2063                  ihp->hlength = (ADDLHDRSZ(icmdp->cmd_un.scsi.cmdlen) -
2064 2064                      sizeof (iscsi_scsi_cmd_hdr_t) + 3) / 4;
2065 2065                  iahp->ahs_hlen_hi = 0;
2066 2066                  iahp->ahs_hlen_lo = (icmdp->cmd_un.scsi.cmdlen - 15);
2067 2067                  iahp->ahs_key = 0x01;
2068 2068                  iahp->ahs_resv = 0;
2069 2069                  bcopy(pkt->pkt_cdbp, ihp->scb, 16);
2070 2070                  bcopy(((char *)pkt->pkt_cdbp) + 16, &iahp->ahs_extscb[0],
2071 2071                      icmdp->cmd_un.scsi.cmdlen);
2072 2072          }
2073 2073  
2074 2074          /*
2075 2075           * Update all values before transfering.
2076 2076           * We should never touch the icmdp after
2077 2077           * transfering if there is no more data
2078 2078           * to send.  The only case the idm_pdu_tx()
2079 2079           * will fail is a on a connection disconnect
2080 2080           * in that case the command will be flushed.
2081 2081           */
2082 2082          pkt->pkt_state |= STATE_SENT_CMD;
2083 2083  }
2084 2084  
2085 2085  static void
2086 2086  iscsi_tx_scsi_init_task(iscsi_cmd_t *icmdp, iscsi_conn_t *icp,
2087 2087      iscsi_scsi_cmd_hdr_t *ihp)
2088 2088  {
2089 2089          idm_task_t              *itp;
2090 2090          struct buf              *bp             = NULL;
2091 2091          uint32_t                data_length;
2092 2092  
2093 2093          bp = icmdp->cmd_un.scsi.bp;
2094 2094  
2095 2095          itp = icmdp->cmd_itp;
2096 2096          ASSERT(itp != NULL);
2097 2097          data_length = ntohl(ihp->data_length);
2098 2098          ISCSI_IO_LOG(CE_NOTE,
2099 2099              "DEBUG: iscsi_tx_init_task: task_start: %p idt_tt: %x cmdsn: %x "
2100 2100              "sess_cmdsn: %x cmd: %p "
2101 2101              "cmdtype: %d datalen: %u",
2102 2102              (void *)itp, itp->idt_tt, ihp->cmdsn, icp->conn_sess->sess_cmdsn,
2103 2103              (void *)icmdp, icmdp->cmd_type, data_length);
2104 2104          if (data_length > 0) {
2105 2105                  if (bp->b_flags & B_READ) {
2106 2106                          icmdp->cmd_un.scsi.ibp_ibuf =
2107 2107                              idm_buf_alloc(icp->conn_ic,
2108 2108                              bp->b_un.b_addr, bp->b_bcount);
2109 2109                          if (icmdp->cmd_un.scsi.ibp_ibuf)
2110 2110                                  idm_buf_bind_in(itp,
2111 2111                                      icmdp->cmd_un.scsi.ibp_ibuf);
2112 2112                  } else {
2113 2113                          icmdp->cmd_un.scsi.ibp_obuf =
2114 2114                              idm_buf_alloc(icp->conn_ic,
2115 2115                              bp->b_un.b_addr, bp->b_bcount);
2116 2116                          if (icmdp->cmd_un.scsi.ibp_obuf)
2117 2117                                  idm_buf_bind_out(itp,
2118 2118                                      icmdp->cmd_un.scsi.ibp_obuf);
2119 2119                  }
2120 2120                  ISCSI_IO_LOG(CE_NOTE,
2121 2121                      "DEBUG: pdu_tx: task_start(%s): %p ic: %p idt_tt: %x "
2122 2122                      "cmdsn: %x sess_cmdsn: %x sess_expcmdsn: %x obuf: %p "
2123 2123                      "cmdp: %p cmdtype: %d "
2124 2124                      "buflen: %lu " "bpaddr: %p datalen: %u ",
2125 2125                      bp->b_flags & B_READ ? "B_READ" : "B_WRITE",
2126 2126                      (void *)itp, (void *)icp->conn_ic,
2127 2127                      itp->idt_tt, ihp->cmdsn,
2128 2128                      icp->conn_sess->sess_cmdsn,
2129 2129                      icp->conn_sess->sess_expcmdsn,
2130 2130                      (void *)icmdp->cmd_un.scsi.ibp_ibuf,
2131 2131                      (void *)icmdp, icmdp->cmd_type, bp->b_bcount,
2132 2132                      (void *)bp->b_un.b_addr,
2133 2133                      data_length);
2134 2134          }
2135 2135  
2136 2136          /*
2137 2137           * Task is now active
2138 2138           */
2139 2139          idm_task_start(itp, ISCSI_INI_TASK_TTT);
2140 2140  }
2141 2141  
2142 2142  /*
2143 2143   * iscsi_tx_scsi -
2144 2144   *
2145 2145   */
2146 2146  static iscsi_status_t
2147 2147  iscsi_tx_scsi(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2148 2148  {
2149 2149          iscsi_status_t          rval            = ISCSI_STATUS_SUCCESS;
2150 2150          iscsi_conn_t            *icp            = NULL;
2151 2151          struct scsi_pkt         *pkt            = NULL;
2152 2152          iscsi_scsi_cmd_hdr_t    *ihp            = NULL;
2153 2153          int                     cdblen          = 0;
2154 2154          idm_pdu_t               *pdu;
2155 2155          int                     len;
2156 2156  
2157 2157          ASSERT(isp != NULL);
2158 2158          ASSERT(icmdp != NULL);
2159 2159  
2160 2160          pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2161 2161  
2162 2162          pkt = icmdp->cmd_un.scsi.pkt;
2163 2163          ASSERT(pkt != NULL);
2164 2164          icp = icmdp->cmd_conn;
2165 2165          ASSERT(icp != NULL);
2166 2166  
2167 2167          /* Reset counts in case we are on a retry */
2168 2168          icmdp->cmd_un.scsi.data_transferred = 0;
2169 2169  
2170 2170          if (icmdp->cmd_un.scsi.cmdlen > DEF_CDB_LEN) {
2171 2171                  cdblen = icmdp->cmd_un.scsi.cmdlen;
2172 2172                  ihp = kmem_zalloc(ADDLHDRSZ(cdblen), KM_SLEEP);
2173 2173                  len = ADDLHDRSZ(cdblen);
2174 2174          } else {
2175 2175                  /*
2176 2176                   * only bzero the basic header; the additional header
2177 2177                   * will be set up correctly later, if needed
2178 2178                   */
2179 2179                  ihp = kmem_zalloc(sizeof (iscsi_scsi_cmd_hdr_t), KM_SLEEP);
2180 2180                  len = sizeof (iscsi_scsi_cmd_hdr_t);
2181 2181          }
2182 2182  
2183 2183          iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ihp,
2184 2184              ISCSI_OP_SCSI_CMD, icmdp);
2185 2185  
2186 2186          idm_pdu_init(pdu, icp->conn_ic, (void *)icmdp, &iscsi_tx_done);
2187 2187          idm_pdu_init_hdr(pdu, (uint8_t *)ihp, len);
2188 2188          pdu->isp_data = NULL;
2189 2189          pdu->isp_datalen = 0;
2190 2190  
2191 2191          /*
2192 2192           * Sestion 12.11 of the iSCSI specification has a good table
2193 2193           * describing when uncolicited data and/or immediate data
2194 2194           * should be sent.
2195 2195           */
2196 2196  
2197 2197          iscsi_tx_scsi_data(icmdp, ihp, icp, pdu);
2198 2198  
2199 2199          iscsi_tx_scsi_init_pkt(icmdp, ihp);
2200 2200  
2201 2201          /* Calls idm_task_start */
2202 2202          iscsi_tx_scsi_init_task(icmdp, icp, ihp);
2203 2203  
2204 2204          mutex_exit(&isp->sess_queue_pending.mutex);
2205 2205  
2206 2206          idm_pdu_tx(pdu);
2207 2207  
2208 2208          icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2209 2209  
2210 2210          return (rval);
2211 2211  }
2212 2212  
2213 2213  
2214 2214  /* ARGSUSED */
2215 2215  static void
2216 2216  iscsi_tx_done(idm_pdu_t *pdu, idm_status_t status)
2217 2217  {
2218 2218          kmem_free((iscsi_hdr_t *)pdu->isp_hdr, pdu->isp_hdrlen);
2219 2219          kmem_free(pdu, sizeof (idm_pdu_t));
2220 2220  }
2221 2221  
2222 2222  
2223 2223  static void
2224 2224  iscsi_tx_pdu(iscsi_conn_t *icp, int opcode, void *hdr, int hdrlen,
2225 2225      iscsi_cmd_t *icmdp)
2226 2226  {
2227 2227          idm_pdu_t       *tx_pdu;
2228 2228          iscsi_hdr_t     *ihp = (iscsi_hdr_t *)hdr;
2229 2229  
2230 2230          tx_pdu = kmem_zalloc(sizeof (idm_pdu_t), KM_SLEEP);
2231 2231          ASSERT(tx_pdu != NULL);
2232 2232  
2233 2233          idm_pdu_init(tx_pdu, icp->conn_ic, icmdp, &iscsi_tx_done);
2234 2234          idm_pdu_init_hdr(tx_pdu, hdr, hdrlen);
2235 2235          if (opcode == ISCSI_OP_TEXT_CMD) {
2236 2236                  idm_pdu_init_data(tx_pdu,
2237 2237                      (uint8_t *)icmdp->cmd_un.text.buf,
2238 2238                      ntoh24(ihp->dlength));
2239 2239          }
2240 2240  
2241 2241          mutex_exit(&icp->conn_sess->sess_queue_pending.mutex);
2242 2242          idm_pdu_tx(tx_pdu);
2243 2243          icmdp->cmd_misc_flags |= ISCSI_CMD_MISCFLAG_SENT;
2244 2244  }
2245 2245  
2246 2246  
2247 2247  /*
2248 2248   * iscsi_tx_nop -
2249 2249   *
2250 2250   */
2251 2251  static iscsi_status_t
2252 2252  iscsi_tx_nop(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2253 2253  {
2254 2254          iscsi_status_t          rval    = ISCSI_STATUS_SUCCESS;
2255 2255          iscsi_conn_t            *icp    = NULL;
2256 2256          iscsi_nop_out_hdr_t     *inohp;
2257 2257  
2258 2258          ASSERT(isp != NULL);
2259 2259          ASSERT(icmdp != NULL);
2260 2260          icp = icmdp->cmd_conn;
2261 2261          ASSERT(icp != NULL);
2262 2262  
2263 2263          inohp = kmem_zalloc(sizeof (iscsi_nop_out_hdr_t), KM_SLEEP);
2264 2264          ASSERT(inohp != NULL);
2265 2265  
2266 2266          inohp->opcode   = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
2267 2267          inohp->flags    = ISCSI_FLAG_FINAL;
2268 2268          inohp->itt      = icmdp->cmd_itt;
2269 2269          inohp->ttt      = icmdp->cmd_ttt;
2270 2270          mutex_enter(&isp->sess_cmdsn_mutex);
2271 2271          icmdp->cmd_sn   = isp->sess_cmdsn;
2272 2272          inohp->cmdsn    = htonl(isp->sess_cmdsn);
2273 2273          mutex_exit(&isp->sess_cmdsn_mutex);
2274 2274          inohp->expstatsn        = htonl(icp->conn_expstatsn);
2275 2275          icp->conn_laststatsn = icp->conn_expstatsn;
2276 2276          iscsi_tx_pdu(icp, ISCSI_OP_NOOP_OUT, inohp,
2277 2277              sizeof (iscsi_nop_out_hdr_t), icmdp);
2278 2278          return (rval);
2279 2279  }
2280 2280  
2281 2281  
2282 2282  /*
2283 2283   * iscsi_tx_abort -
2284 2284   *
2285 2285   */
2286 2286  static iscsi_status_t
2287 2287  iscsi_tx_abort(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2288 2288  {
2289 2289          iscsi_status_t                  rval    = ISCSI_STATUS_SUCCESS;
2290 2290          iscsi_conn_t                    *icp    = NULL;
2291 2291          iscsi_scsi_task_mgt_hdr_t       *istmh;
2292 2292  
2293 2293          ASSERT(isp != NULL);
2294 2294          ASSERT(icmdp != NULL);
2295 2295          icp = icmdp->cmd_conn;
2296 2296          ASSERT(icp != NULL);
2297 2297  
2298 2298          istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2299 2299          ASSERT(istmh != NULL);
2300 2300          mutex_enter(&isp->sess_cmdsn_mutex);
2301 2301          icmdp->cmd_sn   = isp->sess_cmdsn;
2302 2302          istmh->cmdsn    = htonl(isp->sess_cmdsn);
2303 2303          mutex_exit(&isp->sess_cmdsn_mutex);
2304 2304          istmh->expstatsn = htonl(icp->conn_expstatsn);
2305 2305          icp->conn_laststatsn = icp->conn_expstatsn;
2306 2306          istmh->itt      = icmdp->cmd_itt;
2307 2307          istmh->opcode   = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2308 2308          istmh->function = ISCSI_FLAG_FINAL | ISCSI_TM_FUNC_ABORT_TASK;
2309 2309          ISCSI_LUN_BYTE_COPY(istmh->lun,
2310 2310              icmdp->cmd_un.abort.icmdp->cmd_un.scsi.lun);
2311 2311          istmh->rtt      = icmdp->cmd_un.abort.icmdp->cmd_itt;
2312 2312          iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2313 2313              sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2314 2314  
2315 2315          return (rval);
2316 2316  }
2317 2317  
2318 2318  
2319 2319  /*
2320 2320   * iscsi_tx_reset -
2321 2321   *
2322 2322   */
2323 2323  static iscsi_status_t
2324 2324  iscsi_tx_reset(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2325 2325  {
2326 2326          iscsi_status_t                  rval    = ISCSI_STATUS_SUCCESS;
2327 2327          iscsi_conn_t                    *icp    = NULL;
2328 2328          iscsi_scsi_task_mgt_hdr_t       *istmh;
2329 2329  
2330 2330          ASSERT(isp != NULL);
2331 2331          ASSERT(icmdp != NULL);
2332 2332          icp = icmdp->cmd_conn;
2333 2333          ASSERT(icp != NULL);
2334 2334  
2335 2335          istmh = kmem_zalloc(sizeof (iscsi_scsi_task_mgt_hdr_t), KM_SLEEP);
2336 2336          ASSERT(istmh != NULL);
2337 2337          istmh->opcode   = ISCSI_OP_SCSI_TASK_MGT_MSG | ISCSI_OP_IMMEDIATE;
2338 2338          mutex_enter(&isp->sess_cmdsn_mutex);
2339 2339          icmdp->cmd_sn   = isp->sess_cmdsn;
2340 2340          istmh->cmdsn    = htonl(isp->sess_cmdsn);
2341 2341          mutex_exit(&isp->sess_cmdsn_mutex);
2342 2342          istmh->expstatsn        = htonl(icp->conn_expstatsn);
2343 2343          istmh->itt      = icmdp->cmd_itt;
2344 2344  
2345 2345          switch (icmdp->cmd_un.reset.level) {
2346 2346          case RESET_LUN:
2347 2347                  istmh->function = ISCSI_FLAG_FINAL |
2348 2348                      ISCSI_TM_FUNC_LOGICAL_UNIT_RESET;
2349 2349                  ISCSI_LUN_BYTE_COPY(istmh->lun, icmdp->cmd_lun->lun_num);
2350 2350                  break;
2351 2351          case RESET_TARGET:
2352 2352          case RESET_BUS:
2353 2353                  istmh->function = ISCSI_FLAG_FINAL |
2354 2354                      ISCSI_TM_FUNC_TARGET_WARM_RESET;
2355 2355                  break;
2356 2356          default:
2357 2357                  /* unsupported / unknown level */
2358 2358                  ASSERT(FALSE);
2359 2359                  break;
2360 2360          }
2361 2361  
2362 2362          iscsi_tx_pdu(icp, ISCSI_OP_SCSI_TASK_MGT_MSG, istmh,
2363 2363              sizeof (iscsi_scsi_task_mgt_hdr_t), icmdp);
2364 2364  
2365 2365          return (rval);
2366 2366  }
2367 2367  
2368 2368  
2369 2369  /*
2370 2370   * iscsi_tx_logout -
2371 2371   *
2372 2372   */
2373 2373  static iscsi_status_t
2374 2374  iscsi_tx_logout(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2375 2375  {
2376 2376          iscsi_status_t          rval    = ISCSI_STATUS_SUCCESS;
2377 2377          iscsi_conn_t            *icp    = NULL;
2378 2378          iscsi_logout_hdr_t      *ilh;
2379 2379  
2380 2380          ASSERT(isp != NULL);
2381 2381          ASSERT(icmdp != NULL);
2382 2382          icp = icmdp->cmd_conn;
2383 2383          ASSERT(icp != NULL);
2384 2384  
2385 2385          ilh = kmem_zalloc(sizeof (iscsi_logout_hdr_t), KM_SLEEP);
2386 2386          ilh->opcode     = ISCSI_OP_LOGOUT_CMD | ISCSI_OP_IMMEDIATE;
2387 2387          ilh->flags      = ISCSI_FLAG_FINAL | ISCSI_LOGOUT_REASON_CLOSE_SESSION;
2388 2388          ilh->itt                = icmdp->cmd_itt;
2389 2389          ilh->cid                = icp->conn_cid;
2390 2390          mutex_enter(&isp->sess_cmdsn_mutex);
2391 2391          icmdp->cmd_sn   = isp->sess_cmdsn;
2392 2392          ilh->cmdsn      = htonl(isp->sess_cmdsn);
2393 2393          mutex_exit(&isp->sess_cmdsn_mutex);
2394 2394          ilh->expstatsn  = htonl(icp->conn_expstatsn);
2395 2395          iscsi_tx_pdu(icp, ISCSI_OP_LOGOUT_CMD, ilh,
2396 2396              sizeof (iscsi_logout_hdr_t), icmdp);
2397 2397  
2398 2398          return (rval);
2399 2399  }
2400 2400  
2401 2401  /*
2402 2402   * iscsi_tx_text - setup iSCSI text request header and send PDU with
2403 2403   * data given in the buffer attached to the command.  For a single
2404 2404   * text request, the target may need to send its response in multiple
2405 2405   * text response.  In this case, empty text requests are sent after
2406 2406   * each received response to notify the target the initiator is ready
2407 2407   * for more response.  For the initial request, the data_len field in
2408 2408   * the text specific portion of a command is set to the amount of data
2409 2409   * the initiator wants to send as part of the request. If additional
2410 2410   * empty text requests are required for long responses, the data_len
2411 2411   * field is set to 0 by the iscsi_handle_text function.
2412 2412   */
2413 2413  static iscsi_status_t
2414 2414  iscsi_tx_text(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
2415 2415  {
2416 2416          iscsi_status_t          rval    = ISCSI_STATUS_SUCCESS;
2417 2417          iscsi_conn_t            *icp    = NULL;
2418 2418          iscsi_text_hdr_t        *ith;
2419 2419  
2420 2420          ASSERT(icmdp != NULL);
2421 2421          icp = icmdp->cmd_conn;
2422 2422          ASSERT(icp != NULL);
2423 2423  
2424 2424          ith = kmem_zalloc(sizeof (iscsi_text_hdr_t), KM_SLEEP);
2425 2425          ASSERT(ith != NULL);
2426 2426          ith->flags      = ISCSI_FLAG_FINAL;
2427 2427          hton24(ith->dlength, icmdp->cmd_un.text.data_len);
2428 2428          ith->ttt                = icmdp->cmd_un.text.ttt;
2429 2429          iscsi_tx_init_hdr(isp, icp, (iscsi_text_hdr_t *)ith,
2430 2430              ISCSI_OP_TEXT_CMD, icmdp);
2431 2431          bcopy(icmdp->cmd_un.text.lun, ith->rsvd4, sizeof (ith->rsvd4));
2432 2432  
2433 2433          iscsi_tx_pdu(icp, ISCSI_OP_TEXT_CMD, ith, sizeof (iscsi_text_hdr_t),
2434 2434              icmdp);
2435 2435  
2436 2436          return (rval);
2437 2437  }
2438 2438  
2439 2439  /*
2440 2440   * +--------------------------------------------------------------------+
2441 2441   * | End of protocol send routines                                      |
2442 2442   * +--------------------------------------------------------------------+
2443 2443   */
2444 2444  
2445 2445  /*
2446 2446   * iscsi_handle_abort -
2447 2447   *
2448 2448   */
2449 2449  void
2450 2450  iscsi_handle_abort(void *arg)
2451 2451  {
2452 2452          iscsi_sess_t    *isp            = NULL;
2453 2453          iscsi_cmd_t     *icmdp          = (iscsi_cmd_t *)arg;
2454 2454          iscsi_cmd_t     *new_icmdp;
2455 2455          iscsi_conn_t    *icp;
2456 2456  
2457 2457          ASSERT(icmdp != NULL);
2458 2458          icp = icmdp->cmd_conn;
2459 2459          ASSERT(icp != NULL);
2460 2460          isp = icp->conn_sess;
2461 2461          ASSERT(isp != NULL);
2462 2462  
2463 2463          /* there should only be one abort */
2464 2464          ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
2465 2465  
2466 2466          new_icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2467 2467          new_icmdp->cmd_type                 = ISCSI_CMD_TYPE_ABORT;
2468 2468          new_icmdp->cmd_lun                  = icmdp->cmd_lun;
2469 2469          new_icmdp->cmd_un.abort.icmdp       = icmdp;
2470 2470          new_icmdp->cmd_conn                 = icmdp->cmd_conn;
2471 2471          icmdp->cmd_un.scsi.abort_icmdp      = new_icmdp;
2472 2472  
2473 2473          /* pending queue mutex is already held by timeout_checks */
2474 2474          iscsi_cmd_state_machine(new_icmdp, ISCSI_CMD_EVENT_E1, isp);
2475 2475  }
2476 2476  
2477 2477  /*
2478 2478   * Callback from IDM indicating that the task has been suspended or aborted.
2479 2479   */
2480 2480  void
2481 2481  iscsi_task_aborted(idm_task_t *idt, idm_status_t status)
2482 2482  {
2483 2483          iscsi_cmd_t *icmdp = idt->idt_private;
2484 2484          iscsi_conn_t *icp = icmdp->cmd_conn;
2485 2485          iscsi_sess_t *isp = icp->conn_sess;
2486 2486  
2487 2487          ASSERT(icmdp->cmd_conn != NULL);
2488 2488  
2489 2489          switch (status) {
2490 2490          case IDM_STATUS_SUSPENDED:
2491 2491                  /*
2492 2492                   * If the task is suspended, it may be aborted later,
2493 2493                   * so we can ignore this notification.
2494 2494                   */
2495 2495                  break;
2496 2496  
2497 2497          case IDM_STATUS_ABORTED:
2498 2498                  mutex_enter(&icp->conn_queue_active.mutex);
2499 2499                  iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E9, isp);
2500 2500                  mutex_exit(&icp->conn_queue_active.mutex);
2501 2501                  break;
2502 2502  
2503 2503          default:
2504 2504                  /*
2505 2505                   * Unexpected status.
2506 2506                   */
2507 2507                  ASSERT(0);
2508 2508          }
2509 2509  
2510 2510  }
2511 2511  
2512 2512  /*
2513 2513   * iscsi_handle_nop -
2514 2514   *
2515 2515   */
2516 2516  static void
2517 2517  iscsi_handle_nop(iscsi_conn_t *icp, uint32_t itt, uint32_t ttt)
2518 2518  {
2519 2519          iscsi_sess_t    *isp    = NULL;
2520 2520          iscsi_cmd_t     *icmdp  = NULL;
2521 2521  
2522 2522          ASSERT(icp != NULL);
2523 2523          isp = icp->conn_sess;
2524 2524          ASSERT(isp != NULL);
2525 2525  
2526 2526          icmdp = iscsi_cmd_alloc(icp, KM_NOSLEEP);
2527 2527          if (icmdp == NULL) {
2528 2528                  return;
2529 2529          }
2530 2530  
2531 2531          icmdp->cmd_type         = ISCSI_CMD_TYPE_NOP;
2532 2532          icmdp->cmd_itt          = itt;
2533 2533          icmdp->cmd_ttt          = ttt;
2534 2534          icmdp->cmd_lun          = NULL;
2535 2535          icp->conn_nop_lbolt     = ddi_get_lbolt();
2536 2536  
2537 2537          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2538 2538  }
2539 2539  
2540 2540  /*
2541 2541   * iscsi_handle_reset - send reset request to the target
2542 2542   *
2543 2543   */
2544 2544  iscsi_status_t
2545 2545  iscsi_handle_reset(iscsi_sess_t *isp, int level, iscsi_lun_t *ilp)
2546 2546  {
2547 2547          iscsi_status_t  rval    = ISCSI_STATUS_SUCCESS;
2548 2548          iscsi_conn_t    *icp;
2549 2549          iscsi_cmd_t     icmd;
2550 2550  
2551 2551          ASSERT(isp != NULL);
2552 2552  
2553 2553          if (level == RESET_LUN) {
2554 2554                  rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2555 2555                  ASSERT(ilp != NULL);
2556 2556                  if (ilp->lun_state & ISCSI_LUN_STATE_BUSY) {
2557 2557                          rw_exit(&isp->sess_lun_list_rwlock);
2558 2558                          return (ISCSI_STATUS_SUCCESS);
2559 2559                  }
2560 2560                  ilp->lun_state |= ISCSI_LUN_STATE_BUSY;
2561 2561                  rw_exit(&isp->sess_lun_list_rwlock);
2562 2562          } else {
2563 2563                  mutex_enter(&isp->sess_reset_mutex);
2564 2564                  if (isp->sess_reset_in_progress == B_TRUE) {
2565 2565                          /*
2566 2566                           * If the reset is in progress, it is unnecessary
2567 2567                           * to send reset to the target redunantly.
2568 2568                           */
2569 2569                          mutex_exit(&isp->sess_reset_mutex);
2570 2570                          return (ISCSI_STATUS_SUCCESS);
2571 2571                  }
2572 2572                  isp->sess_reset_in_progress = B_TRUE;
2573 2573                  mutex_exit(&isp->sess_reset_mutex);
2574 2574          }
2575 2575  
2576 2576          bzero(&icmd, sizeof (iscsi_cmd_t));
2577 2577          icmd.cmd_sig            = ISCSI_SIG_CMD;
2578 2578          icmd.cmd_state          = ISCSI_CMD_STATE_FREE;
2579 2579          icmd.cmd_type           = ISCSI_CMD_TYPE_RESET;
2580 2580          icmd.cmd_lun            = ilp;
2581 2581          icmd.cmd_un.reset.level = level;
2582 2582          icmd.cmd_result         = ISCSI_STATUS_SUCCESS;
2583 2583          icmd.cmd_completed      = B_FALSE;
2584 2584          icmd.cmd_un.reset.response = SCSI_TCP_TM_RESP_COMPLETE;
2585 2585  
2586 2586          mutex_init(&icmd.cmd_mutex, NULL, MUTEX_DRIVER, NULL);
2587 2587          cv_init(&icmd.cmd_completion, NULL, CV_DRIVER, NULL);
2588 2588          /*
2589 2589           * If we received an IO and we are not in the
2590 2590           * LOGGED_IN state we are in the process of
2591 2591           * failing.  Just respond that we are BUSY.
2592 2592           */
2593 2593          rw_enter(&isp->sess_state_rwlock, RW_READER);
2594 2594          if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2595 2595                  /* We aren't connected to the target fake success */
2596 2596                  rw_exit(&isp->sess_state_rwlock);
2597 2597  
2598 2598                  if (level == RESET_LUN) {
2599 2599                          rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2600 2600                          ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2601 2601                          rw_exit(&isp->sess_lun_list_rwlock);
2602 2602                  } else {
2603 2603                          mutex_enter(&isp->sess_reset_mutex);
2604 2604                          isp->sess_reset_in_progress = B_FALSE;
2605 2605                          mutex_exit(&isp->sess_reset_mutex);
2606 2606                  }
2607 2607  
2608 2608                  return (ISCSI_STATUS_SUCCESS);
2609 2609          }
2610 2610  
2611 2611          mutex_enter(&isp->sess_queue_pending.mutex);
2612 2612          iscsi_cmd_state_machine(&icmd, ISCSI_CMD_EVENT_E1, isp);
2613 2613          mutex_exit(&isp->sess_queue_pending.mutex);
2614 2614          rw_exit(&isp->sess_state_rwlock);
2615 2615  
2616 2616          /* stall until completed */
2617 2617          mutex_enter(&icmd.cmd_mutex);
2618 2618          while (icmd.cmd_completed == B_FALSE) {
2619 2619                  cv_wait(&icmd.cmd_completion, &icmd.cmd_mutex);
2620 2620          }
2621 2621          mutex_exit(&icmd.cmd_mutex);
2622 2622  
2623 2623          /* copy rval */
2624 2624          rval = icmd.cmd_result;
2625 2625  
2626 2626          if (rval == ISCSI_STATUS_SUCCESS) {
2627 2627                  /*
2628 2628                   * Reset was successful.  We need to flush
2629 2629                   * all active IOs.
2630 2630                   */
2631 2631                  rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
2632 2632                  icp = isp->sess_conn_list;
2633 2633                  while (icp != NULL) {
2634 2634                          iscsi_cmd_t *t_icmdp = NULL;
2635 2635                          iscsi_cmd_t *next_icmdp = NULL;
2636 2636  
2637 2637                          mutex_enter(&icp->conn_queue_active.mutex);
2638 2638                          t_icmdp = icp->conn_queue_active.head;
2639 2639                          while (t_icmdp != NULL) {
2640 2640                                  next_icmdp = t_icmdp->cmd_next;
2641 2641                                  mutex_enter(&t_icmdp->cmd_mutex);
2642 2642                                  if (!(t_icmdp->cmd_misc_flags &
2643 2643                                      ISCSI_CMD_MISCFLAG_SENT)) {
2644 2644                                          /*
2645 2645                                           * Although this command is in the
2646 2646                                           * active queue, it has not been sent.
2647 2647                                           * Skip it.
2648 2648                                           */
2649 2649                                          mutex_exit(&t_icmdp->cmd_mutex);
2650 2650                                          t_icmdp = next_icmdp;
2651 2651                                          continue;
2652 2652                                  }
2653 2653                                  if (level == RESET_LUN) {
2654 2654                                          if (icmd.cmd_lun == NULL ||
2655 2655                                              t_icmdp->cmd_lun == NULL ||
2656 2656                                              (icmd.cmd_lun->lun_num !=
2657 2657                                              t_icmdp->cmd_lun->lun_num)) {
2658 2658                                                  mutex_exit(&t_icmdp->cmd_mutex);
2659 2659                                                  t_icmdp = next_icmdp;
2660 2660                                                  continue;
2661 2661                                          }
2662 2662                                  }
2663 2663  
2664 2664                                  if (icmd.cmd_sn == t_icmdp->cmd_sn) {
2665 2665                                          /*
2666 2666                                           * This command may be replied with
2667 2667                                           * UA sense key later. So currently
2668 2668                                           * it is not a suitable time to flush
2669 2669                                           * it. Mark its flag with FLUSH. There
2670 2670                                           * is no harm to keep it for a while.
2671 2671                                           */
2672 2672                                          t_icmdp->cmd_misc_flags |=
2673 2673                                              ISCSI_CMD_MISCFLAG_FLUSH;
2674 2674                                          if (t_icmdp->cmd_type ==
2675 2675                                              ISCSI_CMD_TYPE_SCSI) {
2676 2676                                                  t_icmdp->cmd_un.scsi.pkt_stat |=
2677 2677                                                      STAT_BUS_RESET;
2678 2678                                          }
2679 2679                                          mutex_exit(&t_icmdp->cmd_mutex);
2680 2680                                  } else if ((icmd.cmd_sn > t_icmdp->cmd_sn) ||
2681 2681                                      ((t_icmdp->cmd_sn - icmd.cmd_sn) >
2682 2682                                      ISCSI_CMD_SN_WRAP)) {
2683 2683                                          /*
2684 2684                                           * This reset request must act on all
2685 2685                                           * the commnds from the same session
2686 2686                                           * having a CmdSN lower than the task
2687 2687                                           * mangement CmdSN. So flush these
2688 2688                                           * commands here.
2689 2689                                           */
2690 2690                                          if (t_icmdp->cmd_type ==
2691 2691                                              ISCSI_CMD_TYPE_SCSI) {
2692 2692                                                  t_icmdp->cmd_un.scsi.pkt_stat |=
2693 2693                                                      STAT_BUS_RESET;
2694 2694                                          }
2695 2695                                          mutex_exit(&t_icmdp->cmd_mutex);
2696 2696                                          iscsi_cmd_state_machine(t_icmdp,
2697 2697                                              ISCSI_CMD_EVENT_E7, isp);
2698 2698                                  } else {
2699 2699                                          mutex_exit(&t_icmdp->cmd_mutex);
2700 2700                                  }
2701 2701  
2702 2702                                  t_icmdp = next_icmdp;
2703 2703                          }
2704 2704  
2705 2705                          mutex_exit(&icp->conn_queue_active.mutex);
2706 2706                          icp = icp->conn_next;
2707 2707                  }
2708 2708                  rw_exit(&isp->sess_conn_list_rwlock);
2709 2709          }
2710 2710  
2711 2711          /* clean up */
2712 2712          cv_destroy(&icmd.cmd_completion);
2713 2713          mutex_destroy(&icmd.cmd_mutex);
2714 2714  
2715 2715          if (level == RESET_LUN) {
2716 2716                  rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
2717 2717                  ilp->lun_state &= ~ISCSI_LUN_STATE_BUSY;
2718 2718                  rw_exit(&isp->sess_lun_list_rwlock);
2719 2719          } else {
2720 2720                  mutex_enter(&isp->sess_reset_mutex);
2721 2721                  isp->sess_reset_in_progress = B_FALSE;
2722 2722                  mutex_exit(&isp->sess_reset_mutex);
2723 2723          }
2724 2724  
2725 2725          return (rval);
2726 2726  }
2727 2727  
2728 2728  /*
2729 2729   * iscsi_logout_start - task handler for deferred logout
2730 2730   * Acquire a hold before call, released in iscsi_handle_logout
2731 2731   */
2732 2732  static void
2733 2733  iscsi_logout_start(void *arg)
2734 2734  {
2735 2735          iscsi_task_t            *itp = (iscsi_task_t *)arg;
2736 2736          iscsi_conn_t            *icp;
2737 2737  
2738 2738          icp = (iscsi_conn_t *)itp->t_arg;
2739 2739  
2740 2740          mutex_enter(&icp->conn_state_mutex);
2741 2741          (void) iscsi_handle_logout(icp);
2742 2742          mutex_exit(&icp->conn_state_mutex);
2743 2743  }
2744 2744  
2745 2745  /*
2746 2746   * iscsi_handle_logout - This function will issue a logout for
2747 2747   * the session from a specific connection.
2748 2748   * Acquire idm_conn_hold before call.  Released internally.
2749 2749   */
2750 2750  iscsi_status_t
2751 2751  iscsi_handle_logout(iscsi_conn_t *icp)
2752 2752  {
2753 2753          iscsi_sess_t    *isp;
2754 2754          idm_conn_t      *ic;
2755 2755          iscsi_cmd_t     *icmdp;
2756 2756          int             rval;
2757 2757  
2758 2758          ASSERT(icp != NULL);
2759 2759          isp = icp->conn_sess;
2760 2760          ic = icp->conn_ic;
2761 2761          ASSERT(isp != NULL);
2762 2762          ASSERT(isp->sess_hba != NULL);
2763 2763          ASSERT(mutex_owned(&icp->conn_state_mutex));
2764 2764  
2765 2765          /*
2766 2766           * If the connection has already gone down (e.g. if the transport
2767 2767           * failed between when this LOGOUT was generated and now) then we
2768 2768           * can and must skip sending the LOGOUT.  Check the same condition
2769 2769           * we use below to determine that connection has "settled".
2770 2770           */
2771 2771          if ((icp->conn_state == ISCSI_CONN_STATE_FREE) ||
2772 2772              (icp->conn_state == ISCSI_CONN_STATE_FAILED) ||
2773 2773              (icp->conn_state == ISCSI_CONN_STATE_POLLING)) {
2774 2774                  idm_conn_rele(ic);
2775 2775                  return (0);
2776 2776          }
2777 2777  
2778 2778          icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2779 2779          ASSERT(icmdp != NULL);
2780 2780          icmdp->cmd_type         = ISCSI_CMD_TYPE_LOGOUT;
2781 2781          icmdp->cmd_result       = ISCSI_STATUS_SUCCESS;
2782 2782          icmdp->cmd_completed    = B_FALSE;
2783 2783  
2784 2784          mutex_enter(&isp->sess_queue_pending.mutex);
2785 2785          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2786 2786          mutex_exit(&isp->sess_queue_pending.mutex);
2787 2787  
2788 2788          /*
2789 2789           * release connection state mutex to avoid a deadlock.  This
2790 2790           * function is called from within the connection state
2791 2791           * machine with the lock held.  When the logout response is
2792 2792           * received another call to the connection state machine
2793 2793           * occurs which causes the deadlock
2794 2794           */
2795 2795          mutex_exit(&icp->conn_state_mutex);
2796 2796  
2797 2797          /* stall until completed */
2798 2798          mutex_enter(&icmdp->cmd_mutex);
2799 2799          while (icmdp->cmd_completed == B_FALSE) {
2800 2800                  cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2801 2801          }
2802 2802          mutex_exit(&icmdp->cmd_mutex);
2803 2803          mutex_enter(&icp->conn_state_mutex);
2804 2804  
2805 2805          /* copy rval */
2806 2806          rval = icmdp->cmd_result;
2807 2807  
2808 2808          /* clean up */
2809 2809          iscsi_cmd_free(icmdp);
2810 2810  
2811 2811          if (rval != 0) {
2812 2812                  /* If the logout failed then drop the connection */
2813 2813                  idm_ini_conn_disconnect(icp->conn_ic);
2814 2814          }
2815 2815  
2816 2816          /* stall until connection settles */
2817 2817          while ((icp->conn_state != ISCSI_CONN_STATE_FREE) &&
2818 2818              (icp->conn_state != ISCSI_CONN_STATE_FAILED) &&
2819 2819              (icp->conn_state != ISCSI_CONN_STATE_POLLING)) {
2820 2820                  /* wait for transition */
2821 2821                  cv_wait(&icp->conn_state_change, &icp->conn_state_mutex);
2822 2822          }
2823 2823  
2824 2824          idm_conn_rele(ic);
2825 2825  
2826 2826          /*
2827 2827           * Return value reflects whether the logout command completed --
2828 2828           * regardless of the return value the connection is closed and
2829 2829           * ready for reconnection.
2830 2830           */
2831 2831          return (rval);
2832 2832  }
2833 2833  
2834 2834  
2835 2835  /*
2836 2836   * iscsi_handle_text - main control function for iSCSI text requests.  This
2837 2837   * function handles allocating the command, sending initial text request, and
2838 2838   * handling long response sequence.
2839 2839   * If a data overflow condition occurs, iscsi_handle_text continues to
2840 2840   * receive responses until the all data has been recieved.  This allows
2841 2841   * the full data length to be returned to the caller.
2842 2842   */
2843 2843  iscsi_status_t
2844 2844  iscsi_handle_text(iscsi_conn_t *icp, char *buf, uint32_t buf_len,
2845 2845      uint32_t data_len, uint32_t *rx_data_len)
2846 2846  {
2847 2847          iscsi_sess_t    *isp;
2848 2848          iscsi_cmd_t     *icmdp;
2849 2849          iscsi_status_t  rval    = ISCSI_STATUS_SUCCESS;
2850 2850  
2851 2851          ASSERT(icp != NULL);
2852 2852          ASSERT(buf != NULL);
2853 2853          ASSERT(rx_data_len != NULL);
2854 2854  
2855 2855          isp = icp->conn_sess;
2856 2856          ASSERT(isp != NULL);
2857 2857  
2858 2858          /*
2859 2859           * Ensure data for text request command is not greater
2860 2860           * than the negotiated maximum receive data seqment length.
2861 2861           *
2862 2862           * Although iSCSI allows for long text requests (multiple
2863 2863           * pdus), this function places a restriction on text
2864 2864           * requests to ensure it is handled by a single PDU.
2865 2865           */
2866 2866          if (data_len > icp->conn_params.max_xmit_data_seg_len) {
2867 2867                  return (ISCSI_STATUS_CMD_FAILED);
2868 2868          }
2869 2869  
2870 2870          icmdp = iscsi_cmd_alloc(icp, KM_SLEEP);
2871 2871          ASSERT(icmdp != NULL);
2872 2872  
2873 2873          icmdp->cmd_type         = ISCSI_CMD_TYPE_TEXT;
2874 2874          icmdp->cmd_result       = ISCSI_STATUS_SUCCESS;
2875 2875          icmdp->cmd_misc_flags   &= ~ISCSI_CMD_MISCFLAG_FREE;
2876 2876          icmdp->cmd_completed    = B_FALSE;
2877 2877  
2878 2878          icmdp->cmd_un.text.buf          = buf;
2879 2879          icmdp->cmd_un.text.buf_len      = buf_len;
2880 2880          icmdp->cmd_un.text.offset       = 0;
2881 2881          icmdp->cmd_un.text.data_len     = data_len;
2882 2882          icmdp->cmd_un.text.total_rx_len = 0;
2883 2883          icmdp->cmd_un.text.ttt          = ISCSI_RSVD_TASK_TAG;
2884 2884          icmdp->cmd_un.text.stage        = ISCSI_CMD_TEXT_INITIAL_REQ;
2885 2885  
2886 2886  long_text_response:
2887 2887          rw_enter(&isp->sess_state_rwlock, RW_READER);
2888 2888          if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
2889 2889                  iscsi_cmd_free(icmdp);
2890 2890                  rw_exit(&isp->sess_state_rwlock);
2891 2891                  return (ISCSI_STATUS_NO_CONN_LOGGED_IN);
2892 2892          }
2893 2893  
2894 2894          mutex_enter(&isp->sess_queue_pending.mutex);
2895 2895          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
2896 2896          mutex_exit(&isp->sess_queue_pending.mutex);
2897 2897          rw_exit(&isp->sess_state_rwlock);
2898 2898  
2899 2899          /* stall until completed */
2900 2900          mutex_enter(&icmdp->cmd_mutex);
2901 2901          while (icmdp->cmd_completed == B_FALSE) {
2902 2902                  cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
2903 2903          }
2904 2904          mutex_exit(&icmdp->cmd_mutex);
2905 2905  
2906 2906          /*
2907 2907           * check if error occured.  If data overflow occured, continue on
2908 2908           * to ensure we get all data so that the full data length can be
2909 2909           * returned to the user
2910 2910           */
2911 2911          if ((icmdp->cmd_result != ISCSI_STATUS_SUCCESS) &&
2912 2912              (icmdp->cmd_result != ISCSI_STATUS_DATA_OVERFLOW)) {
2913 2913                  cmn_err(CE_NOTE, "iscsi: SendTarget discovery failed (%d)",
2914 2914                      icmdp->cmd_result);
2915 2915                  rval = icmdp->cmd_result;
2916 2916                  iscsi_cmd_free(icmdp);
2917 2917                  return (rval);
2918 2918          }
2919 2919  
2920 2920          /* check if this was a partial text PDU  */
2921 2921          if (icmdp->cmd_un.text.stage != ISCSI_CMD_TEXT_FINAL_RSP) {
2922 2922                  /*
2923 2923                   * If a paritial text rexponse received, send an empty
2924 2924                   * text request.  This follows the behaviour specified
2925 2925                   * in RFC3720 regarding long text responses.
2926 2926                   */
2927 2927                  icmdp->cmd_misc_flags           &= ~ISCSI_CMD_MISCFLAG_FREE;
2928 2928                  icmdp->cmd_completed            = B_FALSE;
2929 2929                  icmdp->cmd_un.text.data_len     = 0;
2930 2930                  icmdp->cmd_un.text.stage        = ISCSI_CMD_TEXT_CONTINUATION;
2931 2931                  goto long_text_response;
2932 2932          }
2933 2933  
2934 2934          /*
2935 2935           * set total received data length.  If data overflow this would be
2936 2936           * amount of data that would have been received if buffer large
2937 2937           * enough.
2938 2938           */
2939 2939          *rx_data_len = icmdp->cmd_un.text.total_rx_len;
2940 2940  
2941 2941          /* copy rval */
2942 2942          rval = icmdp->cmd_result;
2943 2943  
2944 2944          /* clean up  */
2945 2945          iscsi_cmd_free(icmdp);
2946 2946  
2947 2947          return (rval);
2948 2948  }
2949 2949  
2950 2950  /*
2951 2951   * iscsi_handle_passthru - This function is used to send a uscsi_cmd
2952 2952   * to a specific target lun.  This routine is used for internal purposes
2953 2953   * during enumeration and via the ISCSI_USCSICMD IOCTL.  We restrict
2954 2954   * the CDBs that can be issued to a target/lun to INQUIRY, REPORT_LUNS,
2955 2955   * and READ_CAPACITY for security purposes.
2956 2956   *
2957 2957   * The logic here is broken into three phases.
2958 2958   * 1) Allocate and initialize a pkt/icmdp
2959 2959   * 2) Send the pkt/icmdp
2960 2960   * 3) cv_wait for completion
2961 2961   */
2962 2962  iscsi_status_t
2963 2963  iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun, struct uscsi_cmd *ucmdp)
2964 2964  {
2965 2965          iscsi_status_t          rval;
2966 2966          iscsi_cmd_t             *icmdp;
2967 2967          struct scsi_pkt         *pkt;
2968 2968          struct buf              *bp;
2969 2969          struct scsi_arq_status  *arqstat;
2970 2970          int                     statuslen;
2971 2971  
2972 2972          ASSERT(isp != NULL);
2973 2973          ASSERT(ucmdp != NULL);
2974 2974  
2975 2975          if (ucmdp->uscsi_rqlen > SENSE_LENGTH) {
2976 2976                  /*
2977 2977                   * The caller provided sense buffer large enough for additional
2978 2978                   * sense bytes. We need to allocate pkt_scbp to fit them there
2979 2979                   * too.
2980 2980                   */
2981 2981                  statuslen = ucmdp->uscsi_rqlen + ISCSI_ARQ_STATUS_NOSENSE_LEN;
2982 2982          } else {
2983 2983                  /* The default size of pkt_scbp */
2984 2984                  statuslen = sizeof (struct scsi_arq_status);
2985 2985          }
2986 2986  
2987 2987          /*
2988 2988           * Step 1. Setup structs - KM_SLEEP will always succeed
2989 2989           */
2990 2990          bp = kmem_zalloc(sizeof (struct buf), KM_SLEEP);
2991 2991          ASSERT(bp != NULL);
2992 2992          pkt = kmem_zalloc(sizeof (struct scsi_pkt), KM_SLEEP);
2993 2993          ASSERT(pkt != NULL);
2994 2994          icmdp = iscsi_cmd_alloc(NULL, KM_SLEEP);
2995 2995          ASSERT(icmdp != NULL);
2996 2996  
2997 2997          /* setup bp structure */
2998 2998          bp->b_flags             = B_READ;
2999 2999          bp->b_bcount            = ucmdp->uscsi_buflen;
3000 3000          bp->b_un.b_addr         = ucmdp->uscsi_bufaddr;
3001 3001  
3002 3002          /* setup scsi_pkt structure */
3003 3003          pkt->pkt_ha_private     = icmdp;
3004 3004          pkt->pkt_scbp           = kmem_zalloc(statuslen, KM_SLEEP);
3005 3005          pkt->pkt_cdbp           = kmem_zalloc(ucmdp->uscsi_cdblen, KM_SLEEP);
3006 3006          /* callback routine for passthru, will wake cv_wait */
3007 3007          pkt->pkt_comp           = iscsi_handle_passthru_callback;
3008 3008          pkt->pkt_time           = ucmdp->uscsi_timeout;
3009 3009  
3010 3010          /* setup iscsi_cmd structure */
3011 3011          icmdp->cmd_lun                  = NULL;
3012 3012          icmdp->cmd_type                 = ISCSI_CMD_TYPE_SCSI;
3013 3013          icmdp->cmd_un.scsi.lun          = lun;
3014 3014          icmdp->cmd_un.scsi.pkt          = pkt;
3015 3015          icmdp->cmd_un.scsi.bp           = bp;
3016 3016          bcopy(ucmdp->uscsi_cdb, pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3017 3017          icmdp->cmd_un.scsi.cmdlen       = ucmdp->uscsi_cdblen;
3018 3018          icmdp->cmd_un.scsi.statuslen    = statuslen;
3019 3019          icmdp->cmd_crc_error_seen       = B_FALSE;
3020 3020          icmdp->cmd_completed            = B_FALSE;
3021 3021          icmdp->cmd_result               = ISCSI_STATUS_SUCCESS;
3022 3022  
3023 3023          /*
3024 3024           * Step 2. Push IO onto pending queue.  If we aren't in
3025 3025           * FULL_FEATURE we need to fail the IO.
3026 3026           */
3027 3027          rw_enter(&isp->sess_state_rwlock, RW_READER);
3028 3028          if (!ISCSI_SESS_STATE_FULL_FEATURE(isp->sess_state)) {
3029 3029                  rw_exit(&isp->sess_state_rwlock);
3030 3030  
3031 3031                  iscsi_cmd_free(icmdp);
3032 3032                  kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3033 3033                  kmem_free(pkt->pkt_scbp, statuslen);
3034 3034                  kmem_free(pkt, sizeof (struct scsi_pkt));
3035 3035                  kmem_free(bp, sizeof (struct buf));
3036 3036  
3037 3037                  return (ISCSI_STATUS_CMD_FAILED);
3038 3038          }
3039 3039  
3040 3040          mutex_enter(&isp->sess_queue_pending.mutex);
3041 3041          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E1, isp);
3042 3042          mutex_exit(&isp->sess_queue_pending.mutex);
3043 3043          rw_exit(&isp->sess_state_rwlock);
3044 3044  
3045 3045          /*
3046 3046           * Step 3. Wait on cv_wait for completion routine
3047 3047           */
3048 3048          mutex_enter(&icmdp->cmd_mutex);
3049 3049          while (icmdp->cmd_completed == B_FALSE) {
3050 3050                  cv_wait(&icmdp->cmd_completion, &icmdp->cmd_mutex);
3051 3051          }
3052 3052          mutex_exit(&icmdp->cmd_mutex);
3053 3053  
3054 3054          /* copy rval */
3055 3055          rval = icmdp->cmd_result;
3056 3056  
3057 3057          ucmdp->uscsi_resid = pkt->pkt_resid;
3058 3058  
3059 3059          /* update scsi status */
3060 3060          arqstat = (struct scsi_arq_status *)pkt->pkt_scbp;
3061 3061          ucmdp->uscsi_status = ((char *)&arqstat->sts_status)[0];
3062 3062  
3063 3063          /* copy request sense buffers if caller gave space */
3064 3064          if ((ucmdp->uscsi_rqlen > 0) &&
3065 3065              (ucmdp->uscsi_rqbuf != NULL)) {
3066 3066                  ASSERT(ucmdp->uscsi_rqlen >= arqstat->sts_rqpkt_resid);
3067 3067                  ucmdp->uscsi_rqresid = arqstat->sts_rqpkt_resid;
3068 3068                  bcopy(&arqstat->sts_sensedata, ucmdp->uscsi_rqbuf,
3069 3069                      ucmdp->uscsi_rqlen - arqstat->sts_rqpkt_resid);
3070 3070          }
3071 3071  
3072 3072          if ((ucmdp->uscsi_status == STATUS_CHECK) &&
3073 3073              ((icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_INTERNAL)) == B_TRUE) {
3074 3074                  /*
3075 3075                   * Internal SCSI commands received status
3076 3076                   */
3077 3077                  (void) iscsi_decode_sense(
3078 3078                      (uint8_t *)&arqstat->sts_sensedata, icmdp);
3079 3079          }
3080 3080  
3081 3081          /* clean up */
3082 3082          iscsi_cmd_free(icmdp);
3083 3083          kmem_free(pkt->pkt_cdbp, ucmdp->uscsi_cdblen);
3084 3084          kmem_free(pkt->pkt_scbp, statuslen);
3085 3085          kmem_free(pkt, sizeof (struct scsi_pkt));
3086 3086          kmem_free(bp, sizeof (struct buf));
3087 3087  
3088 3088          return (rval);
3089 3089  }
3090 3090  
3091 3091  
3092 3092  /*
3093 3093   * iscsi_handle_passthru_callback -
3094 3094   *
3095 3095   */
3096 3096  static void
3097 3097  iscsi_handle_passthru_callback(struct scsi_pkt *pkt)
3098 3098  {
3099 3099          iscsi_cmd_t             *icmdp  = NULL;
3100 3100  
3101 3101          ASSERT(pkt != NULL);
3102 3102          icmdp = (iscsi_cmd_t *)pkt->pkt_ha_private;
3103 3103          ASSERT(icmdp != NULL);
3104 3104  
3105 3105          mutex_enter(&icmdp->cmd_mutex);
3106 3106          icmdp->cmd_completed    = B_TRUE;
3107 3107          icmdp->cmd_result       = ISCSI_STATUS_SUCCESS;
3108 3108          cv_broadcast(&icmdp->cmd_completion);
3109 3109          mutex_exit(&icmdp->cmd_mutex);
3110 3110  
3111 3111  }
3112 3112  
3113 3113  /*
3114 3114   * IDM callbacks
3115 3115   */
3116 3116  void
3117 3117  iscsi_build_hdr(idm_task_t *idm_task, idm_pdu_t *pdu, uint8_t opcode)
3118 3118  {
3119 3119          iscsi_cmd_t *icmdp = idm_task->idt_private;
3120 3120          iscsi_conn_t *icp = icmdp->cmd_conn;
3121 3121          iscsi_data_hdr_t *ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
3122 3122  
3123 3123          mutex_enter(&icmdp->cmd_mutex);
3124 3124          if (opcode == ISCSI_OP_SCSI_DATA) {
3125 3125                  uint32_t        data_sn;
3126 3126                  uint32_t        lun;
3127 3127                  icmdp = idm_task->idt_private;
3128 3128                  icp = icmdp->cmd_conn;
3129 3129                  ihp->opcode     = opcode;
3130 3130                  ihp->itt        = icmdp->cmd_itt;
3131 3131                  ihp->ttt        = idm_task->idt_r2t_ttt;
3132 3132                  ihp->expstatsn  = htonl(icp->conn_expstatsn);
3133 3133                  icp->conn_laststatsn = icp->conn_expstatsn;
3134 3134                  data_sn = ntohl(ihp->datasn);
3135 3135                  data_sn++;
3136 3136                  lun = icmdp->cmd_un.scsi.lun;
3137 3137                  ISCSI_LUN_BYTE_COPY(ihp->lun, lun);
3138 3138                  /* CRM: upate_flow_control */
3139 3139                  ISCSI_IO_LOG(CE_NOTE, "DEBUG: iscsi_build_hdr"
3140 3140                      "(ISCSI_OP_SCSI_DATA): task: %p icp: %p ic: %p itt: %x "
3141 3141                      "exp: %d data_sn: %d", (void *)idm_task, (void *)icp,
3142 3142                      (void *)icp->conn_ic, ihp->itt, icp->conn_expstatsn,
3143 3143                      data_sn);
3144 3144          } else {
3145 3145                  cmn_err(CE_WARN, "iscsi_build_hdr: unprocessed build "
3146 3146                      "header opcode: %x", opcode);
3147 3147          }
3148 3148          mutex_exit(&icmdp->cmd_mutex);
3149 3149  }
3150 3150  
3151 3151  static void
3152 3152  iscsi_process_rsp_status(iscsi_sess_t *isp, iscsi_conn_t *icp,
3153 3153      idm_status_t status)
3154 3154  {
3155 3155          switch (status) {
3156 3156          case IDM_STATUS_SUCCESS:
3157 3157                  if ((isp->sess_state == ISCSI_SESS_STATE_IN_FLUSH) &&
3158 3158                      (icp->conn_queue_active.count == 0)) {
3159 3159                          iscsi_drop_conn_cleanup(icp);
3160 3160                  }
3161 3161                  break;
3162 3162          case IDM_STATUS_PROTOCOL_ERROR:
3163 3163                  KSTAT_INC_CONN_ERR_PROTOCOL(icp);
3164 3164                  iscsi_drop_conn_cleanup(icp);
3165 3165                  break;
3166 3166          default:
3167 3167                  break;
3168 3168          }
3169 3169  }
3170 3170  
3171 3171  static void
3172 3172  iscsi_drop_conn_cleanup(iscsi_conn_t *icp) {
3173 3173          mutex_enter(&icp->conn_state_mutex);
3174 3174          idm_ini_conn_disconnect(icp->conn_ic);
3175 3175          mutex_exit(&icp->conn_state_mutex);
3176 3176  }
3177 3177  
3178 3178  void
3179 3179  iscsi_rx_error_pdu(idm_conn_t *ic, idm_pdu_t *pdu, idm_status_t status)
3180 3180  {
3181 3181          iscsi_conn_t *icp = (iscsi_conn_t *)ic->ic_handle;
3182 3182          iscsi_sess_t *isp;
3183 3183  
3184 3184          ASSERT(icp != NULL);
3185 3185          isp = icp->conn_sess;
3186 3186          ASSERT(isp != NULL);
3187 3187          iscsi_process_rsp_status(isp, icp, status);
3188 3188          idm_pdu_complete(pdu, status);
3189 3189  }
3190 3190  
3191 3191  void
3192 3192  iscsi_rx_misc_pdu(idm_conn_t *ic, idm_pdu_t *pdu)
3193 3193  {
3194 3194          iscsi_conn_t            *icp;
3195 3195          iscsi_hdr_t             *ihp    = (iscsi_hdr_t *)pdu->isp_hdr;
3196 3196          iscsi_sess_t            *isp;
3197 3197          idm_status_t            status;
3198 3198  
3199 3199          icp = ic->ic_handle;
3200 3200          isp = icp->conn_sess;
3201 3201          isp->sess_rx_lbolt = icp->conn_rx_lbolt = ddi_get_lbolt();
3202 3202          switch (ihp->opcode & ISCSI_OPCODE_MASK) {
3203 3203          case ISCSI_OP_LOGIN_RSP:
3204 3204                  status = iscsi_rx_process_login_pdu(ic, pdu);
3205 3205                  idm_pdu_complete(pdu, status);
3206 3206                  break;
3207 3207          case ISCSI_OP_LOGOUT_RSP:
3208 3208                  status = iscsi_rx_process_logout_rsp(ic, pdu);
3209 3209                  idm_pdu_complete(pdu, status);
3210 3210                  break;
3211 3211          case ISCSI_OP_REJECT_MSG:
3212 3212                  status = iscsi_rx_process_reject_rsp(ic, pdu);
3213 3213                  break;
3214 3214          case ISCSI_OP_SCSI_TASK_MGT_RSP:
3215 3215                  status = iscsi_rx_process_task_mgt_rsp(ic, pdu);
3216 3216                  idm_pdu_complete(pdu, status);
3217 3217                  break;
3218 3218          case ISCSI_OP_NOOP_IN:
3219 3219                  status = iscsi_rx_process_nop(ic, pdu);
3220 3220                  idm_pdu_complete(pdu, status);
3221 3221                  break;
3222 3222          case ISCSI_OP_ASYNC_EVENT:
3223 3223                  status = iscsi_rx_process_async_rsp(ic, pdu);
3224 3224                  break;
3225 3225          case ISCSI_OP_TEXT_RSP:
3226 3226                  status = iscsi_rx_process_text_rsp(ic, pdu);
3227 3227                  idm_pdu_complete(pdu, status);
3228 3228                  break;
3229 3229          default:
3230 3230                  cmn_err(CE_WARN, "iscsi connection(%u) protocol error "
3231 3231                      "- received misc unsupported opcode 0x%02x",
3232 3232                      icp->conn_oid, ihp->opcode);
3233 3233                  status = IDM_STATUS_PROTOCOL_ERROR;
3234 3234                  break;
3235 3235          }
3236 3236          iscsi_process_rsp_status(isp, icp, status);
3237 3237  }
3238 3238  
3239 3239  /*
3240 3240   * +--------------------------------------------------------------------+
3241 3241   * | Beginning of completion routines                                   |
3242 3242   * +--------------------------------------------------------------------+
3243 3243   */
3244 3244  
3245 3245  /*
3246 3246   * iscsi_ic_thread -
3247 3247   */
3248 3248  void
3249 3249  iscsi_ic_thread(iscsi_thread_t *thread, void *arg)
3250 3250  {
3251 3251          iscsi_sess_t    *isp = (iscsi_sess_t *)arg;
3252 3252          int             ret;
3253 3253          iscsi_queue_t   q;
3254 3254          iscsi_cmd_t     *icmdp;
3255 3255          iscsi_cmd_t     *next_icmdp;
3256 3256  
3257 3257          ASSERT(isp != NULL);
3258 3258          ASSERT(thread != NULL);
3259 3259          ASSERT(thread->signature == SIG_ISCSI_THREAD);
3260 3260  
3261 3261          for (;;) {
3262 3262  
3263 3263                  /*
3264 3264                   * We wait till iodone or somebody else wakes us up.
3265 3265                   */
3266 3266                  ret = iscsi_thread_wait(thread, -1);
3267 3267  
3268 3268                  /*
3269 3269                   * The value should never be negative since we never timeout.
3270 3270                   */
3271 3271                  ASSERT(ret >= 0);
3272 3272  
3273 3273                  q.count = 0;
3274 3274                  q.head  = NULL;
3275 3275                  q.tail  = NULL;
3276 3276                  mutex_enter(&isp->sess_queue_completion.mutex);
3277 3277                  icmdp = isp->sess_queue_completion.head;
3278 3278                  while (icmdp != NULL) {
3279 3279                          next_icmdp = icmdp->cmd_next;
3280 3280                          mutex_enter(&icmdp->cmd_mutex);
3281 3281                          /*
3282 3282                           * check if the associated r2t/abort has finished
3283 3283                           * yet.  If not, don't complete the command.
3284 3284                           */
3285 3285                          if ((icmdp->cmd_un.scsi.r2t_icmdp == NULL) &&
3286 3286                              (icmdp->cmd_un.scsi.abort_icmdp == NULL)) {
3287 3287                                  mutex_exit(&icmdp->cmd_mutex);
3288 3288                                  (void) iscsi_dequeue_cmd(&isp->
3289 3289                                      sess_queue_completion.head,
3290 3290                                      &isp->sess_queue_completion.tail,
3291 3291                                      icmdp);
3292 3292                                  --isp->sess_queue_completion.count;
3293 3293                                  iscsi_enqueue_cmd_head(&q.head,
3294 3294                                      &q.tail, icmdp);
3295 3295                          } else {
3296 3296                                  mutex_exit(&icmdp->cmd_mutex);
3297 3297                          }
3298 3298                          icmdp = next_icmdp;
3299 3299                  }
3300 3300                  mutex_exit(&isp->sess_queue_completion.mutex);
3301 3301                  icmdp = q.head;
3302 3302                  while (icmdp != NULL) {
3303 3303                          next_icmdp = icmdp->cmd_next;
3304 3304                          iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E8, isp);
3305 3305                          icmdp = next_icmdp;
3306 3306                  }
3307 3307  
3308 3308                  if (ret > 0)
3309 3309                          /* Somebody woke us up to work */
3310 3310                          continue;
3311 3311                  else
3312 3312                          /*
3313 3313                           * Somebody woke us up to kill ourselves. We will
3314 3314                           * make sure, however that the completion queue is
3315 3315                           * empty before leaving.  After we've done that it
3316 3316                           * is the originator of the signal that has to make
3317 3317                           * sure no other SCSI command is posted.
3318 3318                           */
3319 3319                          break;
3320 3320          }
3321 3321  
3322 3322  }
3323 3323  
3324 3324  /*
3325 3325   * iscsi_iodone -
3326 3326   *
3327 3327   */
3328 3328  void
3329 3329  iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp)
3330 3330  {
3331 3331          struct scsi_pkt         *pkt    = NULL;
3332 3332          struct buf              *bp     = icmdp->cmd_un.scsi.bp;
3333 3333  
3334 3334          ASSERT(isp != NULL);
3335 3335          ASSERT(icmdp != NULL);
3336 3336          pkt = icmdp->cmd_un.scsi.pkt;
3337 3337          ASSERT(pkt != NULL);
3338 3338  
3339 3339          ASSERT(icmdp->cmd_un.scsi.abort_icmdp == NULL);
3340 3340          ASSERT(icmdp->cmd_un.scsi.r2t_icmdp == NULL);
3341 3341          if (pkt->pkt_reason == CMD_CMPLT) {
3342 3342                  if (bp) {
3343 3343                          if (bp->b_flags & B_READ) {
3344 3344                                  KSTAT_SESS_RX_IO_DONE(isp, bp->b_bcount);
3345 3345                          } else {
3346 3346                                  KSTAT_SESS_TX_IO_DONE(isp, bp->b_bcount);
3347 3347                          }
3348 3348                  }
3349 3349          }
3350 3350  
3351 3351          if (pkt->pkt_flags & FLAG_NOINTR) {
3352 3352                  cv_broadcast(&icmdp->cmd_completion);
3353 3353                  mutex_exit(&icmdp->cmd_mutex);
3354 3354          } else {
3355 3355                  /*
3356 3356                   * Release mutex.  As soon as callback is
3357 3357                   * issued the caller may destroy the command.
3358 3358                   */
3359 3359                  mutex_exit(&icmdp->cmd_mutex);
3360 3360                  /*
3361 3361                   * We can't just directly call the pk_comp routine.  In
3362 3362                   * many error cases the target driver will use the calling
3363 3363                   * thread to re-drive error handling (reset, retries...)
3364 3364                   * back into the hba driver (iscsi).  If the target redrives
3365 3365                   * a reset back into the iscsi driver off this thead we have
3366 3366                   * a chance of deadlocking. So instead use the io completion
3367 3367                   * thread.
3368 3368                   */
3369 3369                  (*icmdp->cmd_un.scsi.pkt->pkt_comp)(icmdp->cmd_un.scsi.pkt);
3370 3370          }
3371 3371  }
3372 3372  
3373 3373  /*
3374 3374   * +--------------------------------------------------------------------+
3375 3375   * | End of completion routines                                         |
3376 3376   * +--------------------------------------------------------------------+
3377 3377   */
3378 3378  
3379 3379  /*
3380 3380   * +--------------------------------------------------------------------+
3381 3381   * | Beginning of watchdog routines                                     |
3382 3382   * +--------------------------------------------------------------------+
3383 3383   */
3384 3384  
3385 3385  /*
3386 3386   * iscsi_watchdog_thread -
3387 3387   *
3388 3388   */
3389 3389  void
3390 3390  iscsi_wd_thread(iscsi_thread_t *thread, void *arg)
3391 3391  {
3392 3392          iscsi_sess_t    *isp = (iscsi_sess_t *)arg;
3393 3393          int             rc = 1;
3394 3394  
3395 3395          ASSERT(isp != NULL);
3396 3396  
3397 3397          while (rc != NULL) {
3398 3398  
3399 3399                  iscsi_timeout_checks(isp);
3400 3400                  iscsi_nop_checks(isp);
3401 3401  
3402 3402                  rc = iscsi_thread_wait(thread, SEC_TO_TICK(1));
3403 3403          }
3404 3404  }
3405 3405  
3406 3406  /*
3407 3407   * iscsi_timeout_checks -
3408 3408   *
3409 3409   */
3410 3410  static void
3411 3411  iscsi_timeout_checks(iscsi_sess_t *isp)
3412 3412  {
3413 3413          clock_t         now = ddi_get_lbolt();
3414 3414          iscsi_conn_t    *icp;
3415 3415          iscsi_cmd_t     *icmdp, *nicmdp;
3416 3416  
3417 3417          ASSERT(isp != NULL);
3418 3418  
3419 3419          /* PENDING */
3420 3420          rw_enter(&isp->sess_state_rwlock, RW_READER);
3421 3421          mutex_enter(&isp->sess_queue_pending.mutex);
3422 3422          for (icmdp = isp->sess_queue_pending.head;
3423 3423              icmdp; icmdp = nicmdp) {
3424 3424                  nicmdp = icmdp->cmd_next;
3425 3425  
3426 3426                  /* Skip entries with no timeout */
3427 3427                  if (icmdp->cmd_lbolt_timeout == 0)
3428 3428                          continue;
3429 3429  
3430 3430                  /*
3431 3431                   * Skip pending queue entries for cmd_type values that depend
3432 3432                   * on having an open cmdsn window for successfull transition
3433 3433                   * from pending to the active (i.e. ones that depend on
3434 3434                   * sess_cmdsn .vs. sess_maxcmdsn). For them, the timer starts
3435 3435                   * when they are successfully moved to the active queue by
3436 3436                   * iscsi_cmd_state_pending() code.
3437 3437                   */
3438 3438                  /*
3439 3439                   * If the cmd is stuck, at least give it a chance
3440 3440                   * to timeout
3441 3441                   */
3442 3442                  if (((icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) ||
3443 3443                      (icmdp->cmd_type == ISCSI_CMD_TYPE_TEXT)) &&
3444 3444                      !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_STUCK))
3445 3445                          continue;
3446 3446  
3447 3447                  /* Skip if timeout still in the future */
3448 3448                  if (now <= icmdp->cmd_lbolt_timeout)
3449 3449                          continue;
3450 3450  
3451 3451                  /* timeout */
3452 3452                  iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E6, isp);
3453 3453          }
3454 3454          mutex_exit(&isp->sess_queue_pending.mutex);
3455 3455          rw_exit(&isp->sess_state_rwlock);
3456 3456  
3457 3457          rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3458 3458          icp = isp->sess_conn_list;
3459 3459          while (icp != NULL) {
3460 3460  
3461 3461                  icp->conn_timeout = B_FALSE;
3462 3462                  /* ACTIVE */
3463 3463                  mutex_enter(&icp->conn_state_mutex);
3464 3464                  mutex_enter(&isp->sess_queue_pending.mutex);
3465 3465                  mutex_enter(&icp->conn_queue_active.mutex);
3466 3466                  for (icmdp = icp->conn_queue_active.head;
3467 3467                      icmdp; icmdp = nicmdp) {
3468 3468                          nicmdp = icmdp->cmd_next;
3469 3469  
3470 3470                          if (iscsi_nop_timeout_checks(icmdp) == B_TRUE) {
3471 3471                                  icp->conn_timeout = B_TRUE;
3472 3472                          }
3473 3473  
3474 3474                          /* Skip entries with no timeout */
3475 3475                          if (icmdp->cmd_lbolt_timeout == 0)
3476 3476                                  continue;
3477 3477  
3478 3478                          /*
3479 3479                           * Skip if command is not active or not needed
3480 3480                           * to flush.
3481 3481                           */
3482 3482                          if (icmdp->cmd_state != ISCSI_CMD_STATE_ACTIVE &&
3483 3483                              !(icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH))
3484 3484                                  continue;
3485 3485  
3486 3486                          /* Skip if timeout still in the future */
3487 3487                          if (now <= icmdp->cmd_lbolt_timeout)
3488 3488                                  continue;
3489 3489  
3490 3490                          if (icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_FLUSH) {
3491 3491                                  /*
3492 3492                                   * This command is left during target reset,
3493 3493                                   * we can flush it now.
3494 3494                                   */
3495 3495                                  iscsi_cmd_state_machine(icmdp,
3496 3496                                      ISCSI_CMD_EVENT_E7, isp);
3497 3497                          } else if (icmdp->cmd_state == ISCSI_CMD_STATE_ACTIVE) {
3498 3498                                  /* timeout */
3499 3499                                  iscsi_cmd_state_machine(icmdp,
3500 3500                                      ISCSI_CMD_EVENT_E6, isp);
3501 3501                          }
3502 3502  
  
    | 
      ↓ open down ↓ | 
    3468 lines elided | 
    
      ↑ open up ↑ | 
  
3503 3503                  }
3504 3504                  mutex_exit(&icp->conn_queue_active.mutex);
3505 3505                  mutex_exit(&isp->sess_queue_pending.mutex);
3506 3506                  mutex_exit(&icp->conn_state_mutex);
3507 3507  
3508 3508                  icp = icp->conn_next;
3509 3509          }
3510 3510  
3511 3511          icp = isp->sess_conn_list;
3512 3512          while (icp != NULL) {
3513      -                if (icp->conn_timeout == B_TRUE) {
     3513 +                mutex_enter(&icp->conn_state_mutex);
     3514 +                if ((icp->conn_timeout == B_TRUE) &&
     3515 +                    (icp->conn_state_idm_connected == B_TRUE)) {
3514 3516                          /* timeout on this connect detected */
3515 3517                          idm_ini_conn_disconnect(icp->conn_ic);
3516 3518                          icp->conn_timeout = B_FALSE;
3517 3519                  }
     3520 +                mutex_exit(&icp->conn_state_mutex);
3518 3521                  icp = icp->conn_next;
3519 3522          }
3520 3523          rw_exit(&isp->sess_conn_list_rwlock);
3521 3524  }
3522 3525  
3523 3526  /*
3524 3527   * iscsi_nop_checks - sends a NOP on idle connections
3525 3528   *
3526 3529   * This function walks the connections on a session and
3527 3530   * issues NOPs on those connections that are in FULL
3528 3531   * FEATURE mode and have not received data for the
3529 3532   * time period specified by iscsi_nop_delay (global).
3530 3533   */
3531 3534  static void
3532 3535  iscsi_nop_checks(iscsi_sess_t *isp)
3533 3536  {
3534 3537          iscsi_conn_t    *icp;
3535 3538  
3536 3539          ASSERT(isp != NULL);
3537 3540  
3538 3541          if (isp->sess_type == ISCSI_SESS_TYPE_DISCOVERY) {
3539 3542                  return;
3540 3543          }
3541 3544  
3542 3545          rw_enter(&isp->sess_conn_list_rwlock, RW_READER);
3543 3546          icp = isp->sess_conn_act;
3544 3547          if (icp != NULL) {
3545 3548  
3546 3549                  mutex_enter(&icp->conn_state_mutex);
3547 3550                  if ((ISCSI_CONN_STATE_FULL_FEATURE(icp->conn_state)) &&
3548 3551                      (ddi_get_lbolt() > isp->sess_conn_act->conn_rx_lbolt +
3549 3552                      SEC_TO_TICK(iscsi_nop_delay)) && (ddi_get_lbolt() >
3550 3553                      isp->sess_conn_act->conn_nop_lbolt +
3551 3554                      SEC_TO_TICK(iscsi_nop_delay))) {
3552 3555  
3553 3556                          /*
3554 3557                           * We haven't received anything from the
3555 3558                           * target is a defined period of time,
3556 3559                           * send NOP to see if the target is alive.
3557 3560                           */
3558 3561                          mutex_enter(&isp->sess_queue_pending.mutex);
3559 3562                          iscsi_handle_nop(isp->sess_conn_act,
3560 3563                              0, ISCSI_RSVD_TASK_TAG);
3561 3564                          mutex_exit(&isp->sess_queue_pending.mutex);
3562 3565                  }
3563 3566                  mutex_exit(&icp->conn_state_mutex);
3564 3567  
3565 3568                  icp = icp->conn_next;
3566 3569          }
3567 3570          rw_exit(&isp->sess_conn_list_rwlock);
3568 3571  }
3569 3572  
3570 3573  static boolean_t
3571 3574  iscsi_nop_timeout_checks(iscsi_cmd_t *icmdp)
3572 3575  {
3573 3576          if (icmdp->cmd_type == ISCSI_CMD_TYPE_NOP) {
3574 3577                  if ((ddi_get_lbolt() - icmdp->cmd_lbolt_active) >
3575 3578                      SEC_TO_TICK(ISCSI_CONN_TIEMOUT_DETECT)) {
3576 3579                          return (B_TRUE);
3577 3580                  } else {
3578 3581                          return (B_FALSE);
3579 3582                  }
3580 3583          }
3581 3584          return (B_FALSE);
3582 3585  }
3583 3586  /*
3584 3587   * +--------------------------------------------------------------------+
3585 3588   * | End of wd routines                                         |
3586 3589   * +--------------------------------------------------------------------+
3587 3590   */
3588 3591  
3589 3592  /*
3590 3593   * iscsi_flush_cmd_after_reset - flush commands after reset
3591 3594   *
3592 3595   * Here we will flush all the commands for a specified LUN whose cmdsn is less
3593 3596   * than the one received with the Unit Attention.
3594 3597   */
3595 3598  static void
3596 3599  iscsi_flush_cmd_after_reset(uint32_t cmd_sn, uint16_t lun_num,
3597 3600      iscsi_conn_t *icp)
3598 3601  {
3599 3602          iscsi_cmd_t     *t_icmdp    = NULL;
3600 3603          iscsi_cmd_t     *next_icmdp = NULL;
3601 3604  
3602 3605          ASSERT(icp != NULL);
3603 3606  
3604 3607          t_icmdp = icp->conn_queue_active.head;
3605 3608          while (t_icmdp != NULL) {
3606 3609                  next_icmdp = t_icmdp->cmd_next;
3607 3610                  mutex_enter(&t_icmdp->cmd_mutex);
3608 3611                  /*
3609 3612                   * We will flush the commands whose cmdsn is less than the one
3610 3613                   * got Unit Attention.
3611 3614                   * Here we will check for wrap by subtracting and compare to
3612 3615                   * 1/2 of a 32 bit number, if greater then we wrapped.
3613 3616                   */
3614 3617                  if ((t_icmdp->cmd_misc_flags & ISCSI_CMD_MISCFLAG_SENT) &&
3615 3618                      ((cmd_sn > t_icmdp->cmd_sn) ||
3616 3619                      ((t_icmdp->cmd_sn - cmd_sn) >
3617 3620                      ISCSI_CMD_SN_WRAP))) {
3618 3621                          /*
3619 3622                           * Internally generated SCSI commands do not have
3620 3623                           * t_icmdp->cmd_lun set, but the LUN can be retrieved
3621 3624                           * from t_icmdp->cmd_un.scsi.lun.
3622 3625                           */
3623 3626                          if ((t_icmdp->cmd_lun != NULL &&
3624 3627                              t_icmdp->cmd_lun->lun_num == lun_num) ||
3625 3628                              (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI &&
3626 3629                              (t_icmdp->cmd_un.scsi.lun & ISCSI_LUN_MASK) ==
3627 3630                              lun_num)) {
3628 3631                                  t_icmdp->cmd_misc_flags |=
3629 3632                                      ISCSI_CMD_MISCFLAG_FLUSH;
3630 3633                                  if (t_icmdp->cmd_type == ISCSI_CMD_TYPE_SCSI) {
3631 3634                                          t_icmdp->cmd_un.scsi.pkt_stat |=
3632 3635                                              STAT_BUS_RESET;
3633 3636                                  }
3634 3637                          }
3635 3638                  }
3636 3639                  mutex_exit(&t_icmdp->cmd_mutex);
3637 3640                  t_icmdp = next_icmdp;
3638 3641          }
3639 3642  }
3640 3643  
3641 3644  /*
3642 3645   * iscsi_decode_sense - decode the sense data in the cmd response
3643 3646   * and take proper actions
3644 3647   */
3645 3648  static boolean_t
3646 3649  iscsi_decode_sense(uint8_t *sense_data, iscsi_cmd_t *icmdp)
3647 3650  {
3648 3651          uint8_t         sense_key       = 0;
3649 3652          uint8_t         asc             = 0;
3650 3653          uint8_t         ascq            = 0;
3651 3654          boolean_t       flush_io        = B_FALSE;
3652 3655          boolean_t       reconfig_lun    = B_FALSE;
3653 3656          iscsi_sess_t    *isp            = NULL;
3654 3657  
3655 3658          ASSERT(sense_data != NULL);
3656 3659  
3657 3660          isp = icmdp->cmd_conn->conn_sess;
3658 3661  
3659 3662          sense_key = scsi_sense_key(sense_data);
3660 3663          switch (sense_key) {
3661 3664                  case KEY_UNIT_ATTENTION:
3662 3665                          asc = scsi_sense_asc(sense_data);
3663 3666                          switch (asc) {
3664 3667                                  case ISCSI_SCSI_RESET_SENSE_CODE:
3665 3668                                          /*
3666 3669                                           * POWER ON, RESET, OR BUS_DEVICE RESET
3667 3670                                           * OCCURRED
3668 3671                                           */
3669 3672                                          flush_io = B_TRUE;
3670 3673                                          break;
3671 3674                                  case ISCSI_SCSI_LUNCHANGED_CODE:
3672 3675                                          ascq = scsi_sense_ascq(sense_data);
3673 3676                                          if (ascq == ISCSI_SCSI_LUNCHANGED_ASCQ)
3674 3677                                                  reconfig_lun = B_TRUE;
3675 3678                                  default:
3676 3679                                          break;
3677 3680                          }
3678 3681                          break;
3679 3682                  default:
3680 3683                          /*
3681 3684                           * Currently we don't care
3682 3685                           * about other sense key.
3683 3686                           */
3684 3687                          break;
3685 3688          }
3686 3689  
3687 3690          if (reconfig_lun == B_TRUE) {
3688 3691                  rw_enter(&isp->sess_state_rwlock, RW_READER);
3689 3692                  if ((isp->sess_state == ISCSI_SESS_STATE_LOGGED_IN) &&
3690 3693                      (iscsi_sess_enum_request(isp, B_FALSE,
3691 3694                      isp->sess_state_event_count) !=
3692 3695                      ISCSI_SESS_ENUM_SUBMITTED)) {
3693 3696                          cmn_err(CE_WARN, "Unable to commit re-enumeration for"
3694 3697                              " session(%u) %s", isp->sess_oid, isp->sess_name);
3695 3698                  }
3696 3699                  rw_exit(&isp->sess_state_rwlock);
3697 3700          }
3698 3701  
3699 3702          return (flush_io);
3700 3703  }
  
    | 
      ↓ open down ↓ | 
    173 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX