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